1502scikit中的k-means
📌 一、 课程导入(5 分钟)
回顾旧知:上节课学习了 k-means 的核心概念和手算过程。今天的目标是让计算机替我们完成这些繁琐的迭代计算。
展示“成品”: 课前运行一段 k-means 代码,现场演示:
- 生成一组二维数据(散点图)。
- 运行 KMeans,K=3,自动聚类。
- 将聚类结果可视化(不同颜色标记不同簇 + 质心用特殊符号标出)。
核心疑问:
- 代码只有几行,如何确保结果稳定可靠?
- K 值应该怎么选?是随便拍脑袋定吗?
本节课路线图:
- KMeans 基础代码(训练、预测、可视化)
- 关键参数详解(
n_init、random_state的作用) - 手肘法 —— 科学地选择 K 值
- 数据标准化 —— 让距离计算更有意义
- 👨🏫 教师活动:在 Jupyter Notebook 中实时演示 KMeans 的完整代码;将
random_state改为不同值,展示聚类结果的差异。 - 🧑🎓 学生活动:观察聚类结果的可视化图像;思考“为什么同样的数据,不同运行结果会不一样”。
代码演示 + 即时可视化让学生看到“学以致用”的效果。“不同 random_state 导致不同结果”的现象为后续讲解初始化敏感性埋下伏笔。
📖 二、 解决问题过程(一):KMeans 基础代码
1. 最基础的 KMeans 实现
2. 可视化聚类结果
3. 核心 API 总结
| 属性/方法 | 作用 |
|---|---|
KMeans(n_clusters=K) |
创建 KMeans 模型,指定 K 值 |
.fit(X) |
在数据 X 上训练模型 |
.predict(X) |
预测新样本的簇标签 |
.fit_predict(X) |
训练 + 预测(合并调用) |
.cluster_centers_ |
获取质心坐标(K × 特征数) |
.inertia_ |
获取 WCSS(簇内平方和) |
- 👨🏫 教师活动:逐行运行代码,在每个关键步骤后暂停并解释输出;展示
.cluster_centers_与之前手算的“均值”完全对应。 - 🧑🎓 学生活动:在本地复现代码;修改
n_clusters为 3、5、6,观察图像变化。
将上节课的“质心=均值”概念与 cluster_centers_ 输出对接,让学生看到数学概念在代码中的具体对应,消除“黑盒感”。
💻 三、 解决问题过程(二):关键参数详解
1. 初始化敏感性 —— random_state
问题:k-means 的初始质心是随机选的。不同的初始质心可能导致不同的聚类结果。
演示:
观察结论:不同 random_state 可能导致不同的质心初始位置,最终得到不同的聚类结果和不同的 inertia 值。
2. 解决方案 —— n_init 参数
n_init:指定算法用不同的初始质心运行 多次,返回其中 inertia 最小的结果。- 默认值:
n_init=10(即运行 10 次取最优)。
3. max_iter —— 最大迭代次数
- 控制每一轮初始化允许的最大迭代步数。
- 默认值:
max_iter=300。 - 如果数据量很大,可适当增大以保证收敛。
4. 核心参数速查表
| 参数 | 默认值 | 作用 | 调参建议 |
|---|---|---|---|
n_clusters |
8 | 聚类个数(K值) | 使用手肘法确定 |
init |
‘k-means++’ | 初始化方法 | 保持默认(k-means++ 比随机更好) |
n_init |
10 | 不同初始值尝试次数 | 数据大时可增至 20-50 |
max_iter |
300 | 每轮最大迭代次数 | 通常够用,可适当增大 |
random_state |
None | 随机种子 | 设为固定值以保证结果可复现 |
- 👨🏫 教师活动:运行三个不同 random_state 的对比代码,展示结果差异;演示
n_init=50如何找到更优的 inertia。 - 🧑🎓 学生活动:记录三个 random_state 对应的 inertia 值;思考“为什么不同初始质心会导致不同的 inertia”。
通过可视化对比,让学生亲眼看到“随机初始化”带来的问题,再引出 n_init 这个解决方案。这种“问题→解决方案”的教学顺序更能加深记忆。
✍️ 四、 解决问题过程(三):手肘法确定最优 K 值
1. 核心问题:K 值应该选多少?
- 选太小 → 把不同的群体强行合并(欠拟合)。
- 选太大 → 把本应为一群的样本打散(过拟合)。
2. 手肘法(Elbow Method)原理
- 对 K = 1, 2, 3, …, 10,分别训练 KMeans 模型。
- 记录每个 K 对应的
inertia_(WCSS)。 - 绘制“K 值 vs inertia”折线图。
- 观察“肘点”:inertia 下降速度突然变缓的那个 K 值,即为最优 K。
3. 代码实现
4. 分析示例
| K 值 | inertia | 下降幅度 |
|---|---|---|
| 1 | 8000 | — |
| 2 | 4500 | 下降 3500 |
| 3 | 2800 | 下降 1700 |
| 4 | 1800 | 下降 1000(肘点) |
| 5 | 1500 | 下降 300 |
| 6 | 1300 | 下降 200 |
观察:K 从 3→4 时下降幅度仍然较大,从 4→5 起下降明显变缓 → 最优 K=4。
- 👨🏫 教师活动:运行手肘法代码,指出图中的“肘点”位置;解释“下降变缓”的物理含义(再增加 K 带来的边际收益递减)。
- 🧑🎓 学生活动:在本地运行手肘法代码;观察自己生成的图中肘点位置是否与真实 K 值一致。
手肘法是实践中最常用的选 K 方法。通过亲手绘制曲线并观察“肘点”,学生获得可复用的工程技能,而非仅停留在理论层面。
📝 五、 课堂小结(5 分钟)
flowchart LR
root["💻 scikit中的k-means(第二次课)"]
subgraph C1["📖 核心API"]
direction TB
A1["KMeans(n_clusters=K)"]
A2["fit / predict / fit_predict"]
end
subgraph C2["📊 关键属性"]
direction TB
B1["cluster_centers_(质心坐标)"]
B2["inertia_(WCSS值)"]
B3["labels_(簇标签)"]
end
subgraph C3["🔧 关键参数"]
direction TB
C1_node["n_init:多次尝试取最优"]
C2_node["random_state:固定随机种子"]
C3_node["max_iter:最大迭代次数"]
end
subgraph C4["📈 选K方法"]
direction TB
D1["手肘法:绘制 K vs inertia"]
D2["肘点 = 下降变缓处"]
end
root --> C1
root --> C2
root --> C3
root --> C4
style root fill:#e65100,stroke:#bf360c,color:#fff,stroke-width:2px,rx:8px,ry:8px
style C1 fill:#fff3e0,stroke:#ff9800,stroke-width:1px
style C2 fill:#e3f2fd,stroke:#1e88e5,stroke-width:1px
style C3 fill:#e8f5e9,stroke:#43a047,stroke-width:1px
style C4 fill:#f3e5f5,stroke:#9c27b0,stroke-width:1px
✏️ 随堂检测与互动练习
📮 六、 课后作业与拓展
📋 七、 板书设计
本课用到的单词
| 英文术语 | 发音(美式) | 中文释义 | 专业语境解释 |
|---|---|---|---|
| Inertia | /ɪˈnɜːr.ʃə/ | 惯性(WCSS) | KMeans 中的目标函数值,即簇内平方和,越小聚类越紧凑。 |
| Elbow Method | /ˈel.boʊ ˈmeθ.əd/ | 手肘法 | 通过绘制 K 值与 inertia 曲线寻找肘点来确定最优 K 的方法。 |
| Initialization | /ɪˌnɪʃ.əl.aɪˈzeɪ.ʃən/ | 初始化 | 算法开始前给参数赋予初始值的过程,在 KMeans 中指初始质心选择。 |
| Random State | /ˈræn.dəm steɪt/ | 随机种子 | 控制随机数生成的参数,固定后每次运行结果一致。 |
| Standardization | /ˌstæn.dɚ.daɪˈzeɪ.ʃən/ | 标准化 | 将特征调整为均值为0、方差为1的分布,消除尺度影响。 |