人工智能之核心基础 机器学习
第九章 聚类算法
9.1 K-Means 聚类
🎯 核心思想:让“群内紧凑,群间分离”
想象你要在操场上把学生分成 K 组做游戏,目标是:
- 每组学生站得尽量近
- 不同组之间离得尽量远
K-Means 就是通过不断调整“组长位置”(聚类中心)来实现这个目标。
🔑 算法步骤(迭代优化)
- 随机选 K 个点作为初始中心
- 分配:每个样本归到最近的中心(用欧氏距离)
- 更新:重新计算每个簇的新中心(均值)
- 重复 2~3,直到中心不再变化或达到最大迭代次数
✅ 距离度量:默认使用欧氏距离
❓ 如何选择 K 值?——两大经典方法
方法1:肘部法则(Elbow Method)
- 计算不同 K 下的簇内平方和(WCSS):
- WCSS 随 K 增大而减小
- 找“拐点”(像手肘)——再增加 K,WCSS 下降变缓
方法2:轮廓系数(Silhouette Coefficient)
-
衡量样本与其所在簇的相似度 vs 与其他簇的不相似度
-
取值范围:[-1, 1],越接近1越好
-
公式:
- :样本 i 到同簇其他点的平均距离
- :样本 i 到最近其他簇的平均距离
💡 推荐:优先看轮廓系数,更可靠!
🧪 K-Means 代码实现
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
from sklearn.metrics import silhouette_score
# 生成模拟数据
X, _ = make_blobs(n_samples=300, centers=4, cluster_std=1.0, random_state=42)
# 肘部法则选K
wcss = []
sil_scores = []
K_range = range(2, 10)
for k in K_range:
kmeans = KMeans(n_clusters=k, random_state=42)
kmeans.fit(X)
wcss.append(kmeans.inertia_) # WCSS
sil_scores.append(silhouette_score(X, kmeans.labels_))
# 可视化
fig, ax = plt.subplots(1, 2, figsize=(12, 4))
ax[0].plot(K_range, wcss, 'bo-')
ax[0].set_title('肘部法则')
ax[0].set_xlabel('K')
ax[0].set_ylabel('WCSS')
ax[1].plot(K_range, sil_scores, 'ro-')
ax[1].set_title('轮廓系数')
ax[1].set_xlabel('K')
ax[1].set_ylabel('Silhouette Score')
plt.show()
# 最终聚类(假设选K=4)
kmeans = KMeans(n_clusters=4, random_state=42)
y_pred = kmeans.fit_predict(X)
plt.scatter(X[:, 0], X[:, 1], c=y_pred, cmap='viridis', s=30)
plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1],
c='red', marker='x', s=200, linewidths=3)
plt.title("K-Means 聚类结果 (K=4)")
plt.show()
9.2 层次聚类(Hierarchical Clustering)
🌳 核心思想:构建“族谱树”
不像 K-Means 需要预先指定 K,层次聚类会生成一棵树状图(Dendrogram),你可以在任意高度切一刀得到想要的簇数。
两种方式:
| 类型 | 过程 | 特点 |
|---|---|---|
| 凝聚式(Agglomerative) | 自底向上:每个点是一簇 → 逐步合并最相似的两簇 | ✅ 常用,适合中小数据 |
| 分裂式(Divisive) | 自顶向下:所有点是一簇 → 逐步分裂 | ❌ 计算复杂,少用 |
🔍 距离度量(簇间距离)
- 单链接(Single Linkage):两簇中最近两点的距离 → 易产生“链式效应”
- 全链接(Complete Linkage):两簇中最远两点的距离 → 簇更紧凑
- 平均链接(Average Linkage):所有点对的平均距离 → 平衡
- Ward 法:合并后WCSS增加最小 → 类似K-Means,推荐!
🧪 层次聚类代码
from scipy.cluster.hierarchy import dendrogram, linkage
from sklearn.cluster import AgglomerativeClustering
# 凝聚式层次聚类
linked = linkage(X, method='ward') # Ward法
# 绘制树状图
plt.figure(figsize=(10, 5))
dendrogram(linked, truncate_mode='level', p=5) # 只显示最后5层
plt.title("层次聚类树状图")
plt.xlabel("样本/簇")
plt.ylabel("距离")
plt.show()
# 指定K=4进行聚类
hac = AgglomerativeClustering(n_clusters=4, linkage='ward')
y_hac = hac.fit_predict(X)
plt.scatter(X[:, 0], X[:, 1], c=y_hac, cmap='plasma', s=30)
plt.title("层次聚类结果 (K=4)")
plt.show()
9.3 DBSCAN 聚类(基于密度)
⚡ 核心思想:找“人多的地方”,忽略“孤魂野鬼”
K-Means 假设簇是球形的,但现实数据可能有任意形状(如月牙、环形)。 DBSCAN 通过密度发现任意形状的簇,并自动识别噪声点!
🔑 四大核心概念
| 概念 | 定义 |
|---|---|
| ε 邻域(Epsilon Neighborhood) | 以点为中心、半径 ε 的圆内所有点 |
| 核心点(Core Point) | ε 邻域内至少有 MinPts 个点(包括自己) |
| 边界点(Border Point) | 在某核心点的 ε 邻域内,但自身不是核心点 |
| 噪声点(Noise Point) | 既不是核心点,也不在任何核心点邻域内 |
✅ 优点:
- 无需指定簇数量
- 能发现任意形状簇
- 自动剔除噪声
❌ 缺点:
- 对参数 ε 和 MinPts 敏感
- 密度差异大的数据效果差
🧪 DBSCAN 代码
from sklearn.cluster import DBSCAN
# DBSCAN聚类
dbscan = DBSCAN(eps=1.5, min_samples=5)
y_db = dbscan.fit_predict(X_with_outliers) # 使用前面加了异常点的数据
# 可视化
plt.scatter(X_with_outliers[y_db != -1, 0], X_with_outliers[y_db != -1, 1],
c=y_db[y_db != -1], cmap='Set1', s=30, label='正常簇')
plt.scatter(X_with_outliers[y_db == -1, 0], X_with_outliers[y_db == -1, 1],
c='black', marker='x', s=100, label='噪声点')
plt.title("DBSCAN 聚类结果")
plt.legend()
plt.show()
print(f"发现 {len(set(y_db)) - (1 if -1 in y_db else 0)} 个簇")
print(f"噪声点数量: {list(y_db).count(-1)}")
9.4 聚类评估指标
📌 注意:无监督学习没有真实标签,所以不能用准确率!只能用内部指标(仅基于数据和聚类结果)
| 指标 | 公式思想 | 越好方向 | 特点 |
|---|---|---|---|
| 轮廓系数(Silhouette) | 群内紧密 vs 群间分离 | 越大越好(max=1) | 直观,推荐首选 |
| Calinski-Harabasz(CH) | 簇间离散 / 簇内离散 | 越大越好 | 计算快,适合凸形簇 |
| Davies-Bouldin(DB) | 平均簇内距 / 簇间距 | 越小越好 | 对K-Means友好 |
from sklearn.metrics import calinski_harabasz_score, davies_bouldin_score
labels = kmeans.labels_
print("轮廓系数:", silhouette_score(X, labels))
print("CH指数:", calinski_harabasz_score(X, labels))
print("DB指数:", davies_bouldin_score(X, labels))
9.5 实战案例
案例1:K-Means 用户分群(电商场景)
# 模拟用户数据:年消费、访问频率、平均订单金额
np.random.seed(42)
users = np.random.rand(500, 3)
users[:, 0] *= 10000 # 年消费:0~10000元
users[:, 1] *= 50 # 访问频率:0~50次/月
users[:, 2] *= 500 # 平均订单:0~500元
# 标准化(K-Means对尺度敏感!)
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
users_scaled = scaler.fit_transform(users)
# 聚类
kmeans = KMeans(n_clusters=3, random_state=42)
user_clusters = kmeans.fit_predict(users_scaled)
# 分析各群特征
import pandas as pd
df = pd.DataFrame(users, columns=['年消费', '访问频率', '平均订单'])
df['群组'] = user_clusters
print(df.groupby('群组').mean())
输出示例:
年消费 访问频率 平均订单
群组
0 8500.2 45.1 420.3 → 高价值用户
1 1200.5 10.2 80.1 → 普通用户
2 5000.8 30.5 200.7 → 中等活跃用户
案例2:DBSCAN 异常交易检测
# 模拟交易数据:金额、时间(小时)、地点(经纬度简化)
transactions = np.random.randn(1000, 3)
transactions[:, 0] = np.abs(transactions[:, 0]) * 1000 # 金额 >0
transactions[:, 1] = (transactions[:, 1] + 12) % 24 # 时间 0-24
# 加入异常交易:深夜大额
anomalies = np.array([[15000, 3, 0.5], [20000, 2, -0.8]])
transactions_full = np.vstack([transactions, anomalies])
# DBSCAN检测
dbscan = DBSCAN(eps=2.0, min_samples=10)
labels = dbscan.fit_predict(transactions_full)
# 输出异常交易
anomaly_indices = np.where(labels == -1)[0]
print("检测到异常交易:")
for idx in anomaly_indices:
amt, hour, loc = transactions_full[idx]
print(f" 金额: ¥{amt:.0f}, 时间: {hour:.1f}点, 位置特征: {loc:.2f}")
🎯 本章总结:三大聚类算法对比
| 算法 | 是否需指定K | 簇形状 | 噪声处理 | 速度 | 适用场景 |
|---|---|---|---|---|---|
| K-Means | ✅ 是 | 球形 | ❌ 不能 | ⭐⭐⭐⭐ | 用户分群、快速原型 |
| 层次聚类 | ❌ 否(可后选) | 球形 | ❌ 不能 | ⭐⭐ | 小数据、需要树状结构 |
| DBSCAN | ❌ 否 | 任意 | ✅ 自动识别 | ⭐⭐⭐ | 异常检测、非球形簇 |
💡 建议:
- 先试 K-Means(快、简单)
- 如果簇形状奇怪 → 用 DBSCAN
- 数据量小且想探索层次关系 → 用 层次聚类
资料关注
公众号:咚咚王 gitee:gitee.com/wy185850518…

《Python编程:从入门到实践》 《利用Python进行数据分析》 《算法导论中文第三版》 《概率论与数理统计(第四版) (盛骤) 》 《程序员的数学》 《线性代数应该这样学第3版》 《微积分和数学分析引论》 《(西瓜书)周志华-机器学习》 《TensorFlow机器学习实战指南》 《Sklearn与TensorFlow机器学习实用指南》 《模式识别(第四版)》 《深度学习 deep learning》伊恩·古德费洛著 花书 《Python深度学习第二版(中文版)【纯文本】 (登封大数据 (Francois Choliet)) (Z-Library)》 《深入浅出神经网络与深度学习+(迈克尔·尼尔森(Michael+Nielsen)》 《自然语言处理综论 第2版》 《Natural-Language-Processing-with-PyTorch》 《计算机视觉-算法与应用(中文版)》 《Learning OpenCV 4》 《AIGC:智能创作时代》杜雨+&+张孜铭 《AIGC原理与实践:零基础学大语言模型、扩散模型和多模态模型》 《从零构建大语言模型(中文版)》 《实战AI大模型》 《AI 3.0》