分享

数据降维的 7 种方法,附 Python 代码

 swordinhand 2024-04-14 发布于美国
图片

大侠幸会,在下全网同名[算法金]图片
0 基础转 AI 上岸,多个算法赛 Top
[日更万日,让更多人享受智能乐趣]



数据降维是一种通过减少数据的维度来提取最重要信息的技术,其重要性在于简化数据集、加快模型训练速度、减少存储空间需求,并帮助发现数据中的潜在结构和模式,特别适用于高维数据下的计算复杂性和过拟合问题。介绍 7 种 降维方法

1. 线性降维方法:

1.1 主成分分析(PCA) 1.2 独立成分分析(ICA) 1.3 线性判别分析(LDA) 2. 非线性降维方法:

2.1 t-分布邻域嵌入(t-SNE) 2.2 自编码器(Autoencoder) 2.3 局部线性嵌入(LLE) 3. 保持距离关系的降维方法:

3.1多维缩放(MDS)



图片

图片


1 线性降维方法
1.1 主成分分析(PCA)
是一种常用的线性降维技术,通过寻找数据中方差最大的方向,将原始高维数据映射到一个低维子空间中,以保留尽可能多的信息。
图片
下面我们使用 sklearn 里面的 PCA 工具在一组人脸数据上直观感受下,
# 导入必要的库import numpy as npimport matplotlib.pyplot as pltfrom sklearn.datasets import fetch_olivetti_facesfrom sklearn.decomposition import PCA
# 加载Olivetti人脸数据集faces_data = fetch_olivetti_faces()X = faces_data.data
# 可视化原始图像和对应的主成分n_images = 4 # 每行显示的图像数量n_rows = 4 # 总共的行数
fig, axes = plt.subplots(n_rows, 2*n_images, figsize=(16, 10), subplot_kw={'xticks':[], 'yticks':[]})
# 使用PCA降维n_components = 50 # 设置PCA保留的主成分数量pca = PCA(n_components=n_components, whiten=True, random_state=42)X_pca = pca.fit_transform(X)
for r in range(n_rows): for i in range(n_images): index = r * n_images + i
axes[r, 2*i].imshow(X[index].reshape(64, 64), cmap='gray') axes[r, 2*i].set_title(f'大侠 {index+1} 图像', fontproperties='SimHei') # 手动设置字体
axes[r, 2*i+1].imshow(pca.inverse_transform(X_pca[index]).reshape(64, 64), cmap='bone') axes[r, 2*i+1].set_title(f'大侠 {index+1} 主成分', fontproperties='SimHei') # 手动设置字体
plt.tight_layout()plt.show()

我们保留了前 50 个主成分

通过可视化对比图直观感受下,信息保留了多多少,损失了多少

通过对比图可以看到,某一张人脸的基本信息都保留了下来

如果保留 前 100 个主成分,那就更接近原始图片了

你也可以试下,保留 1 个主成分会怎样?通过保留的信息你还认得出来哪过大侠是哪过吗

图片

图片

更多 PCA 相关内容,见往期文章 PCA 主成分分析这你看不懂,我吃!

1.2 独立成分分析(ICA)
独立成分分析(ICA)是一种用于将混合信号分解为独立源信号的技术,其工作原理是通过找到最大独立性来估计源信号
特点是可以有效地分离混合信号中的独立成分,例如音频信号中的不同讲话者
经典示例是图像降噪、时间序列数据中的伪影消除或金融数据中驱动组件的识别
这儿有个有趣的示例:https://github.com/akcarsten/Independent_Component_Analysis

1.3 线性判别分析(LDA)
通过最大化类间距离和最小化类内距离,将数据投影到低维空间中,以实现数据的分类和可视化,适用于数据分类、特征提取和可视化分析等场景。
异同:LDA是一种监督学习方法,需要有数据样本的标签;PCA是一种无监督学习方法,没有标签下也能使用


import numpy as npimport matplotlib.pyplot as pltfrom sklearn.datasets import make_classification
# 设置matplotlib支持中文显示plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置中文显示plt.rcParams['axes.unicode_minus'] = False # 正确显示负号

# 生成虚拟武侠人物数据集np.random.seed(42)X, y = make_classification(n_samples=1000, n_features=4, n_informative=3, n_redundant=1, n_classes=3, n_clusters_per_class=2, random_state=42)
# 根据类别重新命名y_names = {0: '正派', 1: '中立', 2: '反派'}y_labels = np.vectorize(lambda x: y_names[x])(y)
# 创建 LDA 模型并拟合数据lda = LinearDiscriminantAnalysis(n_components=2)X_r = lda.fit(X, y).transform(X)
# 绘制降维后的数据plt.figure(figsize=(8, 6))colors = ['navy', 'turquoise', 'darkorange']lw = 2
for color, i, target_name in zip(colors, [0, 1, 2], ['正派', '中立', '反派']): plt.scatter(X_r[y == i, 0], X_r[y == i, 1], color=color, alpha=.8, lw=lw, label=target_name)
plt.legend(loc='best', shadow=False, scatterpoints=1)plt.title('LDA of Martial Arts Heroes dataset')plt.xlabel('LD1')plt.ylabel('LD2')plt.show()

图片


这个可视化结果展示了经过线性判别分析(LDA)降维后的数据在二维空间中的分布情况。
每个点代表一个虚拟武侠人物数据样本,其位置由 LDA 转换后的两个新特征(LD1 和 LD2)决定。
更多内容,见免费知识星球


图片

图片


2. 非线性降维方法

2.1 t-分布邻域嵌入(t-SNE)

t-分布邻域嵌入(t-SNE)是一种非线性降维技术,旨在将高维数据映射到二维或三维空间,保持数据点之间的局部结构,适用于可视化高维数据和发现数据中的潜在结构。

t-SNE 的工作原理是通过测量数据点之间的相似度,然后在低维空间中尽可能地保持相似度,特点是能够有效地保留数据点之间的局部结构和聚类信息,但不保持全局结构。

import numpy as npimport matplotlib.pyplot as pltfrom sklearn.datasets import load_irisfrom sklearn.manifold import TSNE
# 加载鸢尾花数据集iris = load_iris()X = iris.datay = iris.target
# 使用 t-SNE 进行降维tsne = TSNE(n_components=2, random_state=42)X_tsne = tsne.fit_transform(X)
# 绘制降维后的数据plt.figure(figsize=(8, 6))colors = ['navy', 'turquoise', 'darkorange']lw = 2
for color, i, target_name in zip(colors, [0, 1, 2], iris.target_names): plt.scatter(X_tsne[y == i, 0], X_tsne[y == i, 1], color=color, alpha=.8, lw=lw, label=target_name)
plt.legend(loc='best', shadow=False, scatterpoints=1)plt.title('t-SNE of IRIS dataset')plt.xlabel('t-SNE Component 1')plt.ylabel('t-SNE Component 2')plt.show()

图片

2.2 自编码器(Autoencoder)

一种无监督学习的技术,旨在通过学习数据的压缩表示,将高维数据映射到低维空间,适用于特征提取和数据重建。

工作原理:通过神经网络将输入数据压缩到一个低维编码,然后再解码回原始维度,使得重构误差最小化,特点是能够学习数据中的有效特征表达,适用于无监督特征学习、降噪和图像去噪等场景。

import numpy as npimport matplotlib.pyplot as pltfrom keras.datasets import mnistfrom keras.models import Modelfrom keras.layers import Input, Dense
# 加载 MNIST 数据集(X_train, _), (X_test, _) = mnist.load_data()
# 数据预处理X_train = X_train.astype('float32') / 255.X_test = X_test.astype('float32') / 255.X_train = X_train.reshape((len(X_train), np.prod(X_train.shape[1:])))X_test = X_test.reshape((len(X_test), np.prod(X_test.shape[1:])))
# 构建自编码器模型input_img = Input(shape=(784,))encoded = Dense(32, activation='relu')(input_img) # 编码层,将输入压缩到32维decoded = Dense(784, activation='sigmoid')(encoded) # 解码层,将编码结果解压缩到784维
autoencoder = Model(input_img, decoded)autoencoder.compile(optimizer='adam', loss='binary_crossentropy')
# 训练自编码器模型autoencoder.fit(X_train, X_train, epochs=50, batch_size=256, shuffle=True, validation_data=(X_test, X_test))
# 使用训练好的自编码器模型进行数据降维encoder = Model(input_img, encoded)encoded_imgs = encoder.predict(X_test)
# 可视化降维后的结果n = 10 # 可视化的数字数量plt.figure(figsize=(20, 4))for i in range(n): ax = plt.subplot(2, n, i + 1) plt.imshow(X_test[i].reshape(28, 28)) plt.gray() ax.get_xaxis().set_visible(False) ax.get_yaxis().set_visible(False)
ax = plt.subplot(2, n, i + 1 + n) plt.imshow(encoded_imgs[i].reshape(8, 4)) # 将32维的编码结果reshape为8x4的图像 plt.gray() ax.get_xaxis().set_visible(False) ax.get_yaxis().set_visible(False)plt.show()

2.3 局部线性嵌入(LLE)

一种非线性降维方法,通过保持局部数据之间的线性关系,在保留数据结构的同时将高维数据映射到低维空间,适用于保持局部结构的降维需求。

工作原理:在局部邻域内利用线性关系重建数据,通过最小化重建误差来学习数据的低维表示,特点是能够保持数据之间的局部结构和流形形状,适用于高维数据的可视化、图像处理和模式识别等场景。

import numpy as npimport matplotlib.pyplot as pltfrom sklearn.datasets import make_swiss_rollfrom sklearn.manifold import LocallyLinearEmbedding
# 设置matplotlib支持中文显示plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置中文显示plt.rcParams['axes.unicode_minus'] = False # 正确显示负号
# 生成Swiss Roll数据集X, _ = make_swiss_roll(n_samples=1000, noise=0.2, random_state=42)
# 使用局部线性嵌入进行降维lle = LocallyLinearEmbedding(n_components=2, n_neighbors=10, random_state=42)X_lle = lle.fit_transform(X)
# 绘制降维后的数据plt.figure(figsize=(8, 6))plt.scatter(X_lle[:, 0], X_lle[:, 1], c=X[:, 1], cmap='viridis')plt.colorbar(label='Swiss Roll中的高度')plt.title('局部线性嵌入(LLE)降维')plt.xlabel('新特征1')plt.ylabel('新特征2')plt.show()

图片




图片

图片


3. 保持距离关系的降维方法

3.1多维缩放(MDS)

一种用于将高维数据映射到低维空间的技术,以保持数据点之间的距离关系为目标,适用于可视化高维数据和发现数据之间的相似性。

工作原理:通过优化数据点之间的距离或相似度矩阵,将高维数据点映射到低维空间,特点是能够保持数据点之间的全局距离关系。

import numpy as npimport matplotlib.pyplot as pltfrom sklearn.datasets import load_irisfrom sklearn.manifold import MDS
# 加载鸢尾花数据集iris = load_iris()X = iris.datay = iris.target
# 使用多维缩放进行降维mds = MDS(n_components=2, random_state=42)X_mds = mds.fit_transform(X)
# 绘制降维后的数据plt.figure(figsize=(8, 6))plt.scatter(X_mds[:, 0], X_mds[:, 1], c=y, cmap='viridis')plt.colorbar(label='鸢尾花类别')plt.title('多维缩放(MDS)降维')plt.xlabel('新特征1')plt.ylabel('新特征2')plt.show()

图片

免费知识星球,欢迎加入交流



[ 抱个拳,总个结 ]

选择合适的数据降维方法取决于多个因素,包括数据类型、降维目标、计算资源和算法特点等。以下是一些考虑因素:

  • 数据类型:首先要考虑数据的类型,包括数据的维度、结构和特征类型。例如,对于结构化数据(如表格数据),主成分分析(PCA)通常是一个不错的选择;对于非线性数据或流形结构数据(如图像、文本、时间序列等),t-分布邻域嵌入(t-SNE)和局部线性嵌入(LLE)可能更适合。

  • 降维目标:确定降维的目标是重要的。有时候我们仅仅是为了可视化数据,而有时我们需要保留尽可能多的信息以便后续的机器学习任务。如果目标是可视化数据,则应选择能够有效保留数据结构和相似性的方法,如t-SNE;如果目标是尽可能保留数据的信息,则PCA可能更合适。

  • 计算资源:一些降维方法在处理大规模数据时可能需要大量的计算资源和时间。例如,t-SNE 的计算复杂度较高,对于大规模数据集可能不太适用。在这种情况下,可以考虑使用PCA或增量式的降维方法来处理大规模数据。

  • 算法特点:不同的降维方法有不同的算法特点和假设条件。例如,PCA 假设数据是线性可分的,适用于线性相关的数据;t-SNE 假设数据在高维空间中呈现流形结构,适用于非线性数据。因此,要根据数据的特点选择合适的降维方法。



[ 算法金,碎碎念 ]

图片

带小朋友去商场玩,中午在初满吃饭

点了一份拉面,面还挺好吃

其中有有一个蛋,我用筷子一夹
心里暗叫一声:不好
这个蛋怎么这么软
姐姐看出了我的心思,问:你是不是想这个蛋没弄好,咋这么软
我忙点头称是,她哈哈笑了起来,说:这叫溏心蛋,是他们家的特色
害,我那个尴尬啊。没见识,真可怕
希望今天的日更能给大家涨些见识,hhh

全网同名,日更万日,让更多人享受智能乐趣,今日 116/10000

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多