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

相关推荐
weixin_51520249几秒前
第R3周:RNN-心脏病预测
人工智能·rnn·深度学习
Altair澳汰尔3 分钟前
数据分析和AI丨知识图谱,AI革命中数据集成和模型构建的关键推动者
人工智能·算法·机器学习·数据分析·知识图谱
AI视觉网奇24 分钟前
人脸生成3d模型 Era3D
人工智能·计算机视觉
call me by ur name27 分钟前
VLM--CLIP作分类任务的损失函数
人工智能·机器学习·分类
Python机器学习AI32 分钟前
分类模型的预测概率解读:3D概率分布可视化的直观呈现
算法·机器学习·分类
吃个糖糖41 分钟前
34 Opencv 自定义角点检测
人工智能·opencv·计算机视觉
禁默42 分钟前
2024年图像处理、多媒体技术与机器学习
图像处理·人工智能·microsoft
KeepThinking!1 小时前
YOLO-World:Real-Time Open-Vocabulary Object Detection
人工智能·yolo·目标检测·多模态
AIGCmagic社区1 小时前
AI多模态技术介绍:理解多模态大语言模型的原理
人工智能·语言模型·自然语言处理
图王大胜1 小时前
模型 双螺旋(通俗解读)
人工智能·管理·系统科学·认知科学·生命科学·战略规划·通识科学