03. 无监督学习与降维

K-Means、层次聚类、DBSCAN、PCA、t-SNE、UMAP、关联规则等无监督学习算法的原理与实战

无监督学习处理没有标签的数据,旨在发现隐藏的数据结构和模式。本文涵盖聚类、降维与关联规则三大方向的核心算法。

1. 聚类 (Clustering)

聚类将相似的数据点分到同一组。关键在于定义"相似性"和"簇的形状"。

1.1 K-Means 聚类

K-Means 最小化簇内平方和 (WCSS):

$$J = \sum_{i=1}^{k}\sum_{x \in C_i}|x - \mu_i|^2$$

算法步骤

  1. 随机选择 k 个初始中心点
  2. 将每个样本分配到最近的中心点所属簇
  3. 重新计算每个簇的中心点(均值)
  4. 重复 2-3 直到收敛
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler

# 标准化(K-Means 对尺度敏感)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# K-Means
kmeans = KMeans(
    n_clusters=4,         # 簇数量
    init='k-means++',     # 智能初始化
    n_init=10,            # 运行 10 次取最优
    max_iter=300,
    random_state=42
)
labels = kmeans.fit_predict(X_scaled)

# 簇中心与惯性
centers = kmeans.cluster_centers_
inertia = kmeans.inertia_  # WCSS

# 可视化
import matplotlib.pyplot as plt
plt.scatter(X_scaled[:, 0], X_scaled[:, 1], c=labels, cmap='viridis')
plt.scatter(centers[:, 0], centers[:, 1], c='red', marker='x', s=200)

1.2 肘部法则确定 K 值

inertias = []
K_range = range(1, 11)
for k in K_range:
    km = KMeans(n_clusters=k, random_state=42, n_init=10)
    km.fit(X_scaled)
    inertias.append(km.inertia_)

plt.plot(K_range, inertias, 'bo-')
plt.xlabel('K')
plt.ylabel('WCSS')
plt.title('Elbow Method')
plt.show()

1.3 轮廓系数 (Silhouette Score)

from sklearn.metrics import silhouette_score, silhouette_samples

score = silhouette_score(X_scaled, labels)  # [-1, 1],越高越好
sample_scores = silhouette_samples(X_scaled, labels)

1.4 层次聚类 (Hierarchical Clustering)

凝聚式(Agglomerative):从每个样本为一簇开始,逐步合并最近的簇。

from sklearn.cluster import AgglomerativeClustering
from scipy.cluster.hierarchy import dendrogram, linkage

# 层次聚类
agg = AgglomerativeClustering(
    n_clusters=4,
    linkage='ward',       # 'ward', 'complete', 'average', 'single'
    metric='euclidean'
)
labels = agg.fit_predict(X_scaled)

# 绘制树状图
Z = linkage(X_scaled, method='ward')
dendrogram(Z, truncate_mode='lastp', p=20)
plt.title('Hierarchical Clustering Dendrogram')
plt.show()
链接方式定义特点
Ward最小化合并后簇内方差倾向于球形簇
Complete两簇最远点距离对异常值敏感
Average两簇平均距离平衡
Single两簇最近点距离可发现链式簇

1.5 DBSCAN:基于密度的聚类

DBSCAN 通过密度连接发现任意形状的簇,自动识别噪声点。

from sklearn.cluster import DBSCAN

dbscan = DBSCAN(
    eps=0.5,              # 邻域半径
    min_samples=5         # 核心点最少邻居数
)
labels = dbscan.fit_predict(X_scaled)

# labels = -1 表示噪声点
n_clusters = len(set(labels)) - (1 if -1 in labels else 0)
n_noise = list(labels).count(-1)
print(f"发现 {n_clusters} 个簇,{n_noise} 个噪声点")

关键概念

  • 核心点:邻域内样本数 ≥ min_samples
  • 边界点:在核心点邻域内但自身不是核心点
  • 噪声点:既非核心也非边界

参数选择:通过 k-距离图确定 eps。

from sklearn.neighbors import NearestNeighbors

knn = NearestNeighbors(n_neighbors=5)
knn.fit(X_scaled)
distances, _ = knn.kneighbors(X_scaled)
distances = np.sort(distances[:, 4])  # 第 5 近邻距离
plt.plot(distances)
plt.ylabel('5-NN Distance')
# 拐点处作为 eps
算法簇形状需预设簇数处理噪声适用场景
K-Means球形大规模、簇大小均匀
层次聚类任意数据量较小、需树状结构
DBSCAN任意发现不规则簇、有噪声
GMM椭球形软聚类、概率归属

1.6 高斯混合模型 (GMM)

GMM 假设数据来自有限个高斯分布的叠加,提供软聚类(概率归属)。

from sklearn.mixture import GaussianMixture

gmm = GaussianMixture(
    n_components=4,
    covariance_type='full',  # 'full', 'tied', 'diag', 'spherical'
    random_state=42
)
gmm.fit(X_scaled)
labels = gmm.predict(X_scaled)
probs = gmm.predict_proba(X_scaled)  # 每个样本属于各簇的概率

# AIC/BIC 选模型
print(f"AIC: {gmm.aic(X_scaled)}, BIC: {gmm.bic(X_scaled)}")

2. 降维 (Dimensionality Reduction)

2.1 主成分分析 PCA

PCA 通过正交变换将相关变量转换为线性不相关的主成分,保留最大方差方向。

数学原理

  1. 数据标准化
  2. 计算协方差矩阵
  3. 协方差矩阵特征分解
  4. 取前 k 个最大特征值对应的特征向量
from sklearn.decomposition import PCA

pca = PCA(n_components=0.95)  # 保留 95% 方差,或指定整数维度
X_pca = pca.fit_transform(X_scaled)

print(f"原始维度: {X.shape[1]} → 降维后: {X_pca.shape[1]}")
print(f"各主成分方差比例: {pca.explained_variance_ratio_}")
print(f"累计方差比例: {np.cumsum(pca.explained_variance_ratio_)}")

# 可视化方差
plt.plot(np.cumsum(pca.explained_variance_ratio_))
plt.xlabel('Components')
plt.ylabel('Cumulative Explained Variance')
plt.axhline(y=0.95, color='r', linestyle='--')

2.2 核 PCA

from sklearn.decomposition import KernelPCA

kpca = KernelPCA(
    n_components=2,
    kernel='rbf',         # 'linear', 'poly', 'rbf', 'sigmoid'
    gamma=0.04
)
X_kpca = kpca.fit_transform(X_scaled)

2.3 t-SNE:可视化降维

t-SNE 保留局部邻域结构,适合高维数据可视化。

from sklearn.manifold import TSNE

tsne = TSNE(
    n_components=2,
    perplexity=30,        # 邻居数量,5-50
    learning_rate='auto',
    n_iter=1000,
    random_state=42,
    n_jobs=-1
)
X_tsne = tsne.fit_transform(X_scaled)

plt.scatter(X_tsne[:, 0], X_tsne[:, 1], c=y, cmap='tab10')
plt.title('t-SNE Visualization')

注意

  • t-SNE 是随机的,每次结果不同
  • 主要用于可视化,不建议用于后续建模(信息有损失,不稳定)
  • 大数据集(>10k)先用 PCA 降到 50 维再用 t-SNE

2.4 UMAP:更快速的新选择

import umap

reducer = umap.UMAP(
    n_neighbors=15,
    min_dist=0.1,
    n_components=2,
    random_state=42
)
X_umap = reducer.fit_transform(X_scaled)

plt.scatter(X_umap[:, 0], X_umap[:, 1], c=y, cmap='tab10')

UMAP 相比 t-SNE:

  • 更快(支持大数据集)
  • 更好地保留全局结构
  • 支持 transform 新数据点
方法原理线性/非线性支持 transform适用场景
PCA最大方差投影线性预处理、特征压缩
LDA类间散度最大化线性有标签时的降维
t-SNE邻域概率分布匹配非线性可视化
UMAP流形学习 + 拓扑非线性可视化 + 特征表示
Autoencoder神经网络编码非线性深度学习表示

3. 异常检测

3.1 基于统计的方法

from sklearn.ensemble import IsolationForest
from sklearn.neighbors import LocalOutlierFactor

# Isolation Forest:通过随机特征分割隔离异常点
iso = IsolationForest(contamination=0.1, random_state=42)
outliers = iso.fit_predict(X_scaled)  # -1 为异常,1 为正常

# LOF:局部异常因子
lof = LocalOutlierFactor(n_neighbors=20, contamination=0.1)
outliers = lof.fit_predict(X_scaled)

3.2 基于重建误差

from sklearn.decomposition import PCA

# 用 PCA 重建,异常点重建误差大
pca = PCA(n_components=0.95)
X_pca = pca.fit_transform(X_scaled)
X_reconstructed = pca.inverse_transform(X_pca)
reconstruction_error = np.mean((X_scaled - X_reconstructed)**2, axis=1)

threshold = np.percentile(reconstruction_error, 95)
anomalies = reconstruction_error > threshold

4. 关联规则 (Association Rules)

4.1 Apriori 算法

挖掘"如果购买 A,那么也购买 B"的规则。

三个核心指标

  • 支持度 (Support):$P(A \cup B) = \frac{包含 A 和 B 的交易数}{总交易数}$
  • 置信度 (Confidence):$P(B|A) = \frac{P(A \cup B)}{P(A)}$
  • 提升度 (Lift):$\frac{P(B|A)}{P(B)}$,>1 表示正相关
from mlxtend.frequent_patterns import apriori, association_rules
from mlxtend.preprocessing import TransactionEncoder

# 交易数据
transactions = [
    ['牛奶', '面包', '尿布'],
    ['牛奶', '尿布', '啤酒', '鸡蛋'],
    ['牛奶', '面包', '尿布', '啤酒'],
    ['面包', '鸡蛋'],
    ['面包', '尿布', '啤酒']
]

# 编码为 One-Hot
te = TransactionEncoder()
te_array = te.fit_transform(transactions)
df = pd.DataFrame(te_array, columns=te.columns_)

# 挖掘频繁项集
frequent_itemsets = apriori(df, min_support=0.4, use_colnames=True)

# 生成关联规则
rules = association_rules(frequent_itemsets, metric="confidence", min_threshold=0.7)
print(rules[['antecedents', 'consequents', 'support', 'confidence', 'lift']])

4.2 FP-Growth(更高效)

from mlxtend.frequent_patterns import fpgrowth

frequent_itemsets = fpgrowth(df, min_support=0.4, use_colnames=True)

FP-Growth 用频繁模式树 (FP-Tree) 避免 Apriori 的候选项集生成,速度提升一个数量级。

5. 完整实战:客户分群

import pandas as pd
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA

# 加载客户数据
df = pd.read_csv('customers.csv')
features = ['recency', 'frequency', 'monetary', 'age', 'tenure']
X = df[features]

# 标准化
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# K-Means 分群
kmeans = KMeans(n_clusters=4, random_state=42, n_init=10)
df['cluster'] = kmeans.fit_predict(X_scaled)

# 簇特征分析
cluster_summary = df.groupby('cluster')[features].mean()
print(cluster_summary)

# PCA 可视化
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X_scaled)
plt.scatter(X_pca[:, 0], X_pca[:, 1], c=df['cluster'], cmap='Set1')
plt.xlabel('PC1')
plt.ylabel('PC2')
plt.title('Customer Segments')
plt.colorbar(label='Cluster')

# 标签解读
# Cluster 0: 高价值忠诚客户 → VIP 服务
# Cluster 1: 流失风险客户 → 召回策略
# Cluster 2: 新客户 → 引导升级
# Cluster 3: 低频客户 → 促销激活

总结

任务推荐算法关键超参数评估指标
聚类 (球形)K-MeansK轮廓系数、WCSS
聚类 (任意形状)DBSCANeps, min_samples噪声比、簇数
聚类 (软划分)GMMn_componentsAIC/BIC
降维 (预处理)PCAn_components (方差比)重建误差
降维 (可视化)t-SNE/UMAPperplexity/n_neighbors视觉解释
异常检测Isolation ForestcontaminationAUC-PR
关联规则FP-Growthmin_support, min_confidenceLift

无监督学习的评价比监督学习更主观,需要结合业务含义验证聚类结果。建议的验证方法:

  1. 多个算法对照,看结果是否一致
  2. 簇内方差小、簇间距离大
  3. 与业务指标关联(如客户分群的消费差异显著)
  4. 可视化检查(PCA/t-SNE 投影)

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「ai-ml」更多文章

  1. 13. 大语言模型应用开发
  2. 12. MLOps 与实验管理
  3. 11. 模型部署与推理优化