🏠 总目录📚 本教程 06 · 无监督:聚类降维
📑 本页目录(点开跳转)

06 · 无监督:聚类与降维

28 分钟 | 🎁 可以跳,但降维那半节很有用


🎯 一句话

没有标签的时候,你只能问两个问题:「哪些样本像?」(聚类)和 「能不能用更少的维度表示它?」(降维)。


⚠️ 先说一件最重要的事:无监督没有"正确答案"

   监督学习:有标签 → 有准确率 → 【客观】知道好不好

   无监督:  没标签 → 没有"对"的分法
             你把用户分成 3 类还是 5 类,都不能说谁错

   ⭐ 所以无监督的评估必须靠【外部标准】:
      · 这个分群在业务上讲得通吗?
      · 用它做出的下游决策有没有效果?
      · 换个随机种子结论还成立吗?

🔑 这是无监督最大的陷阱:算法永远会给你一个结果, 但"算法跑出来了"和"这个分法有意义"是两码事。 轮廓系数只能告诉你"簇分得紧不紧",不能告诉你"这个分法有没有用"。


🎯 一、K-Means:最常用的聚类

   ① 随机撒 K 个中心点
   ② 每个样本归到最近的中心
   ③ 每个中心移到自己那群样本的重心
   ④ 回到 ②,直到不再变化

        ○ ○        ×             ○ ○ ×
       ○ ○ ○           →        ○ ○ ○      → 收敛
          ×      ○ ○               × ○ ○

五个必须知道的坑

说明 解法
K 要自己定 算法不会告诉你该分几类 肘部法则、轮廓系数、业务意义
必须标准化 它用欧氏距离,尺度大的特征会主导 StandardScaler
只能找"球形"簇 长条形、环形的簇它分不好 换 DBSCAN / 谱聚类
初始化敏感 不同起点得到不同结果 n_init=10(跑 10 次取最好)⭐
对离群点敏感 一个极端点能把整个中心拽跑 先清离群点,或用 K-Medoids

🔗 数学原理第 13 章会告诉你K-Means 是高斯混合模型(GMM)的一个特例—— 它隐含假设了"所有簇都是同样大小的球"。 "只能找球形簇"不是工程缺陷,是这个假设的必然结果。

上面这四步用 numpy 写出来只要 12 行:🔗 附录 C 第 8 题。 值得专门去一趟,是因为它补了一个「照着四步写」一定会漏的分支:空簇。 某一轮没有任何点归到某个中心时,X[lab==j].mean(0) 对空数组求均值返回 nan, 下一轮所有距离全变 nan算法静默地烂掉——不报错,只是结果不对。 那边还把「⑤ n_init=10」这个坑写成了代码(跑 10 次取惯性最小的那次)。

怎么选 K

from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score

for k in range(2, 8):
    km = KMeans(n_clusters=k, n_init=10, random_state=0).fit(X_scaled)
    print(f"K={k}  惯性={km.inertia_:.0f}  "
          f"轮廓系数={silhouette_score(X_scaled, km.labels_):.3f}")
# 惯性(inertia):簇内平方和,一定随 K 单调下降 → 看【拐点】不是看最小值 ⭐
# 轮廓系数:-1~1,越接近 1 越好;接近 0 说明簇之间黏在一起;负数说明分错了

⚠️ 肘部法则的真相很多真实数据根本没有明显的肘部,曲线是平滑下降的。 这时候别硬找拐点——改用业务约束("运营团队最多能维护 5 个人群包"就是最好的 K)。

其他聚类算法

算法 特点 什么时候用
DBSCAN 按密度聚类,不用指定 K,能识别噪声点,能找任意形状 ⭐ 簇形状不规则、有明显噪声
层次聚类 产出树状图,能看到不同粒度的分组 想看层级结构,数据量小(O(n²))
高斯混合 GMM 软分配(一个点可以 70% 属于 A、30% 属于 B) 需要概率、簇是椭圆形
🔧 DBSCAN 的两个参数怎么定(想用再点)
   eps        :多近算"邻居"
   min_samples:一个点周围要有几个邻居才算"核心点"

   ⭐ 定 min_samples:一般取 2×维度
   ⭐ 定 eps:画 k-距离图(k = min_samples)
      对每个点算它到第 k 近邻的距离,排序后画出来
      → 曲线的【拐点】就是 eps
from sklearn.neighbors import NearestNeighbors
import numpy as np, matplotlib.pyplot as plt

k = 2 * X_scaled.shape[1]
d, _ = NearestNeighbors(n_neighbors=k).fit(X_scaled).kneighbors(X_scaled)
plt.plot(np.sort(d[:, -1]))   # ⭐ 看拐点

⚠️ DBSCAN 在高维上会失效——密度的概念在高维失去意义 (🔗 数学原理第 5 章 维度灾难)。 超过 10~20 维时先降维。


📉 二、PCA:降维的默认选择

PC1:方差最大PC2PCA 找的是「数据自己伸展的方向」,不是坐标轴方向沿 PC1 投影:点被拉得很开 → 信息多沿 PC2 投影:点挤在一起 → 丢掉也不太可惜⭐ 「方差大 = 信息多」的前提是:能区分【样本】。但它不保证能区分【标签】所以 PCA 降维有时会掉分 —— 分类任务想要有监督的降维,该用 LDA
PCA 找的是数据自己伸展的方向,不是坐标轴方向。⭐ 「方差大 = 信息多」的前提是能区分样本 —— 但它不保证能区分标签。所以 PCA 降维有时会掉分;分类任务想要有监督的降维,该用 LDA。

它在做什么:找到数据方差最大的几个方向,把数据投影上去。

   原始 2D 数据(沿对角线分布)        PCA 后
        ╱                            ────────►
       ╱ ● ●                          ● ● ● ●
      ╱● ● ●          →          (只保留主方向,
     ╱ ● ●                          垂直方向的信息丢掉)
    ╱
   主成分1 = 方差最大的方向
   主成分2 = 与1垂直、方差次大的方向

💡 人话:把一个立体物体投影到最能看清它形状的那个角度。丢掉的是"最不重要"的变化。

💡 为什么"方差大"就是"信息多"

一个特征如果所有样本上都一样(方差为 0),它没有区分任何东西,删掉不损失信息。 方差越大 → 样本在这个方向上差异越大 → 这个方向越能区分样本。 ⚠️ 但注意:"能区分样本" ≠ "能区分标签" —— 这是 PCA 最大的局限,见下。

from sklearn.decomposition import PCA
import numpy as np

pca = PCA().fit(X_scaled)
cum = np.cumsum(pca.explained_variance_ratio_)
print(f"保留 90% 方差需要 {np.argmax(cum >= 0.90) + 1} 个主成分"
      f"(原本 {X.shape[1]} 个)")

X_reduced = PCA(n_components=0.95).fit_transform(X_scaled)  # 直接指定保留比例

用途

用途 说明
加速训练 30 维压到 10 维,训练快 3 倍
去噪 丢掉的小方差方向往往是噪声
可视化 降到 2 维画图看数据分布
解决共线性 主成分之间天然正交
向量检索加速 推荐/搜索里降维后再建索引

⚠️ PCA 的四个注意

  1. 必须先标准化(否则量纲大的特征会主导主方向)—— 一个"年收入(万元)"和"年龄"放一起,不标准化的话 PC1 基本就是收入
  2. 主成分没有可解释性(PC1 是一堆原特征的加权和,说不清是什么)
  3. 它是无监督的——方差大 ≠ 对预测有用。有时候降维反而掉分
  4. ⚠️ 必须在训练集上 fit,再 transform 验证集 —— 在全量数据上 fit 是数据泄漏
# ❌ 泄漏:PCA 看到了验证集的分布
X_all = PCA(n_components=10).fit_transform(X)
tr, va = split(X_all)

# ✅ 正确:放进 Pipeline,CV 自动帮你处理
from sklearn.pipeline import make_pipeline
pipe = make_pipeline(StandardScaler(), PCA(n_components=10), LogisticRegression())

🔗 第 5 章那个纯噪声数据也能跑出 76.5% 准确率的泄漏实验, 就是这类错误的后果。PCA 是最容易泄漏的预处理之一,因为它看起来"只是转换"。

💡 关于第 3 点:有监督的替代品

   PCA:找【方差最大】的方向      ← 不看标签
   LDA:找【最能分开类别】的方向  ← 看标签 ⭐

   → 如果你的目标是分类,LDA 常常比 PCA 更有用
   → 但 LDA 最多只能降到 (类别数 − 1) 维

🎨 三、t-SNE / UMAP:只用来看图

   PCA:线性投影,保留【全局结构】,可以用来做特征
   t-SNE/UMAP:非线性,保留【局部邻域】,图好看

   ⚠️ 但是:
   · 它们的坐标轴【没有意义】
   · 簇之间的【距离没有意义】
   · 簇的【大小没有意义】
   · 换个随机种子图就变

🔑 一句话t-SNE/UMAP 只用来"看一眼数据有没有结构",绝不能拿降维结果当特征喂给模型,也不能用它的图下结论。 UMAP 比 t-SNE 快、更保留全局结构,现在更常用。

⚠️ t-SNE 的 perplexity 参数会显著改变图形

   perplexity 小(5)  → 碎成很多小簇(可能是假的)
   perplexity 大(50) → 融成大团

   ⭐ 正确用法:跑 3~4 个不同的 perplexity,
      【只相信在所有设置下都稳定出现的结构】

💡 一个可以做的自检把标签打乱,重跑 t-SNE。 如果打乱后的图看起来还是"有几个漂亮的簇"——说明那些簇是算法造出来的,不是数据里的。


🧭 三种降维怎么选

你的目的 用什么
压缩特征喂给模型 PCA(放 Pipeline 里)
分类任务的有监督降维 LDA
只是想看一眼数据结构 UMAP(画图,不当特征)
稀疏矩阵(文本 TF-IDF) TruncatedSVD(PCA 要中心化会破坏稀疏性)⭐
有类别特征的高维数据 Embedding(第 16 章)

🔗 和站内其他章的关系

相关的地方 这里的对应
推荐算法的 Embedding 也是一种降维——把高维 one-hot 压成低维稠密向量
推荐算法第 10 章向量检索 检索前常用 PCA 降维加速
数学原理第 13 章 K-Means 是 GMM 的特例——解释了球形簇的限制 ⭐
数学原理第 5 章 为什么高维上距离和密度都失效
第 5 章的数据泄漏 PCA 必须在 Pipeline 里 fit
Kaggle 第 1 章 竞赛里 PCA/SVD 常作为特征构造手段
全景导论第 10 章的 CLIP 对比学习也是无监督的一种

⚖️ 要不要深挖这一章

说实话:这一章是本教程里最能跳的。

你的情况 建议
做监督学习为主(分类/回归/推荐) 🟡 知道 PCA 和 K-Means 存在即可
做用户分群 / 数据探索 ✅ 聚类那半节要学
特征太多想压缩 ✅ PCA 那半节要学
想快速看数据有没有结构 ✅ 学会用 UMAP 画图

✅ 检查点

  1. 无监督最大的陷阱是什么?该靠什么评估?
  2. K-Means 的五个坑是什么?
  3. 为什么 K-Means 只能找球形簇?(说出根本原因)
  4. 肘部法则找不到拐点怎么办?
  5. 为什么"方差大"约等于"信息多"?这个逻辑在什么时候会失效?
  6. PCA 为什么必须放进 Pipeline?不放会怎样?
  7. 什么时候该用 LDA 而不是 PCA?
  8. t-SNE 的 perplexity 该怎么用?怎么自检簇是不是假的?
  9. 稀疏矩阵为什么该用 TruncatedSVD 而不是 PCA?
👀 答案
  1. 算法永远会给你结果,但"跑出来了"≠"有意义"。必须靠外部标准评估:业务上讲不讲得通、下游决策有没有效果、换种子结论还成不成立。
  2. K 要自己定、必须标准化、只能找球形簇、初始化敏感n_init=10)、对离群点敏感
  3. 因为 K-Means 是 GMM 的特例,隐含假设所有簇都是同样大小的球形高斯。这是假设的必然结果,不是工程缺陷。
  4. 很多真实数据根本没有明显肘部。这时改用业务约束(如"运营最多维护 5 个人群包")。
  5. 方差为 0 的特征不区分任何样本,删掉不损失信息;方差越大越能区分样本。失效场景:能区分样本 ≠ 能区分标签——PCA 是无监督的,方差大的方向可能对预测毫无用处。
  6. 因为在全量数据上 fit 会让 PCA 看到验证集的分布 → 数据泄漏,评估结果虚高。
  7. 目标是分类时。LDA 找"最能分开类别"的方向(看标签),PCA 只找方差最大(不看标签)。但 LDA 最多降到 (类别数−1) 维。
  8. 跑 3~4 个不同 perplexity,只相信在所有设置下都稳定出现的结构。自检:把标签打乱重跑,如果还是有漂亮的簇,说明那些簇是算法造的。
  9. PCA 要中心化(减均值),会把稀疏矩阵变稠密,内存爆炸。TruncatedSVD 不中心化,保持稀疏。

🛑 可以停在这里

走神救援

无监督问两个问题:哪些样本像(聚类)、能否用更少维度表示(降维)。⚠️ 最大陷阱:算法永远给结果,但"跑出来了"≠"有意义"——必须靠业务/下游效果评估。K-Means五坑:K要自己定、必须标准化、只能找球形簇(根因:它是GMM的特例,隐含假设等大球形)、初始化敏感(n_init=10)、离群点敏感。肘部常常根本不存在 → 改用业务约束定K。PCA找方差最大方向(方差大=能区分样本,但≠能区分标签,这是它最大局限 → 分类任务考虑 LDA);⚠️ 必须放 Pipeline 里 fit,否则泄漏;稀疏矩阵用 TruncatedSVD(PCA 要中心化会破坏稀疏)。t-SNE/UMAP只能用来看图——坐标轴、簇间距离、簇大小全无意义;perplexity 要跑多个只信稳定出现的结构;把标签打乱重跑还有漂亮簇 = 簇是假的。本章是最能跳的一章。

下一节 👉 07-从线性到神经网络.md

打卡记录保存在你的浏览器里,首页能看到总进度