大数据-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,提前让迭代停下来反而能够提升模型的表现。

相关推荐
池央11 分钟前
丹摩征文活动 | 搭建 CogVideoX-2b详细教程:用短短6秒展现创作魅力
人工智能
QYR市场调研23 分钟前
5G时代的关键元件:射频微波MLCCs市场前景广阔
人工智能
天冬忘忧27 分钟前
Spark 共享变量:广播变量与累加器解析
大数据·python·spark
AI小白日记33 分钟前
深入探索AutoDL平台:深度学习GPU算力最佳选择
人工智能·深度学习·gpu算力
一尘之中44 分钟前
元宇宙及其技术
人工智能
电子手信1 小时前
AI知识库在行业应用中的未来趋势与案例分析
大数据·人工智能·自然语言处理·数据挖掘
zmd-zk1 小时前
hive中windows子句的使用
大数据·数据仓库·hive·hadoop·windows·分布式·big data
严文文-Chris2 小时前
【卷积神经网络】
人工智能·神经网络·cnn
B站计算机毕业设计超人2 小时前
计算机毕业设计Python+Neo4j中华古诗词可视化 古诗词智能问答系统 古诗词数据分析 古诗词情感分析 PyTorch Tensorflow LSTM
pytorch·python·深度学习·机器学习·知识图谱·neo4j·数据可视化
B站计算机毕业设计超人4 小时前
计算机毕业设计Python+大模型斗鱼直播可视化 直播预测 直播爬虫 直播数据分析 直播大数据 大数据毕业设计 机器学习 深度学习
爬虫·python·深度学习·机器学习·数据分析·课程设计·数据可视化