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

embedded/2024/11/14 5:50:02/

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

目前已经更新到了:

  • 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
在这里插入图片描述

编写代码

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 = 10for 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_jcolor = 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)并给出初始质心
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

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


http://www.ppmy.cn/embedded/136445.html

相关文章

Python: argparse模块

1. 导入模块和创建解析器 argparse 是 Python 标准库中用于命令行参数解析的模块。你首先需要导入 argparse,然后创建一个 ArgumentParser 对象,该对象将负责解析命令行参数。 (感觉和Java中,main 方法的 String[] args有点像&am…

分组校验在Spring中的应用详解

目录 前言1. 什么是分组校验2. 分组校验的基本原理3. 分组校验的实现步骤3.1 定义分组接口3.2 在校验项中指定分组3.3 校验时指定要校验的分组3.4 默认分组和分组的继承 4. 分组校验的优势和适用场景4.1 优势4.2 适用场景 5. 常见问题与解决方案5.1 校验未生效5.2 无法识别默认…

[面试]关于Redis 的持久化你了解吗

Redis的持久化是指Redis服务器在关闭或重启时,将内存中的数据保存到磁盘上的一种机制。Redis支持多种持久化方式。 一、RDB(Redis Database)持久化 RDB持久化是Redis默认采用的持久化方式,它将Redis在某个时间点的数据保存到磁盘上…

QT模态对话框和非模态对话框区别以及常用标准对话框

QT模态对话框和非模态对话框区别以及常用标准对话框 1.概述 这篇文章介绍下对话框的分类,它分为模态对话框和非模态对话框。 模态对话框:打开对话框后,不能操作其他窗口 非模态对话框:打开对话框后,可以操作其他窗口…

Risc-v:mhartid寄存器

简介 mhartid(Machine Hart ID Register)是 RISC-V 架构中的一个控制和状态寄存器(CSR),用于存储当前硬件线程(hart)的标识符。 在多核处理器中,每个核心可能有一个或多个硬件线程&a…

页面上的内容的生成图片后,保存为word,并下载

页面上的内容的生成图片后&#xff0c;保存为word&#xff0c;并下载 juqery <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Download Page Screenshot as Word</title><script src"h…

el-scrollbar 动态更新内容 鼠标滚轮无效

有以下功能逻辑&#xff0c;实现了一个时间轴组件&#xff0c;点击、-号后像地图那样放大组件以显示不同的UI。 默认显示年月&#xff1a; 当点击一下加号时切换为年&#xff1a; 当点击减号时切换为日&#xff1a; 即加号、减号点击就是在年月日显示进行切换。给Scrollvie…

Java并发无锁篇--乐观锁(非阻塞)

共享模型之无锁 问题提出 package com.zjy.unlock;import java.util.ArrayList; import java.util.List;public class AccountDemo {public static void main(String[] args) {Account account new AccountUnsafe(10000);Account.demo(account);} }class AccountUnsafe impl…