轮廓系数找最佳n_cluster(基于sklearn)

轮廓系数找最佳n_cluster(基于sklearn)

# -*- encoding : utf-8 -*-
"""
@project = sklearn_learning_01
@file = 轮廓系数找最佳n_cluster
@author = wly
@create_time = 2022/12/7 23:15
"""

from sklearn.datasets import make_blobs
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_samples, silhouette_score
import matplotlib.pyplot as plt
import matplotlib.cm as cm  # colormap
import numpy as np

if __name__ == '__main__':
    # 基于轮廓系数选择最佳的n_clusters
    # 聚类完毕之后图像的分布是什么样的

    # 自己创建数据集
    X, y = make_blobs(n_samples=500, n_features=2, centers=4, random_state=1)

    # 包装成一个循环
    for n_clusters in [2, 3, 4, 5, 6, 7]:
        # 设定分成的簇数
        n_clusters = n_clusters

        # 创建一个画布,画布上共有一行两列两个图
        fig, (ax1, ax2) = plt.subplots(1, 2)
        # 画布尺寸
        fig.set_size_inches(18, 7)

        # 第一个图是轮廓系数图像,是由各个簇的轮廓系数组成的横向条形图
        # 横向条形图的横坐标是轮廓系数取值,纵坐标是每一个样本,因为轮廓系数是对每一个样本进行计算的

        # 首先设定横坐标
        # 轮廓系数的取值范围在[-1, 1]之间,但目前希望轮廓系数要大于0
        # 太长的横坐标不利于可视化,故只设定X轴的取值在[-0.1, 1]之间
        ax1.set_xlim([-0.1, 1])

        # 设定纵坐标,通常纵坐标是从0开始的,最大值取到X.shape[0]的取值
        # 但为显示直观,每个簇能够排在一起,不同的簇之间能够有一定的空隙
        # 故设定纵坐标的取值范围时,在X.shape[0]上,加上一个距离(n_clusters + 1) * 10,留作间隔用
        ax1.set_ylim([0, X.shape[0] + (n_clusters + 1) * 10])

        # 开始建模,调用聚类好的标签
        clusterer = KMeans(n_clusters=n_clusters, random_state=10).fit(X)
        cluster_labels = clusterer.labels_

        # 调用轮廓系数分数,注意,silhouette_score生成的所有样本点的轮廓系数均值
        # 两个需要输入的参数是,特征矩阵X和聚类完毕后的标签
        silhouette_score_avg = silhouette_score(X, cluster_labels)

        print("For n_clusters = ", n_clusters)
        print("The average silhouette_score is : ", silhouette_score_avg)

        # 调用silhouette_samples,返回每个样本点的轮廓系数,这就是横坐标的值
        sample_silhouette_values = silhouette_samples(X, cluster_labels)
        # print("sample_silhouette_values shape = ", sample_silhouette_values)
        # print(type(sample_silhouette_values))
        # print(sample_silhouette_values.shape)

        # 设定y轴上的初始值
        y_lower = 10

        # 接下来,对每一个簇进行循环
        for i in range(n_clusters):
            # 从每个样本的轮廓系数结果中抽取第i个簇的轮廓系数,并进行排序
            ith_cluster_silhouette_values = sample_silhouette_values[cluster_labels == i]
            # 注意,.sort()这个命令会直接改掉原数据的顺序
            ith_cluster_silhouette_values.sort()

            # 查看一个簇中究竟有多少个样本
            size_cluster_i = ith_cluster_silhouette_values.shape[0]
            # print("size_cluster_i = ", size_cluster_i)

            # 这是一个簇在y轴上取值,应该是由初始值(y_lower)开始,到初始值+这个簇中样本数量结束(y_upper)
            y_upper = y_lower +size_cluster_i
            # print("y_upper = ", y_upper)

            # colormap库中,使用小数来调用颜色的函数
            # 在nipy_spectral([输入任意小数来代表一个颜色])
            # 在这里希望每一个簇的颜色是不同的,需要的颜色种类刚好是循环的个数种类
            # 在这里,只要能够保证,每次循环生成的小数是不同的,可以使用任意方式来获取小数
            # 在这里,使用i的浮点数除以n_clusters, 在不同的i下,自然生成不同的小数
            # 以此来确保所有的簇会有不同的颜色
            color = cm.nipy_spectral(float(i) / n_clusters)

            # 开始填充子图1中的内容
            # fill_between是让一个范围内的柱状图都统一颜色的函数
            # fill_betweenx的范围是纵坐标上
            # fill_betweeny的范围是在横坐标
            # fill_betweenx的参数应该是输入(纵坐标的下限, 纵坐标的上限, 柱状图的颜色)
            ax1.fill_betweenx(np.arange(y_lower, y_upper)
                              , ith_cluster_silhouette_values
                              , facecolor=color
                              , alpha=0.7)

            # 为每一个簇的轮廓系数写上簇的编号,并且让簇的编号显示坐标轴上每个条形图的中间位置
            # text的参数为(要显示编号的位置横坐标, 要显示编号的位置纵坐标, 要显示编号的内容)
            ax1.text(-0.05,
                     y_lower + 0.5 * size_cluster_i,
                     str(i))

            # 为下一个簇计算新的y轴上的初始值,是每一次迭代之后,y的上限+10
            # 以此来保证,不同簇的图像之间显示有空隙
            y_lower = y_upper + 10


        # 图1加上标题,横坐标轴,纵坐标轴的标签
        ax1.set_title("The silhouette plot for the various clusters.")
        ax1.set_xlabel("The silhouette coefficient values")
        ax1.set_ylabel("Cluster label")

        # 把整个数据集上的轮廓系数的均值以虚线的形式放入图中
        ax1.axvline(x=silhouette_score_avg, color="red", linestyle="--")

        # 让y轴不显示任何坐标
        ax1.set_yticks([])

        # 让x轴上的刻度显示规定的列表
        ax1.set_xticks([-0.1, 0, 0.2, 0.4, 0.6, 0.8, 1])

        # 对第二个图进行处理,首先获取新颜色
        colors = cm.nipy_spectral(cluster_labels.astype(float) / n_clusters)

        ax2.scatter(X[:, 0], X[:, 1],
                    marker='o',
                    s=8,
                    c=colors)
        # 把生成的质心放到图像中去
        centers = clusterer.cluster_centers_
        ax2.scatter(centers[:, 0], centers[:, 1],
                    marker='x',
                    c='red',
                    alpha=1,
                    s=200)

        # 为图2设置标题,横坐标标题,纵坐标标题
        ax2.set_title("The visualization of the clustered data.")
        ax2.set_xlabel("Feature space for the 1st feature")
        ax2.set_ylabel("Feature space for the 2nd feature")

        # 为整个图设置标题
        plt.suptitle(("Silhouette analysis for KMeans clustering on sample data with n_clusters = %d" % n_clusters),
                     fontsize=14, fontweight='bold')

        plt.show()

For n_clusters = 2
The average silhouette_score is : 0.7049787496083262
For n_clusters = 3
The average silhouette_score is : 0.5882004012129721
For n_clusters = 4
The average silhouette_score is : 0.6505186632729437
For n_clusters = 5
The average silhouette_score is : 0.56376469026194
For n_clusters = 6
The average silhouette_score is : 0.4504666294372765
For n_clusters = 7
The average silhouette_score is : 0.39092211029930857

轮廓系数找最佳n_cluster(基于sklearn)_第1张图片
轮廓系数找最佳n_cluster(基于sklearn)_第2张图片
轮廓系数找最佳n_cluster(基于sklearn)_第3张图片
轮廓系数找最佳n_cluster(基于sklearn)_第4张图片
轮廓系数找最佳n_cluster(基于sklearn)_第5张图片
轮廓系数找最佳n_cluster(基于sklearn)_第6张图片

你可能感兴趣的:(LachineLearning,sklearn,python)