大数据-216 数据挖掘 机器学习理论 - KMeans 基于轮廓系数来选择 n_clusters

点一下关注吧!!!非常感谢!!持续更新!!!

目前已经更新到了:

  • Hadoop(已更完)
  • HDFS(已更完)
  • MapReduce(已更完)
  • Hive(已更完)
  • Flume(已更完)
  • Sqoop(已更完)
  • Zookeeper(已更完)
  • HBase(已更完)
  • Redis (已更完)
  • Kafka(已更完)
  • Spark(已更完)
  • Flink(已更完)
  • ClickHouse(已更完)
  • Kudu(已更完)
  • Druid(已更完)
  • Kylin(已更完)
  • Elasticsearch(已更完)
  • DataX(已更完)
  • Tez(已更完)
  • 数据挖掘(正在更新...)

章节内容

上节我们完成了如下的内容:

  • KMeans Python 实现
  • 算法验证 sklearn cluster.cluster_centers_ inertia_

案例:基于轮廓系数来选择 n_clusters

结果展示

我们通常绘制轮廓系数分布图和聚类后的数据分布图来选择我们最佳的 n_clusters

(代码在下面,这里放图)

样本数据的 KMeans 轮廓分析 簇为 2

样本数据的 KMeans 轮廓分析 簇为 4

样本数据的 KMeans 轮廓分析 簇为 6

样本数据的 KMeans 轮廓分析 簇为 8

编写代码

python 复制代码
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_samples, silhouette_score
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numpy as np

# 假设X已经是定义好的数据集
# for循环,簇数从2到10,步长为2
for i in range(2, 10, 2):  
    # 创建图形和子图
    fig, (ax1, ax2) = plt.subplots(1, 2)
    fig.set_size_inches(18, 7)

    # 设置第一个子图的x轴和y轴范围
    ax1.set_xlim([-0.1, 1])
    ax1.set_ylim([0, X.shape[0] + (i + 1) * 10])

    # 生成KMeans模型并拟合数据
    clusterer = KMeans(n_clusters=i, random_state=10)
    cluster_labels = clusterer.fit_predict(X)

    # 计算轮廓系数
    silhouette_avg = silhouette_score(X, cluster_labels)
    sample_silhouette_values = silhouette_samples(X, cluster_labels)

    print(f"簇数 = {i}, 轮廓系数均值 = {silhouette_avg}")

    y_lower = 10
    for j in range(i):
        # 获取第j簇的轮廓系数
        ith_cluster_silhouette_values = sample_silhouette_values[cluster_labels == j]
        ith_cluster_silhouette_values.sort()

        size_cluster_j = ith_cluster_silhouette_values.shape[0]
        y_upper = y_lower + size_cluster_j

        color = cm.nipy_spectral(float(j) / i)
        ax1.fill_betweenx(np.arange(y_lower, y_upper), 
                          ith_cluster_silhouette_values, 
                          facecolor=color, alpha=0.5)

        ax1.text(-0.05, y_lower + 0.5 * size_cluster_j, str(j))

        y_lower = y_upper + 10

    # 设置子图1的标题和标签
    ax1.set_title("不同簇的轮廓图")
    ax1.set_xlabel("轮廓系数值")
    ax1.set_ylabel("簇类标签")
    ax1.axvline(x=silhouette_avg, color="red", linestyle="--")
    ax1.set_yticks([])
    ax1.set_xticks([-0.1, 0, 0.2, 0.4, 0.6, 0.8, 1])

    # 子图2:簇群的散点图
    colors = cm.nipy_spectral(cluster_labels.astype(float) / i)
    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", s=200)

    # 设置子图2的标题和标签
    ax2.set_title("簇群数据可视化")
    ax2.set_xlabel("第一特征的特征空间")
    ax2.set_ylabel("第二特征的特征空间")

    # 总标题
    plt.suptitle(f"样本数据的KMeans轮廓分析--簇数为:{i}", fontsize=14, fontweight='bold')
    plt.show()

具体详细的内容不展示了,上述的图片已经都有了。

重要参数-初始质心选择

在 KMeans 中有一个重要的环节,就是放置初始质心。如果有足够的时间,KMeans 一定会收敛,但 Intertia 可能收敛到局部最小值。是否能够收敛到真正的最小值很大程度上取决了质心的初始化。init 就是用来帮助我们解决初始化方式的参数。

初始质心放置的位置不同,聚类的结果很可能也会不一样,一个好的质心选择可以让 KMeans 避免更多的计算,让算法收敛稳定且更快。在之前讲解初始质心的放置时,我们是使用"随机"的方法在样本点中抽取 K 个样本作为初始质心,这种方法显然不符合稳定且更快的需求。为此,我们可以使用 random_state 参数来控制每次生成的初始质心都在相同位置,甚至可以画学习曲线来确定最优的 random_state 是哪个整数。

一个 random_state 对应一个质心随机初始化的随机数种子,如果不指定随机数种子,则 sklearn 中的 KMeans 并不会只选择一个随机模式扔出结果,而会在每个随机数种子来作为初始质心。我们可以使用参数 n_init 来选择,每个随机数种子下运行的次数。这个参数不常用到,默认 10 次,如果我们希望运行的结果来更加精确,那我们可以增加这个参数n_init的值来增加每个随机数种子下运行的次数。

然后这种方法依然是基于随机性的。为了优化选择初始质心的方法,2007 年 Arthur, David, and Sergei Vassilviskii 三人发表了论文"KMeans ++:The advantages of careful seeding",他们开发了"KMeans++"初始化方案,使得初始质心(通常)彼此远离,以此来引导出随机初始化更可靠的结果。

在 sklearn 中,我们使用参数 init = kmeans ++ 来选择 kmeans++作为质心初始化方案。通常来说,建议保留默认的。

init

可输入 "k-means++","random"或者一个 n 维数组

  • 初始化质心的方法,默认"k-means++"
  • 输入"k-means++":一种为 K 均值聚类选择初始聚合中心的聪明的办法,以加速收敛
  • 如果输入了 N 维数组,数组的形状应该是(n_clusters,n_features)并给出初始质心
python 复制代码
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
from sklearn.datasets import load_breast_cancer

# 加载数据集
data = load_breast_cancer()
X = data.data

# KMeans 聚类,使用 'k-means++' 初始化
cluster_01 = KMeans(n_clusters=8, init='k-means++', random_state=42).fit(X)

# 输出运行的迭代次数
print(f"KMeans with 'k-means++' initialization ran for {cluster_01.n_iter_} iterations.")

# 计算并输出轮廓系数(用于评估聚类效果)
sil_score_01 = silhouette_score(X, cluster_01.labels_)
print(f"Silhouette Score for 'k-means++': {sil_score_01:.4f}")

# KMeans 聚类,使用 'random' 初始化
cluster_02 = KMeans(n_clusters=8, init='random', random_state=42).fit(X)

# 输出运行的迭代次数
print(f"KMeans with 'random' initialization ran for {cluster_02.n_iter_} iterations.")

# 计算并输出轮廓系数
sil_score_02 = silhouette_score(X, cluster_02.labels_)
print(f"Silhouette Score for 'random': {sil_score_02:.4f}")

执行结果如下图所示:

n_init

整数,默认 10

  • 使用不同的质心随机初始化的种子来运行 KMeans 算法的次数,最终结果会是基于 Inertia 来计算的
  • n_init 次连续运行后的最佳输出

random_state

python 复制代码
cluster_01 = KMeans(n_clusters = 10,n_init=500).fit(X)
cluster_01.n_iter_ # 输出运行的迭代次数
silhouette_score(X,cluster_01.labels_)
cluster_02 = KMeans(n_clusters = 10,n_init=500,random_state=10).fit(X) # 每次运行结果将会一样
cluster_02.n_iter_
silhouette_score(X,cluster_02.labels_)

执行结果如下图所示:

重要参数-迭代停止

在之前描述 KMeans 的基础流程时我们提到过,当质心不再移动,KMeans 算法就会停下来。但在完成收敛之前,我们也可以使用 max_iter,最大迭代次数,或者 tol,两次迭代间 Inertia 下降的量,这两个参数来让迭代提前 停下来。有时间,当我们 n_cluster 选择不符合数据的自然分布,或者我们为了业务需求,必须要填入与数据的自然分布不合的 n_cluster,提前让迭代停下来反而能够提升模型的表现。

相关推荐
AI_小站2 分钟前
RAG 示例:使用 langchain、Redis、llama.cpp 构建一个 kubernetes 知识库问答
人工智能·程序人生·langchain·kubernetes·llama·知识库·rag
Doker 多克4 分钟前
Spring AI 框架使用的核心概念
人工智能·spring·chatgpt
Guofu_Liao5 分钟前
Llama模型文件介绍
人工智能·llama
麦田里的稻草人w9 分钟前
【数据分析实战】(一)—— JOJO战力图
数据挖掘·数据分析
天冬忘忧24 分钟前
Kafka 工作流程解析:从 Broker 工作原理、节点的服役、退役、副本的生成到数据存储与读写优化
大数据·分布式·kafka
思通数科多模态大模型35 分钟前
10大核心应用场景,解锁AI检测系统的智能安全之道
人工智能·深度学习·安全·目标检测·计算机视觉·自然语言处理·数据挖掘
数据岛39 分钟前
数据集论文:面向深度学习的土地利用场景分类与变化检测
人工智能·深度学习
sevevty-seven1 小时前
幻读是什么?用什么隔离级别可以防止幻读
大数据·sql
龙的爹23331 小时前
论文翻译 | RECITATION-AUGMENTED LANGUAGE MODELS
人工智能·语言模型·自然语言处理·prompt·gpu算力
白光白光1 小时前
凸函数与深度学习调参
人工智能·深度学习