降维可视化(tSNE、UMAP、hypertools等)代码及效果对比
在机器学习和深度学习领域,特征往往是高维度的,然而不幸的是,我们的电脑屏幕是二维的,我们的人眼也只能观察最多三维,所以必须对特征进行降维之后才能可视化。
在机器学习和深度学习领域,特征往往是高维度的,然而不幸的是,我们的电脑屏幕是二维的,我们的人眼也只能观察最多三维,所以必须对特征进行降维之后才能可视化。
一、准备工作:提取MNIST在LeNet5中的特征
方法很简单,我们在第一节的代码上修改,我们取出倒数第二个全连接层的输出特征,有84维。代码如下,多输出一个emb。
def forward(self, x):
x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
x = F.max_pool2d(F.relu(self.conv2(x)), (2, 2))
x = x.view(-1, self.num_flat_features(x))
x = F.relu(self.fc1(x))
emb = F.relu(self.fc2(x))
x = self.fc3(emb)
return emb,x
然后用训练好的模型过一遍数据集,得到数据集所有样本的嵌入向量embs,同时也收集labels用于后面按类别画图:
model.eval()
embs = []
labels = []
for data, target in test_loader:
data, target = data.cuda(), target.cuda()
emb,output = model(data)
embs.append(emb.data.cpu().numpy())
labels.append(target.data.cpu().numpy())
embs = np.concatenate(embs)
labels = np.concatenate(labels)
二、使用sklearn中的t-SNE可视化
使用tSNE可视化不用更改网络结构,直接对原网络得到的输出进行处理即可,sklearn中已经封装好此功能:
from sklearn.manifold import TSNE
tsne = TSNE(n_components=2, learning_rate=200, metric='cosine',n_jobs=-1)
tsne.fit_transform(embs)
outs_2d = np.array(tsne.embedding_)
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
css4 = list(mcolors.CSS4_COLORS.keys())
#我选择了一些较清楚的颜色,更多的类时也能画清晰
color_ind = [2,7,9,10,11,13,14,16,17,19,20,21,25,28,30,31,32,37,38,40,47,51,
55,60,65,82,85,88,106,110,115,118,120,125,131,135,139,142,146,147]
css4 = [css4[v] for v in color_ind]
for lbi in range(10):
temp = outs_2d[labels==lbi]
plt.plot(temp[:,0],temp[:,1],'.',color=css4[lbi])
plt.title('feats dimensionality reduction visualization by tSNE,test data')
注意在TSNE的参数中可以指定距离类型metric,默认是euclidean,我这里使用了cosine,还可以是correlation等其他距离。
可以看出,由于随机种子的不同,每次画出来的结果不一样,每个类别的形态是大致一样的,但相对位置会有变化,这也说明tSNE在降维的时候能够保证较近的点的距离关系,但不能保证较远的点的距离关系,通常也就是类内和类间能够很好的体现,但类间的距离关系不能体现。比如黑色和红色的类在第一张图中很近,但在第二张图中很远。或者从另一个角度说,tSNE在降维的同时,也具备一定的分类能力。
三、使用hypertools中的多种降维方法
hypertools是Kaggle推出的一种降维工具包,集成了多种降维算法,如PCA、TSNE、Isomap、UMAP等。此外还有聚类算法和对齐算法等,用起来更加方便。可以用pip install hypertools安装。降维和画图的核心代码用一行搞定:
import hypertools as hyp
import matplotlib.pyplot as plt
hyp.plot(embs,'.',reduce='TSNE',ndims=2,hue=labels)
plt.title('TSNE')
注意,这个hyp.plot画的图内部也是调用matplotlib.pyplot,所以可以直接混合使用plt的命令实现更多的画图功能,如上面的plt.title()。下面给出各种降维方法的效果:
通常TSNE和UMAP两种方法可视化效果较好,其他的如PCA更多的保留了样本间距离信息的比例关系,反而看起来各类分的不是那么开,而UMAP则更极端一些,它把各类间区分的相当开。
使用hypertools也可以实现聚类,带的聚类算法有K-Means, AgglomerativeClustering, Birch, FeatureAgglomeration, SpectralClustering这几种。如果没有labels信息,可以先聚类,用聚类结果代替labels画出各簇的图:
clust = hyp.cluster(embs, cluster='KMeans',n_clusters = 10)
hyp.plot(embs,'.',reduce='TSNE',ndims=2,hue=clust)
plt.title('TSNE, clutering by KMeans')
最后说一个小细节,注意看图3的各簇中仍有一些其他簇的“噪点”,这些噪点应是TSNE分类和KMeans分类的误差造成的,这也说明图2中的噪点也不全是标注错误造成的。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)