Python数据挖掘之聚类
文章目录
- @[toc] **K-means 聚类算法** “深入浅出”
- 🧠 一、K-means 是什么?
- 🔢 二、算法原理(用直觉理解)
- 🧮 三、数学形式
- 🧩 四、实际案例:客户分群(Customer Segmentation)
- 步骤 1:设定 K = 2 K=2 K=2
- 步骤 2:初始化两个中心点
- 步骤 3:分配客户到最近中心
- 步骤 4:更新中心
- 📊 五、结果解释
- 💡 六、K-means 的优缺点
- 🧰 七、Python 实现示例
- 参数
- 🧩 一、基础参数
- 1. `n_clusters`
- 2. `init`
- 3. `n_init`
- 4. `max_iter`
- 5. `tol`
- 6. `random_state`
- ⚙️ 二、高级参数
- 1. `algorithm`
- 2. `verbose`
- 3. `copy_x`
- 4. `n_jobs`(旧版本参数)
- 🧠 三、一个示例:理解参数组合
- 📊 四、常见调优技巧
- K
- 在使用 **K-means 聚类算法** 前,确实最关键的一步是确定合理的簇数 **K**。选得太少会“合并不同群体”,选得太多又会“过度分割”。
- 🧠 一、肘部法(Elbow Method)
- 原理
- 优点
- 缺点
- 📈 二、轮廓系数法(Silhouette Coefficient)
- 原理
- 实践步骤
- 优点
- 缺点
- 📊 三、Gap Statistic 法(间隙统计)
- 原理
- 优点
- 缺点
- 🔍 四、领域知识 + 可解释性
- 💡 五、综合策略推荐
- 📘 Python 示例(Elbow + Silhouette 双验证)
K-means 聚类算法 “深入浅出”
文章目录
- @[toc] **K-means 聚类算法** “深入浅出”
- 🧠 一、K-means 是什么?
- 🔢 二、算法原理(用直觉理解)
- 🧮 三、数学形式
- 🧩 四、实际案例:客户分群(Customer Segmentation)
- 步骤 1:设定 K = 2 K=2 K=2
- 步骤 2:初始化两个中心点
- 步骤 3:分配客户到最近中心
- 步骤 4:更新中心
- 📊 五、结果解释
- 💡 六、K-means 的优缺点
- 🧰 七、Python 实现示例
- 参数
- 🧩 一、基础参数
- 1. `n_clusters`
- 2. `init`
- 3. `n_init`
- 4. `max_iter`
- 5. `tol`
- 6. `random_state`
- ⚙️ 二、高级参数
- 1. `algorithm`
- 2. `verbose`
- 3. `copy_x`
- 4. `n_jobs`(旧版本参数)
- 🧠 三、一个示例:理解参数组合
- 📊 四、常见调优技巧
- K
- 在使用 **K-means 聚类算法** 前,确实最关键的一步是确定合理的簇数 **K**。选得太少会“合并不同群体”,选得太多又会“过度分割”。
- 🧠 一、肘部法(Elbow Method)
- 原理
- 优点
- 缺点
- 📈 二、轮廓系数法(Silhouette Coefficient)
- 原理
- 实践步骤
- 优点
- 缺点
- 📊 三、Gap Statistic 法(间隙统计)
- 原理
- 优点
- 缺点
- 🔍 四、领域知识 + 可解释性
- 💡 五、综合策略推荐
- 📘 Python 示例(Elbow + Silhouette 双验证)
🧠 一、K-means 是什么?
K-means 是一种常见的 无监督学习算法(Unsupervised Learning),用于将数据自动分成 K K K 个簇(clusters)。
它的目标是让 同一簇内的数据尽可能相似,而 不同簇之间的数据尽可能不同。
通俗点说:
想象你在一个班里想把学生按照“学习风格”分组。你不知道谁学得好谁学得差,只知道他们的考试分数、作业时间等数据。K-means 就帮你自动找出相似的学生,把他们分成几组。
🔢 二、算法原理(用直觉理解)
K-means 的过程可以分为 4 步:
-
确定簇的数量 K K K
比如我们想分 3 组,就设 K = 3 K=3 K=3。 -
随机选择 K 个初始“中心点”(Centroids)
-
将每个样本分配到离自己最近的中心点
计算“欧氏距离”,选择最近的那个中心。 -
更新中心点
对每一簇内的点求平均值,作为新的中心点。
然后反复执行第 3 和第 4 步,直到:
- 中心点几乎不变;或者
- 达到设定的最大迭代次数。
🧮 三、数学形式
设:
- 数据集为 X = { x 1 , x 2 , . . . , x n } X = \{x_1, x_2, ..., x_n\} X={x1,x2,...,xn},每个样本 x i ∈ R d x_i \in \mathbb{R}^d xi∈Rd
- 要分成 K K K 个簇 C 1 , C 2 , . . . , C K C_1, C_2, ..., C_K C1,C2,...,CK
- 每个簇的中心为 μ k \mu_k μk
K-means 的目标函数是最小化 簇内平方误差 (SSE):
J = ∑ k = 1 K ∑ x i ∈ C k ∣ ∣ x i − μ k ∣ ∣ 2 J = \sum_{k=1}^{K} \sum_{x_i \in C_k} ||x_i - \mu_k||^2 J=k=1∑Kxi∈Ck∑∣∣xi−μ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 K=2 K=2
假设我们想看看客户能否分成「普通客户」与「高价值客户」两类。
步骤 2:初始化两个中心点
随机选取两个点,例如:
- μ 1 = ( 500 , 2 ) \mu_1 = (500, 2) μ1=(500,2)
- μ 2 = ( 4000 , 15 ) \mu_2 = (4000, 15) μ2=(4000,15)
步骤 3:分配客户到最近中心
计算每个客户与两中心的欧氏距离,谁近归谁。
结果可能是:
- C1组(普通客户):A, B, C, D
- C2组(高价值客户):E, F
步骤 4:更新中心
对每组求均值:
μ 1 = ( 750 , 3.5 ) , μ 2 = ( 3900 , 14.5 ) \mu_1 = (750, 3.5), \quad \mu_2 = (3900, 14.5) μ1=(750,3.5),μ2=(3900,14.5)
重复步骤 3-4,直到中心不再变化。
📊 五、结果解释
最后,算法自动将客户分成两类:
| 客户类型 | 平均月消费 | 平均购物次数 | 营销策略 |
|---|---|---|---|
| 普通客户 | 750元 | 3.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_)
输出结果会告诉你每个客户属于哪一类,以及各组的中心。
参数
🧩 一、基础参数
1. n_clusters
- 含义:要划分的簇的数量 K K K。
- 默认值:
8 - 影响:这是最关键的参数,直接决定分群的粒度。
- 选择方法:常用“肘部法(Elbow Method)”或“轮廓系数(Silhouette Score)”来确定合适的 K K K。
2. init
-
含义:初始化簇中心的方法。
-
可选值:
'k-means++'(默认):通过概率分布方式挑选初始点,能提高稳定性;'random':随机选择初始点;- 也可直接传入一个自定义初始中心矩阵。
-
建议:几乎总是使用
'k-means++'。
3. n_init
- 含义:算法会用不同初始点运行多少次,选择效果最好的结果。
- 默认值(在 sklearn >=1.4 中):
'auto'(通常相当于10) - 建议:设置为较高的值(如
10~20),可以提高稳定性,减少陷入局部最优的风险。
4. max_iter
- 含义:每次运行的最大迭代次数。
- 默认值:
300 - 说明:K-means 是迭代算法;如果数据多、收敛慢,可以适当增大。
5. tol
- 含义:容差(收敛阈值),当簇中心变化小于此值时停止迭代。
- 默认值:
1e-4 - 作用:影响算法的停止条件。值越小,结果更精确,但计算时间更长。
6. random_state
- 含义:随机种子,确保结果可复现。
- 建议:调试时或需要复现结果时设定固定值,例如
random_state=42。
⚙️ 二、高级参数
1. algorithm
-
含义:选择具体的底层算法。
-
可选值:
'lloyd'(默认):传统的 Lloyd 算法;'elkan':使用三角不等式加速(只适用于欧氏距离);'auto':根据数据自动选择;'full'(旧版本别名,等价于'lloyd')。
-
建议:大多数情况下用默认值
'lloyd'即可;高维或稀疏数据可试'elkan'。
2. verbose
- 含义:是否输出详细日志。
- 值:整数(0 表示不输出,数字越大输出越多)
- 用途:调试或监控收敛过程时开启。
3. copy_x
- 含义:是否复制输入数据。
- 默认值:
True - 说明:若设为
False,原数据可能被算法修改,节省内存但需谨慎。
4. n_jobs(旧版本参数)
- 说明:并行计算任务数。在 sklearn 新版中已弃用(改用
joblib自动管理)。
🧠 三、一个示例:理解参数组合
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 |
| 提高精度(更精确收敛) | 减小 tol,增大 max_iter |
| 控制聚类数量 | 调整 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 si,衡量它与本簇和其他簇的相对紧密度:
s i = b i − a i max ( a i , b i ) s_i = \frac{b_i - a_i}{\max(a_i, b_i)} si=max(ai,bi)bi−ai
其中:
- a i a_i ai:样本与本簇内其他样本的平均距离;
- b i b_i bi:样本与最近邻簇中样本的平均距离。
整体平均轮廓系数 S S S 的取值范围为 [-1, 1],越接近 1 表示聚类越好。
实践步骤
- 对不同 K 值计算平均 Silhouette Score;
- 取最大值对应的 K。
优点
- 自动量化聚类质量;
- 不依赖主观视觉判断。
缺点
- 计算开销略大;
- 对形状复杂的簇不总是可靠。
📊 三、Gap Statistic 法(间隙统计)
原理
将真实数据的聚类结果与随机均匀分布数据的聚类结果作比较:
G a p ( K ) = E ∗ [ log ( W k ) ] − log ( W k ) Gap(K) = E^*[\log(W_k)] - \log(W_k) Gap(K)=E∗[log(Wk)]−log(Wk)
其中 W k W_k Wk 是簇内平方和。
当 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 pltinertias = []
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()
