我一直在尝试计算我使用 KModes 聚类创建的聚类的轮廓系数(因为我的所有数据字段都是分类的)。我使用匹配差异作为距离度量。
def matching_disimilarity(a, b):
return np.sum(a != b)
由于我在互联网上找不到任何这样的 Python 实现,我决定自己按照 Wikipedia 文档 - https://en.wikipedia.org/wiki/Silhouette_(clustering)编写一个。这是我到目前为止所拥有的。
def silhouette_analysis(df):
n_clusters = 5
sil = []
for i, r_i in df.iterrows():
c_i = r_i['cluster']
r_i = r_i.drop('cluster', axis=0)
same_cluster_df = df[df['cluster'] == c_i].reset_index(drop=True)
other_clusters_df = df[df['cluster'] != c_i].reset_index(drop=True)
a_i = 0
for j, r_j in same_cluster_df.iterrows():
r_j = r_j.drop('cluster', axis=0)
d_ij = matching_disimilarity(r_i, r_j)
a_i += d_ij
a_i = a_i/(len(same_cluster_df) - 1)
b_i = []
b_in = 0
for c_n in range(n_clusters):
if c_i == c_n: continue
nearest_cluster_df = other_clusters_df[other_clusters_df['cluster'] == c_n]
for j, r_j in nearest_cluster_df.iterrows():
r_j = r_j.drop('cluster', axis=0)
d_ij = matching_disimilarity(r_i, r_j)
b_in += d_ij
b_in = b_in/len(nearest_cluster_df)
b_i.append(b_in)
b_i = min(b_i)
if (a_i < b_i):
s_i = 1 - (a_i/b_i)
elif(a_i == b_i):
s_i = 0
else:
s_i = b_i/a_i - 1
sil.append(s_i)
df['sil'] = sil
return df
df
我作为参数传递的数据框已将集群映射到列中的每一行cluster
。
我想问3个问题:
- 我的代码正确吗?它会给我对集群的正确评估吗?
- 这现在超级慢。我有近 20k 行,计算轮廓系数需要 2 多分钟。为单行。
- Silhouette coeff 是否有任何现有且可靠的 python 实现。使用匹配差异作为距离度量的 KModes 聚类。