用kmeans创建集群时,有没有办法输出每一行的失真?
Posted
技术标签:
【中文标题】用kmeans创建集群时,有没有办法输出每一行的失真?【英文标题】:Is there a way to output the distortions for each row when creating clusters with kmeans? 【发布时间】:2018-08-10 00:59:54 【问题描述】:这里有一点代码:
df_tr_std = stats.zscore(df_tr[clmns])
km = KMeans(n_clusters=3, init='k-means++',n_init=10,max_iter=300,tol=1e-04,random_state=0)
y_km = km.fit_predict(df_tr_std)
我尝试引用惯性_,但那是完全失真。以下代码用于计算各个距离:
distance = euclidean_distances(km.cluster_centers_, df_tr_std)
但它将距离分成 3 个数组(或者我创建的许多簇)。有没有办法在不按标签/集群分隔的情况下做到这一点?
我想用一列距离扩展我的原始数据集,以便我可以识别最大距离。我也想要最近的距离,但我能够使用以下代码找到:
closest, _ = pairwise_distances_argmin_min(km.cluster_centers_, df_tr_std)
【问题讨论】:
【参考方案1】:您可以做的是使用集群质心以及标签来索引到集群质心,以获取每个示例的表示方式。然后,您可以分别计算每个示例的失真。回想一下,K-Means 聚类结果的失真或惯性只是示例与其对应的代表质心之间的平方差之和。要计算单个失真值,您只需找到每个示例的代表质心,然后找到分量的平方差之和。总失真是所有这些值的总和。
因此:
cluster_centers = km.cluster_centers_
centroids = cluster_centers[y_km]
distortion = ((df_tr_std - centroids)**2.0).sum(axis=1)
第一行代码访问您拟合的 K-means 模型的聚类中心。第二行代码使用拟合结果输出的标签获取每个示例的代表性质心。对于最后一行,您可以通过减去输入的每一行或示例及其代表质心分量来计算失真,将每个元素平方,然后沿每一行求和。
在不需要临时变量的情况下,在一行中执行此操作可能很方便:
distortion = ((df_tr_std - km.cluster_centers_[y_km])**2.0).sum(axis=1)
现在为您提供每个示例的计算失真。具体来说,distortion
是一个 N,
NumPy 数组,N
是数据集中示例的数量。每个元素对应于相应示例对整体失真的贡献。
要验证,您可以检查km.inertia_
,即总失真与最后一行计算的失真数组的总和相匹配,因此请检查distortion.sum()
和km.inertia_
。
作为一个可重现的例子:
In [27]: import numpy as np
In [28]: from sklearn.cluster import KMeans
In [29]: df_tr_std = np.random.rand(1000,3)
In [30]: km = KMeans(n_clusters=3, init='k-means++',n_init=10,max_iter=300,tol=
...: 1e-04,random_state=0)
In [31]: y_km = km.fit_predict(df_tr_std)
In [32]: distortion = ((df_tr_std - km.cluster_centers_[y_km])**2.0).sum(axis=1)
In [33]: km.inertia_
Out[33]: 147.01626670004867
In [34]: distortion.sum()
Out[34]: 147.01626670004865
请注意,值的尾部存在一些细微差异,这是由于数值精度造成的,但您可以放心,我们已经分别计算了每个示例的失真。
一旦你有了扭曲的数组,你可以在你的数据框中添加一个额外的列来代表这些,你可以根据你的需要找到哪一行给你带来了最大或最小的扭曲。
【讨论】:
以上是关于用kmeans创建集群时,有没有办法输出每一行的失真?的主要内容,如果未能解决你的问题,请参考以下文章
KMeans 从 2 列的所有可能组合中聚类不产生正确的输出