以下内容将使用一个非常经典的手写数字数据集来降低维度和可视化显示。在原始数据中,手写数字的维度为64,因为其像素为64,以下内容将使用不同的算法降低到2~三维并显示。因此,2可以分别实现D可视化显示降维效果3D可视化降维效果。
文章目录
- 1. t-SNE降维效果
-
- 1.1 2D可视化
- 1.2 3D可视化
- 2. PCA降维效果
-
- 2.1 2D可视化
- 2.2 3D可视化
- 3. KernelPCA降维效果
-
- 3.1 2D可视化
- 3.2 3D可视化
- 4. MDS降维效果
-
- 4.1 2D可视化
- 4.2 3D可视化
- 5. SpectralEmbedding降维效果
-
- 5.1 2D可视化
- 5.2 3D可视化
- 6. 总结
import numpy as np import matplotlib.pyplot as plt %matplotlib inline
1. t-SNE降维效果
1.1 2D可视化
from sklearn import datasets from sklearn import preprocessing from sklearn.manifold import TSNE # 数据集导入 X, y = datasets.load_digits(return_X_y=True) # t-SNE降维处理 tsne = TSNE(n_components=2, verbose=1 ,random_state=42) result = tsne.fit_transform(X) # 归一化处理 scaler = preprocessing.MinMaxScaler(feature_range=(-1,1)) result = scaler.fit_transform(result) # 颜色设置 color = ['#FFFAFA', '#BEBEBE', '#000080', '#87CEEB', '#006400', '#00FF00', '#4682B4', '#D02090', '#8B7765', '#B03060'] # 可视化展示 plt.figure(figsize=(span class="token number">10, 10))
plt.title('t-SNE process')
# plt.xlim((-1.1, 1.1))
# plt.ylim((-1.1, 1.1))
# for i in range(len(result)):
# plt.text(result[i,0], result[i,1], str(y[i]),
# color=color[y[i]], fontdict={'weight': 'bold', 'size': 9})
plt.scatter(result[:,0], result[:,1], c=y, s=10)
输出:
[t-SNE] Computing 91 nearest neighbors...
[t-SNE] Indexed 1797 samples in 0.000s...
[t-SNE] Computed neighbors for 1797 samples in 0.116s...
[t-SNE] Computed conditional probabilities for sample 1000 / 1797
[t-SNE] Computed conditional probabilities for sample 1797 / 1797
[t-SNE] Mean sigma: 11.585657
[t-SNE] KL divergence after 250 iterations with early exaggeration: 61.555897
[t-SNE] KL divergence after 1000 iterations: 0.743767
1.2 3D可视化
from sklearn.manifold import TSNE
from sklearn import preprocessing
from sklearn import datasets
# 导入数据
X, y = datasets.load_digits(return_X_y=True)
# t-SNE降维处理
tsne = TSNE(n_components=3, verbose=1 ,random_state=42)
result = tsne.fit_transform(X)
# 归一化处理
scaler = preprocessing.MinMaxScaler(feature_range=(-1,1))
result = scaler.fit_transform(result)
# 3D可视化展示
fig = plt.figure(figsize=(14, 14))
ax = fig.add_subplot(projection='3d')
ax.set_title('t-SNE process')
ax.scatter(result[:,0], result[:,1], result[:,2] , c=y, s=10)
输出:
[t-SNE] Computing 91 nearest neighbors...
[t-SNE] Indexed 1797 samples in 0.000s...
[t-SNE] Computed neighbors for 1797 samples in 0.119s...
[t-SNE] Computed conditional probabilities for sample 1000 / 1797
[t-SNE] Computed conditional probabilities for sample 1797 / 1797
[t-SNE] Mean sigma: 11.585657
[t-SNE] KL divergence after 250 iterations with early exaggeration: 61.700397
[t-SNE] KL divergence after 1000 iterations: 0.615485
可以看见,t-SNE无论是将数据降维到2维或者是3维,其可视化的效果都是比较好的,可以明显的看出来数据之间的分布是有一定距离的。
2. PCA降维效果
2.1 2D可视化
from sklearn.decomposition import PCA from sklearn.preprocessing import MinMaxScaler from sklearn import datasets # 颜色设置 color = ['#FFFAFA', '#BEBEBE', '#000080', '#87CEEB', '#006400', '#00FF00', '#4682B4', '#D02090', '#8B7765', '#B03060'] # 导入数据 X, y = datasets.load_digits(return_X_y=True) # PCA降维(一种
矩阵分解的方法) pca = PCA(n_components=2, random_state=42) result = pca.fit_transform(X) # 归一化处理 scaler = MinMaxScaler(feature_range=(-1., 1.), copy=True) result = scaler.fit_transform(result) # 可视化展示 plt.figure(figsize=(10, 10)) plt.xlim((-1.1, 1.1)) plt.ylim((-1.1, 1.1)) plt.title('PCA process') for i in range(len(result)): plt.text(result[i,0], result[i,1], str(y[i]), color=color[y[i]], fontdict={ 'weight': 'bold', 'size': 9})
2.2 3D可视化
from sklearn.decomposition import PCA from sklearn.preprocessing import MinMaxScaler from sklearn import datasets # 颜色设置 color = ['#FFFAFA', '#BEBEBE', '#000080', '#87CEEB', '#006400', '#00FF00', '#4682B4', '#D02090', '#8B7765', '#B03060'] # 导入数据 X, y = datasets.load_digits(return_X_y=True) # PCA降维(一种矩阵分解的方法) pca = PCA(n_components=3, random_state=42) result = pca.fit_transform(X) # 归一化处理 scaler = MinMaxScaler(feature_range=(-2., 2.), copy=True) result = scaler.fit_transform(result) # 可视化展示 fig = plt.figure(figsize=(14, 14)) ax = fig.add_subplot(111, projection='3d') # 标题,范围,
标签设置 ax.set_title('PCA process') ax.set_xlim((-2.1, 2.1)) ax.set_ylim((-2.1, 2.1)) ax.set_zlim((-2.1, 2.1)) ax.set_xlabel('X') ax.set_ylabel('Y') ax.set_zlabel('Z') # 绘制散点图(直接在对应位置上画出标签值) for i in range(len(result)): ax.text(result[i, 0], result[i, 1], result[i, 2], str(y[i]), color=color[y[i]], fontdict={ 'weight': 'bold', 'size': 9})
3. KernelPCA降维效果
3.1 2D可视化
from sklearn.decomposition import KernelPCA
from sklearn.preprocessing import MinMaxScaler
# 导入数据
X, y = datasets.load_digits(return_X_y=True)
# PCA降维(一种矩阵分解的方法)
pca = KernelPCA(n_components=2, random_state=42)
result = pca.fit_transform(X)
# 归一化处理
scaler = MinMaxScaler(feature_range=(-1, 1), copy=True)
result = scaler.fit_transform(result)
# 可视化展示
plt.figure(figsize=(10, 10))
plt.title('KernelPCA process')
plt.scatter(result[:,0], result[:,1], c=y, s=10)
3.2 3D可视化
from sklearn.decomposition import KernelPCA
from sklearn.preprocessing import MinMaxScaler
from sklearn import datasets
# 颜色设置
color = ['#000000', '#BEBEBE', '#000080', '#87CEEB', '#006400',
'#00FF00', '#4682B4', '#D02090', '#8B7765', '#104E8B']
# 导入数据
X, y = datasets.load_digits(return_X_y=True)
# PCA降维(一种矩阵分解的方法)
kernel_pca = KernelPCA(n_components=3, random_state=42)
result = kernel_pca.fit_transform(X)
# 归一化处理
scaler = MinMaxScaler(feature_range=(-2., 2.), copy=True)
result = scaler.fit_transform(result)
# 可视化展示
fig = plt.figure(figsize=(14, 14))
ax = fig.add_subplot(111, projection='3d')
# 标题,范围,标签设置
ax.set_title('KernelPCA process')
ax.set_xlim((-2.1, 2.1))
ax.set_ylim((-2.1, 2.1))
ax.set_zlim((-2.1, 2.1))
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
# 绘制散点图(直接在对应位置上画出标签值)
for i in range(len(result)):
ax.text(result[i, 0], result[i, 1], result[i, 2], str(y[i]),
color=color[y[i]], fontdict={
'weight': 'bold', 'size': 9})
4. MDS降维效果
4.1 2D可视化
from sklearn.manifold import MDS
from sklearn.preprocessing import MinMaxScaler
# 导入数据
X, y = datasets.load_digits(return_X_y=True)
# 数据降维
mds = MDS(n_components=2, verbose=1, random_state=42)
result = mds.fit_transform(X)
# 归一化处理
scaler = MinMaxScaler(feature_range=(-1, 1), copy=True)
result = scaler.fit_transform(result)
# 可视化展示
plt.figure(figsize=(10, 10))
plt.title('MDS process')
plt.scatter(result[:,0], result[:,1], c=y, s=10)
4.2 3D可视化
from sklearn.manifold import MDS
from sklearn.preprocessing import MinMaxScaler
# 导入数据
X, y = datasets.load_digits(return_X_y=True)
# 数据降维
mds = MDS(n_components=3, verbose=1, random_state=42)
result = mds.fit_transform(X)
# 归一化处理
scaler = MinMaxScaler(feature_range=(-1, 1), copy=True)
result = scaler.fit_transform(result)
# 可视化展示
fig = plt.figure(figsize=(14, 14))
ax = fig.add_subplot(projection='3d')
ax.set_title('MDS process')
ax.scatter(result[:,0], result[:,1], result[:,2] , c=y, s=10)
5. SpectralEmbedding降维效果
5.1 2D可视化
from sklearn.manifold import SpectralEmbedding
from sklearn.preprocessing import MinMaxScaler
# 导入数据
X, y = datasets.load_digits(return_X_y=True)
# 数据降维
sp = SpectralEmbedding(n_components=2, random_state=42)
result = sp.fit_transform(X)
# 归一化处理
scaler = MinMaxScaler(feature_range=(-1, 1), copy=True)
result = scaler.fit_transform(result)
# 可视化展示
fig = plt.figure(figsize=(10, 10))
ax = fig.add_subplot(111)
ax.set_title('SpectralEmbedding process')
ax.scatter(result[:,0], result[:,1], c=y, s=10)
5.2 3D可视化
from sklearn.manifold import SpectralEmbedding
from sklearn.preprocessing import MinMaxScaler
# 导入数据
X, y = datasets.load_digits(return_X_y=True)
# 数据降维
sp = SpectralEmbedding(n_components=3, random_state=42)
result = sp.fit_transform(X)
# 归一化处理
scaler = MinMaxScaler(feature_range=(-1, 1), copy=True)
result = scaler.fit_transform(result)
# 可视化展示
fig = plt.figure(figsize=(10, 10))
ax = fig.add_subplot(projection='3d')
ax.set_title('SpectralEmbedding process')
ax.scatter(result[:,0], result[:,1], result[:,2] , c=y, s=10)
6. 总结
通过可视化的比较,可以明显的看得出来,t-SNE的降维效果是最好的,那么如果使用t-SNE降维后再使用一些机器学习的分类方法能否可以超越深度学习的方法呢?这里我做了一个实验,详细见:t-SNE原理介绍与对手写数字MNIST的可视化结果,最后的答案效果是不好的。
线性降维方法包括PCA、LDA时间消耗较少,但是这种线性降维方法会丢失高维空间中的非线性结构信息。相比较而言,非线性降维方法(这里没有提到KPCA和KLDA,有兴趣的可以试一试这两类非线性降维方法)中的。虽然典型的流形学习是非监督的方法,但是也存在一些有监督方法的变体。
在进行数据降维时,我们。在降维的方法的选择上,我们也要尽量平衡时间成本和降维效果。
另外,在降维时需要注意以下几点:
- 降维之前,所有特征的尺度是一致的;
- 重构误差可以用于寻找最优的输出维度𝑑d(此时降维不只是为了可视化),随着维度𝑑d的增加,重构误差将会减小,直到达到实现设定的阈值;
- 噪音点可能会导致流形出现“短路”,即原本在流形之中很容易分开的两部分被噪音点作为一个“桥梁”连接在了一起;
- 某种类型的输入数据可能导致权重矩阵是奇异的,比如在数据集有超过两个样本点是相同的,或者样本点被分在了不相交的组内。在这种情况下,特征值分解的实现solver='arpack’将找不到零空间。解决此问题的最简单的办法是使用solver='dense’实现特征值分解,虽然dense可能会比较慢,但是它可以用在奇异矩阵上。除此之外,我们也可以通过理解出现奇异的原因来思考解决的办法:如果是由于不相交集合导致,则可以尝试n_neighbors增大;如果是由于数据集中存在相同的样本点,那么可以尝试去掉这些重复的样本点,只保留其中一个。
这部分的总结来自参考资料2.
1. RGB配色表 2. 十种方法实现图像数据集降维