Python中的光谱聚类和多维缩放

Posted

技术标签:

【中文标题】Python中的光谱聚类和多维缩放【英文标题】:Spectral Clustering and Multi-Dimensional Scaling in Python 【发布时间】:2016-01-01 01:11:48 【问题描述】:

我使用 Spectral Clustering 对一些单词特征向量进行聚类。我在光谱聚类算法中使用了词向量的余弦相似度矩阵作为预先计算的亲和度矩阵。这就是我作为三个集群得到的。我使用集群分配作为标签来为点着色。

但是我使用了相同的余弦相似度矩阵并从中计算出距离矩阵。

dist=1-cosimilarity. 

并使用多维缩放算法来可视化 3 维空间中的点。这就是我从中得到的。我用那个实际的点标签来给点上色。

如果您看到 MDS 分组,那些没有显示任何明显的集群分组,而 Spectral 1 似乎确实显示了三个相当不错的集群。

1)。你认为原因可能是什么?因为 MDS 只是利用它们之间的距离在较低维度的尺度上绘制点(MDS 将点之间的距离以与它们在较高维度上的距离相同的比例减少,从而保持点之间距离的比例相同)而不是使用一些距离标准对它们进行聚类?我希望看到光谱结果与 MDS 有点相似,因为两者都使用距离测量。只是这种聚类正在将附近的点融合为一个。当 MDS 按原样绘制时。但在 MDS 中,我使用了点的实际标签。所以这表明了基本事实?

2)。有什么建议可以使用其他算法改进集群,或者这看起来不错?

编辑:

似乎有三个组,但红色与蓝色和绿色组重叠。但是,如果我说它在我们看来是重叠的,因为我们无法看到 3D 之外的东西(在计算机屏幕上无论如何都是 2D)。如果我们碰巧在 3D 甚至更多维度中看到红点,它们会远高于蓝色和绿色会怎样。

举个例子:

假设您正在查看三点。

想象一下,如果您寻找 1D,您在上面看到的点就会出现在您面前。也许就在上面。

现在,如果您在 2D 中看到这些点会怎样。它如下所示。

如果您现在看到,所有三个点看起来都是分开的。只是我们能够看到 2D 中的点,我们实际上能够看到点之间的关系,当从顶部和 1D 中可视化时,这些点在我们看来是直线。

那么,如果我们能够以 3D 形式将它们可视化,那么您是否认为像上面这样的聚类结果实际上可能是一组明显分离的点,并且与现实中的每个组相距很远,而我们目前似乎没有很好地分离? .这是否意味着可能存在上述情况,聚类结果的可视化可能不是正确的方法,因为它可能会导致上述结论?

编辑二:

使用以下代码运行 DBSCAN 算法:使用之前计算的距离矩阵作为 DBSCAN 的预计算矩阵

from sklearn.cluster import DBSCAN
    dbscan=DBSCAN(metric='precomputed')
    cluster_labels=dbscan.fit_predict(dist)

请记住,在所有光谱和 DBSCAN 中,我绘制的点是多维缩放算法到三个维度的结果。

DBSCAN 图:

编辑三:

相似度和距离矩阵的计算:

 from sklearn.metrics.pairwise import cosine_similarity

    cossim= cosine_similarity(X)

    dist=1-cossim

    dist=np.round(dist, 2)

编辑四:

由于 Anony-Mousse 建议余弦相似度可能不是正确的度量,所以现在我所做的只是在 DBSCAN 算法中使用了原始的词袋设计矩阵,并且没有提供任何距离矩阵作为预先计算的选项.并将其留给 sklearn 来计算正确的亲和度矩阵。现在这就是我得到的。只有一个集群。而已。它根本没有分开点。 请记住,这是与上面使用的距离矩阵相同的数据点词矩阵包。基础数据点是相同的。

编辑五:

将词袋中的计数数据转换为 tf-idf 数据。

1)。在预先计算的 tf-idf 词袋数据的距离矩阵上运行 DBSCAN。 在所有早期的方法中,我只是简单地使用计数词袋矩阵作为基础。现在我使用 tf-idf 矩阵作为余弦相似度距离的基础。

距离矩阵上的 DBSCAN:

它给出了两种类型的点,但又没有分离。

原始 Tf-idf 词袋矩阵上的 DBSCAN:

只有一个红色斑点。

tf-idf数据余弦相似度矩阵的谱:

看看就好。它甚至比我在单词数据包的相似度矩阵上使用频谱时得到的结果还要糟糕。使用 tf-idf 只是把事情搞砸了。

计数数据的相似矩阵谱:

如果您看到 Spectral 在仅计数数据上完成时仍然给出一些本地分组,而在 tf-idf 数据上完成时则全部混淆。

其次,我有 4000 个功能。为了可视化,我需要在 3 个维度上做最大值。因此,我正在使用 MDS 的结果。 MDS 类似于 PCA,因此如果有人需要可视化点,则需要执行 MDS 或 PCA。

编辑 VI:

因此,根据 Anony-Mousse 的说法,MDS 搞砸了,我想为什么不尝试使用 PCA。因此,我从 DBSCAN 或 Spectral 获取集群,然后从 PCA 绘制前三台 PC。这是我为 PCA 编写的代码。这里的 docs_bow 可以是 tf-idf 甚至是普通计数的 docs_bow。

def PCA(docs_bow): 
    """ This function carries out PCA of the dataset
    """

    #Doing PCA (SVD)
    U,S,Vt=np.linalg.svd(docs_bow,full_matrices=False)
    # Projection matrix with Principal Component Loading vectors. Transpose of Vt.(Right singular vectors)
    W=Vt.T
    # Keep only the top 3 Dimensions
    W=W[:,0:3]

    # Finding our Projected datapoints on those two PC's
    PC=np.dot(docs_bow,W)

    return PC

余弦矩阵上的光谱和 MDS 的绘图结果:

余弦矩阵和 PCA 的前三个 PC 上的光谱:

距离矩阵和MDS前三个维度的DBSCAN:

距离矩阵的 DBSCAN 和 PCA 的前三个 PC:

MDS 似乎比 PCA 提供更好的可视化。我不是可以用来减少维度以可视化高维数据的其他东西。

【问题讨论】:

【参考方案1】:

如果您禁用颜色,您会看到多少个簇?

我会说这个数据集中只有一个大集群,至少在这种预处理/可视化中是这样。

您从光谱聚类中获得的三个聚类毫无意义。它本质上是在做量化,但它没有发现结构。它通过将数据分成三个大小相似的块来最小化平方偏差。但是如果你再次运行它,它可能会产生相似的外观,但不同的块:结果很大程度上是随机的,抱歉。

不要期望类与集群一致。正如你在这个数据集中看到的,它可能有三个标签,但只有一个大杂乱的“集群”。

很容易产生这种效果:

from sklearn import datasets, cluster
data=datasets.make_blobs(5000, 3, 1)[0]
c=cluster.SpectralClustering(n_clusters=3).fit_predict(data)
colors = np.array([x for x in 'bgrcmykbgrcmykbgrcmykbgrcmyk'])
scatter(data[:,0],data[:,1],color=colors[c].tolist())

产生这个:

注意这与您的结果有多相似?然而,这是一个单高斯,这里没有集群。光谱聚类在这里按要求生成了 3 个聚类,但它们完全没有意义。

请务必检查您的结果是否有意义。很容易得到看起来不错的分区,但那是随机凸分区。 仅仅因为它产生了集群并不意味着集群就在那里 - k-means 和谱聚类等算法容易出现https://en.wikipedia.org/wiki/Pareidolia

你能看到这张脸上的簇吗? ;-) 是真的吗?

这是使用 MDS 对文本数据集进行的相当成功的投影。它显示了许多簇延伸到数据空间的不同方向。 K-means 和变体在这个数据集上不能很好地工作。高斯混合建模可以工作,但仅限于投影数据。

【讨论】:

我不确定我是否理解这一点。该算法将相同的聚类点标记在一起。只是他们没有很好地分开。它不像算法给出的标签点彼此不同,就像您在 MDS 中看到的图表一样。也可能是因为我们在 2d 中可视化事物,我们无法看到集群之间的差异。如果在现实中有一个空间呢 MDS 显示真实标签。 Spectral 是一个投影的 k-means,即使没有集群,它也会产生集群。生成单个 3d 高斯,并在其上运行光谱聚类。它看起来就像你得到的一样。 MDS 显示真实标签。 Spectral 是一个投影的 k-means,即使没有集群,它也会产生集群。生成单个 3d 高斯,并在其上运行光谱聚类。它看起来就像你得到的一样。 查看我添加的示例。这就是无意义集群的样子——数据只是一个单个高斯,而不是三个集群。光谱聚类产生了一个完全没有意义的结果。 好的,所以让我试着更好地理解它,如果我表现得更好奇,请原谅我。您正在强调一些有趣的事情。所以你的意思是,即使使用一个高斯分布,我们也有三个集群。那么这是否意味着光谱聚类是完全无用的算法或者它给出了错误的结果?我想了解的是为什么它对点进行局部分组(红色在一起,绿色在一起等)。通过局部分组,看起来好像有一些点彼此靠近。它不像完全分散对吧?

以上是关于Python中的光谱聚类和多维缩放的主要内容,如果未能解决你的问题,请参考以下文章

scikit-learn 谱聚类:无法找到潜伏在数据中的 NaN

谱聚类算法总结

谱聚类为啥要用到kmeans

转:完整的最简单的谱聚类python代码

谱聚类python实践

谱聚类(Spectral clustering)(python实现)