【机器学习】1.聚类算法
·
机器学习聚类算法全梳理(原理+语法+案例+表格)
聚类是无监督学习的核心任务,目标是将相似样本归为同一簇,不同样本分至不同簇。本文系统梳理所有主流聚类算法,涵盖原理、语法、实战案例、优缺点及选型指南,基于Python sklearn 实现。
一、聚类算法总览
1.1 算法分类与核心特征表
| 算法类别 | 核心算法 | 核心思想 | 适用场景 | 核心参数 |
|---|---|---|---|---|
| 划分式聚类 | K-Means、K-Medoids、K-Modes | 划分为K个不重叠簇,最小化簇内误差(均值/中位数/众数为中心) | 凸形簇、样本量大、分布均匀 | K(簇数)、距离度量 |
| 层次聚类 | AGNES、DIANA | 凝聚式(合并簇)/分裂式(拆分簇),构建聚类树 | 小样本、需层次结构 | 链接方式(ward/average) |
| 密度基聚类 | DBSCAN、OPTICS | 基于密度聚类,簇是“密度相连”的点集 | 非凸簇、含噪声/离群点 | ɛ(邻域半径)、MinPts(最小样本数) |
| 模型基聚类 | GMM(EM) | 假设数据服从混合高斯分布,最大化似然估计(软聚类) | 非凸簇、需概率归属 | K(高斯分布数)、协方差类型 |
| 其他聚类 | 谱聚类、Mean Shift、Birch | 谱聚类(图论降维);Mean Shift(密度峰值);Birch(大规模增量聚类) | 谱聚类:非凸/高维;Birch:大数据 | 谱聚类gamma;Mean Shift带宽 |
1.2 评估指标(选算法/调参关键)
| 指标 | 适用场景 | 取值范围 | 最优值 | 核心作用 |
|---|---|---|---|---|
| 轮廓系数 | 无真实标签 | [-1, 1] | 接近1 | 衡量簇内紧凑性+簇间分离度 |
| 调整兰德指数(ARI) | 有真实标签 | [-1, 1] | 1 | 修正随机误差的聚类一致性 |
| 簇内平方和(Inertia) | KMeans专用 | [0, +∞) | 越小越好 | 衡量簇内样本与中心的距离和 |
二、划分式聚类(最常用)
2.1 K-Means(经典划分式)
核心原理
- 随机选K个初始聚类中心;
- 样本分配到最近的中心,更新簇均值为新中心;
- 重复至中心收敛或达到迭代次数(欧氏距离为默认度量)。
语法格式(sklearn.cluster.KMeans)
from sklearn.cluster import KMeans
# 初始化模型
kmeans = KMeans(
n_clusters=8, # 簇数(必须指定)
init='k-means++', # 初始中心(避免随机初始化弊端)
n_init=10, # 不同初始值运行次数(取最优)
max_iter=300, # 最大迭代次数
random_state=42 # 固定随机种子
)
# 训练+预测
labels = kmeans.fit_predict(X) # 聚类标签
centers = kmeans.cluster_centers_ # 聚类中心
inertia = kmeans.inertia_ # 簇内平方和
实战案例(鸢尾花数据集聚类)
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.datasets import load_iris
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import silhouette_score
# 1. 数据预处理
iris = load_iris()
X = iris.data[:, :2] # 取前2特征(萼片长/宽)
X_scaled = StandardScaler().fit_transform(X) # 标准化(KMeans对尺度敏感)
# 2. 肘部法则选最优K
inertias = []
k_range = range(1, 10)
for k in k_range:
kmeans = KMeans(n_clusters=k, random_state=42, n_init=10)
kmeans.fit(X_scaled)
inertias.append(kmeans.inertia_)
# 可视化肘部图
plt.figure(figsize=(8, 4))
plt.plot(k_range, inertias, 'o-', c='blue')
plt.xlabel('K (簇数)')
plt.ylabel('Inertia (簇内平方和)')
plt.title('肘部法则选最优K')
plt.show()
# 3. 训练K=3的模型(真实类别数为3)
kmeans = KMeans(n_clusters=3, random_state=42, n_init=10)
labels = kmeans.fit_predict(X_scaled)
# 4. 可视化聚类结果
plt.figure(figsize=(8, 6))
plt.scatter(X_scaled[:, 0], X_scaled[:, 1], c=labels, cmap='viridis', s=50, alpha=0.8)
plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], c='red', s=200, marker='*')
plt.xlabel('萼片长度(标准化)')
plt.ylabel('萼片宽度(标准化)')
plt.title('K-Means聚类结果(鸢尾花数据集)')
plt.show()
# 5. 评估:轮廓系数
print(f"轮廓系数:{silhouette_score(X_scaled, labels):.3f}")
结果分析
- 肘部图中K=3时曲线“变缓”,是最优簇数;
- 标准化后聚类效果更优(KMeans对特征尺度敏感);
- 轮廓系数≈0.4,说明簇内紧凑性中等。
优缺点
| 优点 | 缺点 |
|---|---|
| 计算高效(O(nkt))、易实现 | 需指定K、对离群点/非凸簇敏感 |
| 适用于大规模数据 | 初始中心敏感(k-means++缓解) |
2.2 K-Medoids(抗离群点的K-Means改进版)
核心原理
聚类中心是簇内实际样本(而非均值),损失函数为“样本到medoid的绝对距离和”,对离群点鲁棒。
语法格式(需安装scikit-learn-extra)
from sklearn_extra.cluster import KMedoids
kmedoids = KMedoids(
n_clusters=2,
metric='euclidean', # 距离度量
random_state=42
)
labels = kmedoids.fit_predict(X_scaled)
medoids = kmedoids.cluster_centers_ # 聚类中心(实际样本)
实战对比(抗离群点能力)
# 生成带离群点的模拟数据
np.random.seed(42)
X1 = np.random.normal([0,0], 0.5, (100,2))
X2 = np.random.normal([3,3], 0.5, (100,2))
outliers = np.array([[10,10], [11,11]])
X = np.vstack([X1, X2, outliers])
X_scaled = StandardScaler().fit_transform(X)
# KMeans vs KMedoids
kmeans = KMeans(n_clusters=2, random_state=42)
kmedoids = KMedoids(n_clusters=2, random_state=42)
labels_kmeans = kmeans.fit_predict(X_scaled)
labels_kmed = kmedoids.fit_predict(X_scaled)
# 可视化对比
fig, (ax1, ax2) = plt.subplots(1,2, figsize=(12,5))
ax1.scatter(X_scaled[:,0], X_scaled[:,1], c=labels_kmeans, cmap='viridis')
ax1.set_title('K-Means(被离群点拉偏)')
ax2.scatter(X_scaled[:,0], X_scaled[:,1], c=labels_kmed, cmap='viridis')
ax2.set_title('K-Medoids(抗离群点)')
plt.show()
优缺点
| 优点 | 缺点 |
|---|---|
| 抗离群点、中心可解释 | 计算效率低(O(n²k)),不适用于大数据集 |
2.3 K-Modes(针对分类数据)
核心原理
替换均值为“众数”,距离度量为“汉明距离”(不同特征数),专为分类特征设计。
语法格式(需安装kmodes)
from kmodes.kmodes import KModes
# 模拟分类数据(性别、职业、消费等级)
df = pd.DataFrame({
'gender': np.random.choice(['男','女'], 200),
'occupation': np.random.choice(['学生','上班族','自由职业'], 200),
'level': np.random.choice(['低','中','高'], 200)
})
# 训练模型
kmode = KModes(n_clusters=3, init='Huang', random_state=42)
labels = kmode.fit_predict(df.values)
# 输出聚类中心(众数)
print("聚类中心(各簇众数):\n", kmode.cluster_centroids_)
三、层次聚类(带层次结构)
核心原理
- 凝聚式(AGNES):从单个样本为簇,逐步合并最相似的簇;
- 分裂式(DIANA):从全样本为簇,逐步拆分最不相似的簇;
- 链接方式:ward(最小化簇内平方和)、average(平均距离)、complete(最远距离)。
语法格式(sklearn.cluster.AgglomerativeClustering)
from sklearn.cluster import AgglomerativeClustering
from scipy.cluster.hierarchy import dendrogram, linkage
# 1. 生成链接矩阵(用于绘制树状图)
link_mat = linkage(X_scaled, method='ward', metric='euclidean')
# 2. 绘制树状图(层次结构)
plt.figure(figsize=(12,6))
dendrogram(link_mat, truncate_mode='level', p=3)
plt.title('层次聚类树状图(Ward链接)')
plt.xlabel('样本索引')
plt.ylabel('欧氏距离')
plt.show()
# 3. 训练模型
agg = AgglomerativeClustering(n_clusters=3, linkage='ward')
labels = agg.fit_predict(X_scaled)
优缺点
| 优点 | 缺点 |
|---|---|
| 无需指定K、提供层次结构 | 计算效率低(O(n³))、无法回溯 |
四、密度基聚类(非凸簇+噪声)
4.1 DBSCAN(经典密度聚类)
核心概念
- ɛ:邻域半径;MinPts:邻域内最小样本数;
- 核心点:邻域内样本≥MinPts;边界点:在核心点邻域但自身非核心;噪声点:无归属。
语法格式(sklearn.cluster.DBSCAN)
from sklearn.cluster import DBSCAN
dbscan = DBSCAN(
eps=0.3, # 邻域半径
min_samples=5 # 最小样本数
)
labels = dbscan.fit_predict(X_scaled) # 噪声点标签为-1
# 核心点索引
core_idx = dbscan.core_sample_indices_
实战案例(月牙形非凸簇)
from sklearn.datasets import make_moons
# 生成月牙形数据
X, _ = make_moons(n_samples=200, noise=0.05, random_state=42)
X_scaled = StandardScaler().fit_transform(X)
# 训练DBSCAN
dbscan = DBSCAN(eps=0.3, min_samples=5)
labels = dbscan.fit_predict(X_scaled)
# 可视化
plt.figure(figsize=(8,6))
unique_labels = set(labels)
colors = ['red', 'blue', 'black'] # -1=噪声(黑色)
for label, color in zip(unique_labels, colors):
mask = (labels == label)
plt.scatter(X_scaled[mask,0], X_scaled[mask,1], c=color, label=f'簇{label}' if label!=-1 else '噪声')
plt.title('DBSCAN聚类(月牙形非凸簇)')
plt.legend()
plt.show()
# 输出结果
n_clusters = len(set(labels)) - (1 if -1 in labels else 0)
print(f"检测到簇数:{n_clusters},噪声点数:{list(labels).count(-1)}")
优缺点
| 优点 | 缺点 |
|---|---|
| 无需指定K、抗噪声、适配非凸簇 | 对ɛ/MinPts敏感、高维数据效果差 |
4.2 OPTICS(密度不均匀数据改进版)
解决DBSCAN对密度不均匀簇适配差的问题,无需严格指定ɛ,可生成层次聚类结果。
from sklearn.cluster import OPTICS
optics = OPTICS(min_samples=5, xi=0.05)
labels = optics.fit_predict(X_scaled)
五、模型基聚类(GMM软聚类)
核心原理
假设数据由多个高斯分布混合而成,通过EM算法求解:
- E步:计算样本属于每个高斯分布的后验概率(软聚类);
- M步:更新高斯分布的均值、协方差、权重。
语法格式(sklearn.mixture.GaussianMixture)
from sklearn.mixture import GaussianMixture
gmm = GaussianMixture(
n_components=2, # 高斯分布数(簇数)
covariance_type='full', # 协方差类型(full=独立协方差)
random_state=42
)
gmm.fit(X_scaled)
labels = gmm.predict(X_scaled) # 硬标签(最大概率簇)
probs = gmm.predict_proba(X_scaled) # 软标签(概率归属)
实战案例(软聚类置信度)
# 月牙形数据
X, _ = make_moons(n_samples=300, noise=0.1, random_state=42)
X_scaled = StandardScaler().fit_transform(X)
# 训练GMM
gmm = GaussianMixture(n_components=2, covariance_type='full', random_state=42)
labels = gmm.predict(X_scaled)
probs = gmm.predict_proba(X_scaled)
confidence = np.max(probs, axis=1) # 最大概率(置信度)
# 可视化(颜色深浅=置信度)
plt.figure(figsize=(8,6))
scatter = plt.scatter(X_scaled[:,0], X_scaled[:,1], c=labels, cmap='viridis',
s=50, alpha=0.8, norm=plt.Normalize(0,1))
plt.colorbar(scatter, label='聚类置信度(最大概率)')
plt.title('GMM软聚类(月牙形数据)')
plt.show()
优缺点
| 优点 | 缺点 |
|---|---|
| 软聚类、适配非凸簇、提供概率 | 需指定K、对离群点敏感、计算成本高 |
六、其他重要聚类算法
| 算法 | 核心特点 | 适用场景 |
|---|---|---|
| 谱聚类 | 图论降维后聚类,适配非凸/高维数据 | 小样本、非凸簇 |
| Mean Shift | 无参数,寻找密度峰值 | 无需指定K、密度聚类 |
| Birch | 增量式聚类,构建CF树 | 大规模数据(TB级) |
七、聚类算法选型指南
| 场景需求 | 推荐算法 | 关键调参 |
|---|---|---|
| 大规模+凸形簇 | KMeans/Birch | KMeans(n_clusters)、Birch(threshold) |
| 分类数据 | K-Modes | init(Huang/Cao) |
| 含噪声/离群点 | K-Medoids/DBSCAN | DBSCAN(eps, min_samples) |
| 非凸簇/密度不均匀 | OPTICS/GMM/谱聚类 | GMM(covariance_type) |
| 需层次结构 | 层次聚类/OPTICS | 层次聚类(linkage) |
| 软聚类/概率归属 | GMM | n_components |
| 无参数聚类 | DBSCAN/Mean Shift | Mean Shift(bandwidth) |
八、总结
- 优先尝试简单算法:KMeans(大规模/凸簇)、DBSCAN(非凸/噪声);
- 调参核心:KMeans用肘部法则/轮廓系数选K,DBSCAN调ɛ和MinPts;
- 数据预处理:数值特征标准化,分类特征用K-Modes;
- 评估:无标签用轮廓系数,有标签用ARI/AMI。
聚类算法的选择需结合数据特性(类型、规模、分布)和业务需求,实战中建议多算法对比,通过评估指标确定最优方案。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐
所有评论(0)