CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
机器学习入门/课时/无监督学习
RawBlame
课时目录12 节

机器学习入门

  1. 01机器学习是什么
  2. 02数学基础
  3. 03Python 与数据栈
  4. 04数据预处理
  5. 05监督学习
  6. 06无监督学习
  7. 07模型评估
  8. 08Scikit-learn 工作流
  9. 09深度学习基础
  10. 10NLP 与 Transformer
  11. 11TensorFlow 与 PyTorch
  12. 12综合练习

无监督学习

聚类、PCA、Autoencoder。

35 分钟

无监督学习

这一课你将能做到

  1. 用 K-Means 把题目自动聚成「简单/中等/困难」三档,并给每簇赋予业务含义
  2. 用肘部法则和轮廓系数回答「K 到底取几」
  3. 用 PCA 把高维题目特征压到 2 维画散点图,看清楚聚类的结构

为什么要学

不是所有数据都有标签。给全站几百道题人工标注难度费时费力,但每道题的「正确率、平均用时、平均尝试次数」现成就有——能不能让算法自己把题目分成几档?这就是无监督学习:没有标准答案,从数据里发现结构。

两个最常用的工具:K-Means 负责分组(题目分难度档、用户分人群画像),PCA 负责压缩(几十维特征压成 2-3 维用于可视化和降噪)。本站「题目自动分级」和「用户画像分群」都能直接落地。

先建立图像

K-Means 迭代过程(二维示意):

第1轮        第2轮        收敛
×   ●        ×   ●        ×   ●
  ×    ●       ×    ●  →     ×    ●      ×=一簇  ●=另一簇
 ① ②          ① ②            ① ②        ①②=质心
步骤:随机放质心 → 每个点归最近质心 → 质心移到簇中心 → 重复直到不动

跟着做

步骤 1:构造题目特征表

import numpy as np
import pandas as pd

rng = np.random.default_rng(42)
n = 200
# 造三类题目:简单(70) / 中等(80) / 困难(50),但算法不知道这个标签
accuracy = np.concatenate([
    rng.uniform(0.75, 0.98, 70),
    rng.uniform(0.40, 0.75, 80),
    rng.uniform(0.05, 0.40, 50),
])
seconds  = 230 - 150 * accuracy + rng.normal(0, 15, n)   # 越难用时越长
attempts = 1 + (1 - accuracy) * 6 + rng.normal(0, 0.4, n) # 越难尝试越多

步骤 2:标准化 + K-Means 聚类

from sklearn.preprocessing import StandardScaler
from sklearn.cluster import KMeans

X = StandardScaler().fit_transform(np.column_stack([accuracy, seconds, attempts]))
km = KMeans(n_clusters=3, n_init=10, random_state=42)
labels = km.fit_predict(X)

df = pd.DataFrame({"accuracy": accuracy.round(2), "seconds": seconds.round(0),
                   "attempts": attempts.round(1), "cluster": labels})
summary = df.groupby("cluster").mean().round(2)
print(summary)

看输出给簇起名:正确率高/用时短/尝试少的那簇是「简单题」,反之是「困难题」。聚出来的簇没有名字,解释权在业务手里——这是无监督和监督最大的区别。

步骤 3:K 取几?肘部法则 + 轮廓系数

from sklearn.metrics import silhouette_score

for k in range(2, 8):
    m = KMeans(n_clusters=k, n_init=10, random_state=42).fit(X)
    sil = silhouette_score(X, m.labels_)
    print(f"k={k}  inertia={m.inertia_:8.1f}  silhouette={sil:.3f}")
  • inertia(簇内平方和):随 k 增大单调下降,找「下降骤缓的拐点」(肘部);
  • 轮廓系数:[-1, 1],越高说明「簇内紧、簇间远」,一般 > 0.5 算结构清晰。

两个指标 + 业务需要(产品上就想要三档难度),三者合起来定 K。

步骤 4:PCA 降维可视化

from sklearn.decomposition import PCA import matplotlib.pyplot as plt plt.rcParams["font.sans-serif"] = ["SimHei"] plt.rcParams["axes.unicode_minus"] = False pca = PCA(n_components=2) X2 = pca.fit_transform(X) print("各主成分方差占比:", pca.explained_variance_ratio_.round(3)) plt.scatter(X2[:, 0], X2[:, 1], c=labels, cmap="viridis", s=15) plt.xlabel("主成分1"); plt.ylabel("主成分2"); plt.title("题目聚类 PCA 可视化") plt.colorbar(label="簇") plt.show()

200 道题、3 个特征压成平面上的三个色块,肉眼可辨。特征有 20 个时 PCA 的价值才真正显现——你不可能肉眼画 20 维。

讲清楚要点

  1. 无监督没有「对错」,只有「有没有用」:聚类的评估不是准确率,而是轮廓系数这类内部指标 + 业务解释力。同一个数据集聚成 3 类或 5 类都可能合理,取决于用途。
  2. K-Means 三步循环:初始化质心(k-means++ 让初始点尽量分散)→ 每个样本归最近的质心 → 质心更新为簇均值,重复到收敛。对初值敏感,所以要 n_init=10 多跑几轮取最优。
  3. 标准化对 K-Means 是生死线:K-Means 基于欧氏距离,「用时 200 秒」和「正确率 0.8」量纲差 250 倍,不标准化则聚类完全被用时一个特征主导。
  4. PCA 找方差最大的方向:第一主成分是数据「最伸展」的方向,第二主成分与它垂直且次之。explained_variance_ratio_ 告诉你每个方向保留了多少信息(常用累计 90%-95% 做取舍)。
  5. PCA 的两个用途:可视化(降到 2-3 维)与降噪提速(高维数据先 PCA 再喂模型,训练更快且能缓解维度灾难)。

你可能会懵的地方

  • 聚类结果一定是「对的」吗? 不存在「对」。算法只是按距离把数据分了堆,堆的含义靠业务解释。危险的是把簇标签当成真值标签直接拿去做监督学习的 ground truth——错了没人发现。
  • K-Means 一定要球形簇吗? 是的,它隐含假设簇是「大小相近的凸球」(基于欧氏距离+均值质心)。簇是月牙形、长条形时用它就是错的,改用 DBSCAN 或层次聚类。
  • PCA 之后的特征还能解释业务吗? 主成分是原特征的线性组合,本身没有业务名字。建模可以用,向产品解释时需要换回原特征(看 pca.components_ 的系数)。
  • 为什么我聚出来的簇大小悬殊? 正常现象,真实分布本来就偏。K-Means 倾向切出均等的球,若业务需要「长尾自然分布」,考虑 KMeans 换 GMM(高斯混合)或直接用分位数切档。
  • 用户分群和题目分档,特征该怎么选? 原则一致:选「区分目的相关」的特征。分难度用正确率/用时/尝试次数;分人群用活跃度/正确率/知识点覆盖度。塞一堆无关特征只会稀释结构。

错法对照

错法问题正解
原始量纲直接 K-Means大数值特征主导距离先 StandardScaler 再聚类
把簇标签当真值评估「准确率」无监督没有真值用轮廓系数/业务评审来检验
k 无脑取 3 或 8簇过多失去业务含义肘部法则 + 轮廓系数 + 业务需求共同定
PCA 后不看 explained_variance_ratio丢了关键信息不自知累计方差 ≥ 90% 再决定保留几个成分
用欧氏距离聚类 One-Hot 高维稀疏特征距离区分度极差连续特征聚类,类别维度单独处理

卡点急救

  1. KMeans 警告 memory leak on Windows with MKL:Windows + sklearn 老版本的已知问题,升级 scikit-learn 即可;不影响结果正确性。
  2. 轮廓系数报错 k=1:silhouette_score 至少要 2 个簇,循环从 range(2, 8) 开始。
  3. 聚类结果每次跑都不一样:没固定 random_state,或没设 n_init;两者都固定后结果可复现。

面试常问

  • K-Means 的原理和主要缺点? 原理:随机初始化 K 个质心,反复「样本归最近质心、质心移到簇均值」直到收敛,最小化簇内平方和。缺点:要预先指定 K、对初值和离群点敏感、只适合球形凸簇、对量纲敏感(必须先标准化)。
  • PCA 是怎么降维的?什么时候用? 对协方差矩阵做特征值分解,取方差最大的若干方向作为新坐标轴,投影实现降维。用途:高维可视化、去相关降噪、加速训练、缓解维度灾难;前提是特征间存在相关性(否则压不出意义)。
  • 怎么评价聚类的好坏? 内部指标:轮廓系数(簇内紧簇间远)、inertia 拐点、DB 指数;外部验证:与业务专家标注对照、看簇的下游效果(分档后推题点击率是否提升)。

自测三问

  1. 为什么 K-Means 之前必须标准化?
  2. 肘部法则看的是哪个量?轮廓系数什么范围算好?
  3. PCA 的第一主成分是什么方向的?怎么知道保留几个成分够用?

小结一句话

没有标签也能干活:K-Means 把相似的东西分堆(记得标准化、科学选 K),PCA 把高维压扁好看好算——簇的含义由业务解释,不是算法给的。

延伸

  • scikit-learn 聚类指南
  • 下一课:ml-eval 模型评估——准确率的陷阱、精确率召回率的取舍、AUC 和交叉验证。
加载本节练习…
← 上一课监督学习下一课 →模型评估