光谱聚类 Scikit 学习集群中的打印项目

Spectral Clustering Scikit learn print items in Cluster

我知道我可以使用 scikit-learn 使用以下代码获取 K 均值聚类中特定聚类的内容。

    order_centroids = model.cluster_centers_.argsort()[:, ::-1]
    terms = vectorizer.get_feature_names()
    for i in range(true_k):
        print "Cluster %d:" % i,
        for ind in order_centroids[i, :10]:
            print ' %s' % terms[ind],
        print

由于没有用于光谱聚类的属性“cluster_centers_”,我该如何对光谱聚类做同样的事情?我正在尝试对文本文档中的术语进行聚类。

更新: 抱歉,我第一次没有正确理解你的问题。

我认为用谱聚类不可能做你想做的事,因为谱聚类方法本身不计算任何中心,它根本不需要它们。它甚至不对原始 space 中的样本点进行操作,光谱聚类将您的数据集转换为不同的子 space,然后尝试在该数据集上聚类点。而且我不知道如何从数学上反转这个转换。

A Tutorial on Spectral Clustering

也许你应该问你的问题,因为它是关于 SO 的数学相关社区的更理论化的问题。

spectral = cluster.SpectralClustering(n_clusters=2, eigen_solver='arpack', affinity="nearest_neighbors")
spectral.fit(X)
y_pred = spectral.labels_.astype(np.int)

来自here

谱聚类不计算任何质心。在更实际的情况下,如果您确实需要一种由谱聚类算法派生的 'centroids' ,您总是可以在聚类过程结束后计算属于同一聚类的点的平均值。这些将是在典型 k-means 算法的上下文中定义的质心的近似值。同样的原则也适用于其他不产生质心的聚类算法(例如分层)。

虽然您确实无法获得光谱聚类的聚类中心,但您可以做一些接近的事情,这在某些情况下可能很有用。为了解释,我将 运行 快速通过谱聚类算法并解释修改。

首先,我们称我们的数据集为 X = {x_1, ..., x_N},其中每个点都是 d 维(d 是数据集中的特征数)。我们可以将 X 视为 N by d 矩阵。假设我们想将这些数据放入 k 个集群中。谱聚类首先将数据集转换为另一种表示,然后在数据的新表示上使用 K-means 聚类以获得聚类。首先,利用K-neighbors信息形成亲和矩阵A。为此,我们需要选择一个正整数n来构造A。如果 x_ix_j 都在彼此的顶部 n 邻居列表中,则元素 A_{i, j} 等于 1,并且 A_{i, j} 等于0 否则。 AN 乘以 N 的对称矩阵。接下来构造normalized Laplacian matrix L of A, which is L = I - D^{-1/2}AD^{-1/2}, where D is the degree matrix. Then the eigenvalue decompositionL进行运算得到L = VEV^{-1},其中VL的特征向量矩阵,E是对角线特征值为 L 的对角矩阵。由于L是半正定的,所以它的特征值都是非负实数。对于谱聚类,我们使用它来对 V 的列进行排序,以便 V 的第一列对应于 L 的最小特征值,最后一列对应于 L.

接下来,我们取 V 的前 k 列,并将它们视为 k 维 space 中的 N 点。让我们将此 t运行 分类矩阵写为 V',并将其行写为 {v'_1, ..., v'_N},其中每个 v'_ik 维。然后我们使用K-means算法将这些点聚类成k个簇; {C'_1,...,C'_k}。然后通过"pulling back"从V'X的簇将簇分配给数据集X中的点:点x_i在簇[=62中=] 当且仅当 v'_i 在簇 C'_j 中。

现在,将 X 转换为 V' 并在该表示上聚类的要点之一是 X 通常不是球形分布的,而 V' 在至少接近于如此。由于 V' 更接近球形分布,质心将是 "inside" 它定义的点簇。我们可以取 V' 中最接近每个簇的簇质心的点。我们称集群质心为 {c_1,...,c_k}。这些是参数 space 中表示 V' 的点。然后对于每个簇,选择最接近簇质心的 V' 点以获得 kV'。假设 {v'_i_1,...,v'_i_k} 是最接近 V' 的聚类质心的代表点。然后选择 {x_i_1,...,x_i_k} 作为 X.

簇的簇代表

此方法可能并不总是如您所愿,但它至少是一种更接近您想要的方法,也许您可​​以修改它以更接近您的需要。下面是一些示例代码来展示如何执行此操作。

让我们使用 scikit-learn 提供的一些假数据。

import numpy as np
import pandas as pd
from sklearn.datasets import make_moons

moons_data = make_moons(n_samples=1000, noise=0.07, random_state=0)
moons = pd.DataFrame(data=moons_data[0], columns=['x', 'y'])
moons['label_truth'] = moons_data[1]

moons.plot(
    kind='scatter',
    x='x',
    y='y',
    figsize=(8, 8),
    s=10,
    alpha=0.7
);

我要作弊并使用 scikit-learn 提供的谱聚类方法,然后从那里提取亲和力矩阵。

from sklearn.cluster import SpectralClustering

sclust = SpectralClustering(
    n_clusters=2,
    random_state=42,
    affinity='nearest_neighbors',
    n_neighbors=10,
    assign_labels='kmeans'
)

sclust.fit(moons[['x', 'y']]);

moons['label_cluster'] = sclust.labels_

moons.plot(
    kind='scatter',
    x='x',
    y='y',
    figsize=(16, 14),
    s=10,
    alpha=0.7,
    c='label_cluster',
    cmap='Spectral'
);

接下来,我们将计算亲和矩阵的归一化拉普拉斯算子,而不是计算拉普拉斯算子的整个特征值分解,我们使用 scipy 函数 eigsh 提取两个 (因为我们想要两个簇)对应于两个最小特征值的特征向量。

from scipy.sparse.csgraph import laplacian
from scipy.sparse.linalg import eigsh

affinity_matrix = sclust.affinity_matrix_
lpn = laplacian(affinity_matrix, normed=True)
w, v = eigsh(lpn, k=2, which='SM')

pd.DataFrame(v).plot(
    kind='scatter',
    x=0,
    y=1,
    figsize=(16, 16),
    s=10,
    alpha=0.7
);

然后让我们使用 K-means 对这种新的数据表示进行聚类。让我们也找到这个新表示中最接近簇质心的两个点,并突出显示它们。

from sklearn.cluster import KMeans
from scipy.spatial.distance import euclidean
import matplotlib.pyplot as plt

kmeans = KMeans(
    n_clusters=2,
    random_state=42
)
kmeans.fit(v)
center_0, center_1 = kmeans.cluster_centers_
representative_index_0 = np.argmin(np.array([euclidean(a, center_0) for a in v]))
representative_index_1 = np.argmin(np.array([euclidean(a, center_1) for a in v]))
fig, ax = plt.subplots(figsize=(16, 16));

pd.DataFrame(v).plot(
    kind='scatter',
    x=0,
    y=1,
    ax=ax,
    s=10,
    alpha=0.7);

pd.DataFrame(v).iloc[[representative_index_0, representative_index_1]].plot(
    kind='scatter',
    x=0,
    y=1,
    ax=ax,
    s=100,
    alpha=0.9,
    c='orange',
)

最后,让我们绘制突出显示相应点的原始数据集。

moons['labels_lpn_kmeans'] = kmeans.labels_

fig, ax = plt.subplots(figsize=(16, 14));

moons.plot(
    kind='scatter',
    x='x',
    y='y',
    ax=ax,
    s=10,
    alpha=0.7,
    c='labels_lpn_kmeans',
    cmap='Spectral'
);

moons.iloc[[representative_index_0, representative_index_1]].plot(
    kind='scatter',
    x='x',
    y='y',
    ax=ax,
    s=100,
    alpha=0.9,
    c='orange',
);

如我们所见,突出显示的点可能不在我们预期的位置,但这可能有助于提供某种算法从每个集群中选择点的方法。