跳至主要内容

理解降维

了解降维的重要性、常用技术,以及如何将其应用于图像数据集,并在低维空间中可视化与比较数据。
· 12分钟 阅读

使用 AI 探索

降维是机器学习与数据分析中的一项强大技术,它将高维数据转换到低维空间,同时尽可能保留重要信息。高维数据指具有大量特征或变量的数据集,这类数据会给机器学习模型带来显著挑战。

在本教程中,我们将学习为何需要使用降维、常见的降维技术类型,以及如何将这些技术应用到一个简单的图像数据集。我们还会在二维空间中可视化数据,并在更低维的空间中比较图像。

如果您刚接触机器学习并希望掌握其核心概念,可以学习Become a Machine Learning Scientist in Python 职业路径,迈向机器学习科学家之路。

Understanding Dimensionality Reduction feature image

作者供图

为什么要降维?

高维数据虽然信息丰富,但往往包含冗余或无关特征,这会带来多方面问题:

  1. 维度灾难: 随着维度增加,数据点会变得稀疏,使机器学习模型更难发现模式。
  2. 过拟合: 高维数据集可能导致模型过拟合,因为模型可能学到的是噪声而非潜在模式。
  3. 计算复杂度: 维度越多,计算成本越高,会减慢训练与推理速度。
  4. 可视化困难: 超过三维的数据很难进行直观可视化,不利于理解其结构。

降维通过在保留关键信息的同时简化数据来解决这些问题。这不仅能提升模型性能,还能让数据更易解释与可视化。

线性降维与非线性降维

降维技术还可按其是否假设数据具有线性结构分为线性与非线性方法。

线性方法

线性方法假设数据位于某个线性子空间中。这类技术计算效率高,适用于数据结构本身接近线性的场景。

示例如下:

  • 主成分分析(PCA):识别能最大程度捕捉数据方差的方向(主成分)。广泛用于在尽量保留方差的情况下进行降维。
  • 线性判别分析(LDA):对分类任务尤为有用,在降维的同时保留类别可分性。

请参阅 Principal Component Analysis (PCA) in Python 教程,学习如何使用乳腺癌与 CIFAR-10 数据集在无监督设置下从数据中提取信息。

非线性方法

当数据位于非线性流形上时,使用非线性方法。这些技术更擅长刻画数据中的复杂结构。

示例如下:

  • t-SNE(t-分布随机邻域嵌入):一种流行方法,可在二维或三维中可视化高维数据,侧重保持数据点之间的局部关系。查阅我们的t-SNE 指南了解更多。
  • UMAP(统一流形近似与投影):与 t-SNE 类似,但速度更快,且更擅长保留全局结构。
  • 自编码器:使用神经网络在无监督学习下对数据进行压缩表示。

降维的类型

降维技术大致可分为两类:特征选择与特征提取。

特征选择

特征选择旨在识别并保留数据集中最相关的特征。该过程不对数据做变换,而是从原始特征中选出一个子集。

常见方法包括:

  • 过滤法(Filter):使用统计量对特征进行排序与筛选。
  • 包裹法(Wrapper):使用机器学习模型评估特征子集。
  • 嵌入法(Embedded):在模型训练过程中执行特征选择。

特征提取

特征提取(亦称特征投影)通过创建由原始特征组合而成的新特征,将数据映射到低维空间。当原始特征高度相关或存在冗余时,此方法尤为有用。

常见特征提取方法包括:

  • PCA:将数据投影到方差最大的方向。
  • LDA:专注于最大化类别可分性。
  • 非线性方法:如 t-SNE、UMAP 与自编码器,适用于数据位于非线性流形上的情况。

图像数据的降维

在本指南中,我们将学习如何在 Python 中应用降维技术。

1. 使用图像数据集

我们先导入必要的 Python 包,并从sklearn.datasets加载 digits 数据集。

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_digits
from sklearn.manifold import TSNE
from sklearn.preprocessing import StandardScaler


# Load the digits dataset
digits = load_digits()
X = digits.data   # shape (1797, 64)
y = digits.target # labels for digits (0 through 9)

print("Data shape:", X.shape)
print("Labels shape:", y.shape)

该数据集包含 1,797 张手写数字(0–9)的灰度图像,每张表示为 8x8 图像(64 个像素)。数据被展平为每张图像的 64 维特征向量。

Data shape: (1797, 64)
Labels shape: (1797,)

2. 可视化样本图像

我们现在可视化数据集中的一些样本以加深理解。使用 Matplotlib,我们会将图像重塑回原始的 8x8 网格格式进行显示。

def plot_digits(images, labels, n_rows=2, n_cols=5):
    fig, axes = plt.subplots(n_rows, n_cols, figsize=(10, 4))
    axes = axes.ravel()
    for i in range(n_rows * n_cols):
        axes[i].imshow(images[i].reshape(8, 8), cmap='gray')
        axes[i].set_title(f"Label: {labels[i]}")
        axes[i].axis('off')
    plt.tight_layout()
    plt.show()

plot_digits(X, y)

如您所见,它显示了一个图像网格,展示了 0 到 9 的灰度数字。

visualizing 0-9 digit images in gray scale.

3. 应用 t-SNE

t-SNE 是一种常用的降维技术,可在二维或三维中可视化高维数据。它对保持数据中的局部结构尤其有效。

阅读博文Introduction to t-SNE: Nonlinear Dimensionality Reduction and Data Visualization,了解如何使用非线性降维技术在低维空间中可视化高维数据。

在应用 t-SNE 之前,我们使用 StandardScaler 对数据进行缩放以归一化特征值。

scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

随后,我们选择 500 个样本进行更快的计算,并在该子集上运行 t-SNE 算法。

以下是 TSNE 函数参数的说明:

  • n_components=2:将数据降至二维。
  • perplexity=30:困惑度是 t-SNE 的关键超参数,用于在数据的局部与全局结构间取得平衡。
  • n_iter=1000:优化迭代次数。更高迭代次数有助于更好收敛,但会增加计算时间。
  • random_state=42:用于结果可复现。
n_samples = 500
X_sub = X_scaled[:n_samples]
y_sub = y[:n_samples]

tsne = TSNE(n_components=2, 
            perplexity=30, 
            n_iter=1000, 
            random_state=42)
X_tsne = tsne.fit_transform(X_sub)

print("t-SNE result shape:", X_tsne.shape)

降维已成功完成,我们现在有 500 个样本,每个样本以二维表示。

t-SNE result shape: (500, 2)

4. 可视化 t-SNE 输出

我们现在对二维 t-SNE 结果进行可视化。每个点按其数字标签着色,便于观察 t-SNE 对不同数字类别的分离效果。

plt.figure(figsize=(8, 6))
scatter = plt.scatter(X_tsne[:, 0], X_tsne[:, 1], 
                      c=y_sub, cmap='jet', alpha=0.7)
plt.colorbar(scatter, label='Digit Label')
plt.title('t-SNE (2D) of Digits Dataset (500-sample)')
plt.show()

t-SNE 将数字有效地分成了 10 个相对独立的簇,但簇间仍存在一定重叠。

Visualizing t-SNE Output

5. 在 t-SNE 空间中比较图像

为进一步探索 t-SNE 空间,我们随机选择两个点,在二维 t-SNE 空间中计算它们的欧氏距离,并可视化对应图像以观察它们的相似程度。

import random

idx1, idx2 = random.sample(range(X_tsne.shape[0]), 2)

point1, point2 = X_tsne[idx1], X_tsne[idx2]
dist_tsne = np.linalg.norm(point1 - point2)

print(f"Comparing images #{idx1} and #{idx2}")
print(f"Distance in t-SNE space: {dist_tsne:.4f}")
print(f"Label of image #{idx1}: {y_sub[idx1]}")
print(f"Label of image #{idx2}: {y_sub[idx2]}")

# Plot the original images
fig, axes = plt.subplots(1, 2, figsize=(6, 3))
axes[0].imshow(X[idx1].reshape(8, 8), cmap='gray')
axes[0].set_title(f"Label: {y_sub[idx1]}")
axes[0].axis('off')

axes[1].imshow(X[idx2].reshape(8, 8), cmap='gray')
axes[1].set_title(f"Label: {y_sub[idx2]}")
axes[1].axis('off')

plt.show()

t-SNE 空间中的距离反映了这两张图像在降至二维表示后的不相似程度。

Comparing images #291 and #90
Distance in t-SNE space: 35.7666
Label of image #291: 5
Label of image #90: 1

Visualizing digit 5 and 1

如果您在运行上述代码时遇到问题,请查看DataLab 工作区以获取进一步帮助。

结论

降维在真实应用中发挥着关键作用:它能提升模型的效率、准确性与可解释性,并有助于对复杂数据集进行更好的可视化与分析。

在本教程中,我们探讨了降维的概念、目的、方法与类型。最后,我们学习了如何使用 t-SNE 将图像数据映射到低维空间进行可视化与分析。

学习 Dimensionality Reduction in Python 课程,理解如何对数据进行降维,并掌握在 Python 中实现这些技术的方法。

降维常见问答

执行降维通常使用的两种技术是什么?

两种常用技术是 PCA 和 t-SNE。

PCA 是有监督还是无监督?

PCA 是一种无监督学习技术。

何时应使用降维?

当面对高维数据、需要降低复杂度、提升模型性能或实现可视化时应使用降维。

降维的主要目标是什么?

主要目标是在保留重要信息的同时减少特征数量。

降维有哪些现实应用场景?

应用包括文本分类、图像检索、人脸识别、神经科学与基因表达分析等。

Abid Ali Awan

作者

Abid Ali Awan

作为一名持证的数据科学家,我热衷于利用前沿技术打造创新的机器学习应用。凭借在语音识别、数据分析与报告、MLOps、对话式人工智能以及自然语言处理方面的扎实背景,我不断打磨构建智能系统的能力,力求带来切实影响。除技术专长外,我也擅长沟通,能够将复杂概念提炼为清晰、简明的表述。因此,我成为数据科学领域备受关注的博主,与不断壮大的数据专业人士社区分享洞见与实践经验。目前,我专注于内容创作与编辑,借助大语言模型打造有力且吸引人的内容,帮助企业与个人更好地发挥数据价值。

主题