机器学习聚类算法全梳理(原理+语法+案例+表格)

聚类是无监督学习的核心任务,目标是将相似样本归为同一簇,不同样本分至不同簇。本文系统梳理所有主流聚类算法,涵盖原理、语法、实战案例、优缺点及选型指南,基于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(经典划分式)

核心原理
  1. 随机选K个初始聚类中心;
  2. 样本分配到最近的中心,更新簇均值为新中心;
  3. 重复至中心收敛或达到迭代次数(欧氏距离为默认度量)。
语法格式(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)

八、总结

  1. 优先尝试简单算法:KMeans(大规模/凸簇)、DBSCAN(非凸/噪声);
  2. 调参核心:KMeans用肘部法则/轮廓系数选K,DBSCAN调ɛ和MinPts;
  3. 数据预处理:数值特征标准化,分类特征用K-Modes;
  4. 评估:无标签用轮廓系数,有标签用ARI/AMI。

聚类算法的选择需结合数据特性(类型、规模、分布)和业务需求,实战中建议多算法对比,通过评估指标确定最优方案。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐