Sklearn 成长之路(五)K-means聚类及其评价指标——轮廓系数

时间:2024-03-23 16:03:12

聚类结果评价指标——轮廓系数

某个点的轮廓系数定义为:

s=disMeanoutdisMeaninmax(disMeanout,disMeanin)s =\frac{disMean_{out} - disMean_{in}}{max(disMean_{out}, disMean_{in})}
其中disMeanintdisMean_{int}为该点与本类其他点的平均距离,disMeanoutdisMean_{out}为该点与非本类点的平均距离。该值取值范围为[1,1][-1, 1], 越接近1则说明分类越优秀。在sklearn中函数silhouette_score()计算所有点的平均轮廓系数,而silhouette_samples()返回每个点的轮廓系数。

预设不同的簇数分类结果

原始数据:
Sklearn 成长之路(五)K-means聚类及其评价指标——轮廓系数
分类结果:
Sklearn 成长之路(五)K-means聚类及其评价指标——轮廓系数
Sklearn 成长之路(五)K-means聚类及其评价指标——轮廓系数
Sklearn 成长之路(五)K-means聚类及其评价指标——轮廓系数
结论:预设4簇的时候其平均轮廓系数最高,所以分4簇是最优的,与数据集相匹配。

Show me the code

导包

# 生成数据模块
from sklearn.datasets import make_blobs
# k-means模块
from sklearn.cluster import KMeans
# 评估指标——轮廓系数,前者为所有点的平均轮廓系数,后者返回每个点的轮廓系数
from sklearn.metrics import silhouette_score, silhouette_samples

import numpy as np
import matplotlib.pyplot as plt

生成数据

# 生成数据
x_true, y_true = make_blobs(n_samples= 600
                            , n_features= 2, centers= 4, random_state= 1)

# 绘制出所生成的数据
plt.figure(figsize= (6, 6))
plt.scatter(x_true[:, 0], x_true[:, 1], c= y_true, s= 10)
plt.title("Origin data")
plt.show()

预设不同簇数并聚类

# 根据不同的n_centers进行聚类
n_clusters = [x for x in range(3, 6)]

for i in range(len(n_clusters)):
    # 实例化k-means分类器
    clf = KMeans(n_clusters= n_clusters[i])
    y_predict = clf.fit_predict(x_true)
    
    # 绘制分类结果
    plt.figure(figsize= (6, 6))
    plt.scatter(x_true[:, 0], x_true[:, 1], c= y_predict, s= 10)
    plt.title("n_clusters= {}".format(n_clusters[i]))
    
    ex = 0.5
    step = 0.01
    xx, yy = np.meshgrid(np.arange(x_true[:, 0].min() - ex, x_true[:, 0].max() + ex, step),
                         np.arange(x_true[:, 1].min() - ex, x_true[:, 1].max() + ex, step))
    
    zz = clf.predict(np.c_[xx.ravel(), yy.ravel()])
    zz.shape = xx.shape
    
    plt.contourf(xx, yy, zz, alpha= 0.1)
    
    plt.show()
    
    # 打印平均轮廓系数
    s = silhouette_score(x_true, y_predict)
    print("When cluster= {}\nThe silhouette_score= {}".format(n_clusters[i], s))
    
    # 利用silhouette_samples计算轮廓系数为正的点的个数
    n_s_bigger_than_zero = (silhouette_samples(x_true, y_predict) > 0).sum()
    print("{}/{}\n".format(n_s_bigger_than_zero, x_true.shape[0]))