光谱聚类 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_i
和 x_j
都在彼此的顶部 n
邻居列表中,则元素 A_{i, j}
等于 1,并且 A_{i, j}
等于0 否则。 A
是 N
乘以 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 decomposition对L
进行运算得到L = VEV^{-1}
,其中V
是L
的特征向量矩阵,E
是对角线特征值为 L
的对角矩阵。由于L
是半正定的,所以它的特征值都是非负实数。对于谱聚类,我们使用它来对 V
的列进行排序,以便 V
的第一列对应于 L
的最小特征值,最后一列对应于 L
.
接下来,我们取 V
的前 k
列,并将它们视为 k
维 space 中的 N
点。让我们将此 t运行 分类矩阵写为 V'
,并将其行写为 {v'_1, ..., v'_N}
,其中每个 v'_i
是 k
维。然后我们使用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'
点以获得 k
点V'
。假设 {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',
);
如我们所见,突出显示的点可能不在我们预期的位置,但这可能有助于提供某种算法从每个集群中选择点的方法。
我知道我可以使用 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_i
和 x_j
都在彼此的顶部 n
邻居列表中,则元素 A_{i, j}
等于 1,并且 A_{i, j}
等于0 否则。 A
是 N
乘以 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 decomposition对L
进行运算得到L = VEV^{-1}
,其中V
是L
的特征向量矩阵,E
是对角线特征值为 L
的对角矩阵。由于L
是半正定的,所以它的特征值都是非负实数。对于谱聚类,我们使用它来对 V
的列进行排序,以便 V
的第一列对应于 L
的最小特征值,最后一列对应于 L
.
接下来,我们取 V
的前 k
列,并将它们视为 k
维 space 中的 N
点。让我们将此 t运行 分类矩阵写为 V'
,并将其行写为 {v'_1, ..., v'_N}
,其中每个 v'_i
是 k
维。然后我们使用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'
点以获得 k
点V'
。假设 {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',
);
如我们所见,突出显示的点可能不在我们预期的位置,但这可能有助于提供某种算法从每个集群中选择点的方法。