文章目录
@[toc] K-means 聚类算法 “深入浅出”
- 一、K-means 是什么?
- 二、算法原理(用直觉理解)
- 三、数学形式
- 四、实际案例:客户分群(Customer Segmentation)
- 五、结果解释
- 六、K-means 的优缺点
- 七、Python 实现示例
一、基础参数
n_clustersinitn_initmax_itertolrandom_state
二、高级参数
algorithmverbosecopy_xn_jobs(旧版本参数)
三、一个示例:理解参数组合
四、常见调优技巧
K 在使用K-means 聚类算法前,确实最关键的一环是确定合理的簇数K。选得太少会“合并不同群体”,选得太多又会“过度细分”。
一、肘部法(Elbow Method)
- 原理:
- 优点:
- 缺点:
二、轮廓系数法(Silhouette Coefficient)
- 原理:
- 实践步骤:
- 优点:
- 缺点:
三、Gap Statistic 法(间隙统计)
- 原理:
- 优点:
- 缺点:
四、领域知识 + 可解释性
五、综合策略推荐
Python 示例(Elbow + Silhouette 双验证)
K-means 聚类算法 “深入浅出”
一、K-means 是什么?
K-means 是一种常见的无监督学习算法(Unsupervised Learning),用于将数据自动分成 K 个簇(clusters)。它的目标是让同一簇内的数据尽可能相似,而不同簇之间的数据尽可能不同。
通俗点说:想象你在一个班里想把学生按照“学习风格”分组。你不知道谁学得好谁学得差,只知道他们的考试分数、作业时间等数据。K-means 就帮你自动找出相似的学生,把他们分成几组。
二、算法原理(用直觉理解)
K-means 的过程可以分为 4 步:
- 确定簇的数量 K,比如我们想分 3 组,就设 K=3。
- 随机选择 K 个初始“中心点”(Centroids)
- 将每个样本分配到离自己最近的中心点。计算“欧氏距离”,选择最近的那个中心。
- 更新中心点,对每一簇内的点求平均值,作为新的中心点。然后反复执行第 3 和第 4 步,直到:中心点几乎不变;或者达到设定的最大迭代次数。
三、数学形式
设: 数据集为 X = \{x_1, x_2, ..., x_n\},每个样本 x_i \in \mathbb{R}^d 要分成 K 个簇 C_1, C_2, ..., C_K 每个簇的中心为 \mu_k
K-means 的目标函数是最小化簇内平方误差 (SSE): J = \sum_{k=1}^{K} \sum_{x_i \in C_k} ||x_i - \mu_k||^2 也就是说,K-means 想让每个点尽量靠近自己的中心点。
四、实际案例:客户分群(Customer Segmentation)
场景: 一家电商公司有用户的购买数据(如下):
| 用户 | 月消费额(元) | 每月购物次数 |
|---|---|---|
| A | 500 | 2 |
| B | 1200 | 6 |
| C | 300 | 1 |
| D | 1000 | 5 |
| E | 4000 | 15 |
| F | 3800 | 14 |
我们想把这些客户分成几类,方便做营销。
- 步骤 1:设定 K=2 假设我们想看看客户能否分成「普通客户」与「高价值客户」两类。
- 步骤 2:初始化两个中心点 随机选取两个点,例如: \mu_1 = (500, 2) \mu_2 = (4000, 15)
- 步骤 3:分配客户到最近中心 计算每个客户与两中心的欧氏距离,谁近归谁。 结果可能是: C1组(普通客户):A, B, C, D C2组(高价值客户):E, F
- 步骤 4:更新中心 对每组求均值: \mu_1 = (750, 3.5), \quad \mu_2 = (3900, 14.5) 重复步骤 3-4,直到中心不再变化。
五、结果解释
最后,算法自动将客户分成两类:
| 客户类型 | 平均月消费 | 平均购物次数 | 营销策略 |
|---|---|---|---|
| 普通客户 | 750元 | 3.5次 | 打折促销、积分奖励 |
| 高价值客户 | 3900元 | 14.5次 | 专属服务、优惠券 |
3900元
14.5次
VIP 客服、专属优惠
K-means 的优缺点
优点:
- 简单、直观、运算效率高;
- 适合大规模数据处理。
缺点:
- 需要提前确定 K 值;
- 对初始点较为敏感;
- 只能发现“球状”集群;
- 对异常值敏感。
Python 实现示例
from sklearn.cluster import KMeans
import pandas as pd
# 构建数据
data = pd.DataFrame({
'消费额': [500, 1200, 300, 1000, 4000, 3800],
'购物次数': [2, 6, 1, 5, 15, 14]
})
# 训练 K-means 模型
kmeans = KMeans(n_clusters=2, random_state=42)
data['类别'] = kmeans.fit_predict(data)
print(data)
print("簇中心:\n", kmeans.cluster_centers_)
输出结果将展示每个客户属于哪一类,以及各组的中心。
基础参数
-
含义:要划分的簇的数量 K。n_clusters- 默认值:
8 - 影响:这是最关键的参数,直接决定分群的粒度。
- 选择方法:常用“肘部法(Elbow Method)”或“轮廓系数(Silhouette Score)”来确定合适的 K。
- 默认值:
-
含义:初始化簇中心的方法。init- 可选值:
(默认):通过概率分布方式挑选初始点,能提高稳定性;'k-means++'
:随机选择初始点;也可直接传入一个自定义初始中心矩阵。'random' - 建议:几乎总是使用
。'k-means++'
- 可选值:
-
含义:算法会用不同初始点运行多少次,选择效果最好的结果。n_init- 默认值(在 sklearn >=1.4 中):
(通常相当于'auto'
)10 - 建议:设置为较高的值(如
),可以提高稳定性,减少陷入局部最优的风险。10~20
- 默认值(在 sklearn >=1.4 中):
-
含义:每次运行的最大迭代次数。max_iter- 默认值:
300 - 说明:K-means 是迭代算法;如果数据多、收敛慢,可以适当增大。
- 默认值:
-
含义:容差(收敛阈值),当簇中心变化小于此值时停止迭代。tol- 默认值:
1e-4 - 作用:影响算法的停止条件。值越小,结果更精确,但计算时间更长。
- 默认值:
-
含义:随机种子,确保结果可复现。random_state- 建议:调试时或需要复现结果时设定固定值,例如
。random_state=42
- 建议:调试时或需要复现结果时设定固定值,例如
高级参数
-
含义:选择具体的底层算法。algorithm- 可选值:
(默认):传统的 Lloyd 算法;'lloyd'
:使用三角不等式加速(只适用于欧氏距离);'elkan'
:根据数据自动选择;'auto'
(旧版本别名,等价于'full'
)。'lloyd' - 建议:大多数情况下用默认值
即可;高维或稀疏数据可试'lloyd'
。'elkan'
- 可选值:
-
含义:是否输出详细日志。verbose- 值:整数(0 表示不输出,数字越大输出越多)
- 用途:调试或监控收敛过程时开启。
-
含义:是否复制输入数据。copy_x- 默认值:
True - 说明:若设为
,原数据可能被算法修改,节省内存但需谨慎。False
- 默认值:
-
(旧版本参数)n_jobs- 说明:并行计算任务数。在 sklearn 新版中已弃用(改用
自动管理)。joblib
- 说明:并行计算任务数。在 sklearn 新版中已弃用(改用
一个示例:理解参数组合
from sklearn.cluster import KMeans
import pandas as pd
# 模拟数据
data = pd.DataFrame({
'消费额': [500, 1200, 300, 1000, 4000, 3800],
'购物次数': [2, 6, 1, 5, 15, 14]
})
# 初始化模型
kmeans = KMeans(
n_clusters=2, # 分两类
init='k-means++', # 启发式初始化
n_init=10, # 运行10次取最优
max_iter=300, # 每次最多迭代300次
tol=1e-4, # 收敛阈值
random_state=42, # 固定随机种子
algorithm='lloyd' # 使用经典算法
)
# 拟合模型
kmeans.fit(data)
print("簇中心:\n", kmeans.cluster_centers_)
print("标签:", kmeans.labels_)
常见调优技巧
调优目标:
- 提高结果稳定性:增大
n_init - 提高精度(更精确收敛):减小
,增大tolmax_iter - 控制聚类数量:调整 K 值
n_clusters
加快计算速度
使用
algorithm='elkan'
(仅限欧氏距离)
结果可重现
设置
random_state
K
在使用 K-means 聚类算法前,确实最关键的一步是确定合理的簇数 K。选得太少会“合并不同群体”,选得太多又会“过度分割”。
???? 一、肘部法(Elbow Method)
原理
对不同的 K 值(例如 1~10)运行 K-means;
记录每次的 SSE(Sum of Squared Errors,簇内误差平方和);
画出 “K - SSE” 曲线。
随着 K 的增加,SSE 会持续下降,但下降速度会逐渐放缓。
当下降趋势明显减缓、形成“肘部”时,该点对应的 K 即为较优选择。
优点
简单直观;
适合初步判断簇数。
缺点
肘部位置有时不明显(主观性强);
对高维数据可能效果较差。
???? 二、轮廓系数法(Silhouette Coefficient)
原理
每个样本都有一个轮廓系数 s_i,衡量它与本簇和其他簇的相对紧密度:
s_i = \frac{b_i - a_i}{\max(a_i, b_i)}
其中:
a_i:样本与本簇内其他样本的平均距离;
b_i:样本与最近邻簇中样本的平均距离。
整体平均轮廓系数 S 的取值范围为 [-1, 1],越接近 1 表示聚类效果越好。
实践步骤
对不同 K 值计算平均 Silhouette Score;
取最大值对应的 K。
优点
自动量化聚类质量;
不依赖主观视觉判断。
缺点
计算开销略大;
对形状复杂的簇不总是可靠。
???? 三、Gap Statistic 法(间隙统计)
原理
将真实数据的聚类结果与随机均匀分布数据的聚类结果作比较:
Gap(K) = E^*[\log(W_k)] - \log(W_k)
其中 W_k 是簇内平方和。
当 Gap 值首次显著下降时,对应的 K 为理想值。
优点
理论基础较强;
自动评估“与随机数据相比是否显著更好”。
缺点
计算较慢;
实现复杂(需重复采样)。
???? 四、领域知识 + 可解释性
在商业、工程、金融等应用中,往往可以根据业务逻辑辅助判断 K:
客户类型(普通、高端、VIP) → K=3;
用户地域(东部、西部、北部) → K=3;
产品系列分类 → 固定 K。
算法可提供参考,但最终还要结合领域理解。
???? 五、综合策略推荐
场景
建议方法
数据较简单、初次尝试
肘部法
想客观度量聚类效果
轮廓系数法
数据复杂、需要严格比较
Gap Statistic
有业务逻辑或先验分类
结合领域知识设定 K
???? Python 示例(Elbow + Silhouette 双验证)
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
import matplotlib.pyplot as plt
inertias = []
sil_scores = []
K_range = range(2, 10)
for k in K_range:
kmeans = KMeans(n_clusters=k, random_state=42).fit(X)
inertias.append(kmeans.inertia_)
sil_scores.append(silhouette_score(X, kmeans.labels_))
fig, ax1 = plt.subplots()
ax2 = ax1.twinx()
ax1.plot(K_range, inertias, 'o-', label='Inertia')
ax2.plot(K_range, sil_scores, 's--', color='orange', label='Silhouette Score')
ax1.set_xlabel('K')
ax1.set_ylabel('Inertia')
ax2.set_ylabel('Silhouette Score')
plt.title('Elbow & Silhouette Method')
plt.show()


雷达卡


京公网安备 11010802022788号







