Menu
CoddyTech

肘部法

本课属于 Coddy Machine Learning 学习旅程的“无监督学习”单元。第 7 课,共 51 课。

绘制惯性随 k 变化的曲线。每增加一个中心,如果它能把真实的组分开,惯性就会急剧下降;随后曲线会逐渐变平。弯折处,也就是肘部,对应的 k 值通常不错:

k from 1 to 8 的两条惯性曲线。左图是苹果:曲线陡降至 k = 3,之后几乎变平,并在 3 处标有虚线。右图是没有分组的点:曲线平滑,没有弯折

一个经验法则:当再增加一个中心只能让惯性减少不到四分之一时,就停止。苹果数据的减少幅度依次为 56%、69%,然后只有 15%。所以 k = 3:

ax.plot(ks, inertias, marker="o")
ax.axvline(3, linestyle="--")

平缓且没有弯折的曲线意味着没有明显的分组。下一课会带来第二位评判者。

challenge icon

挑战

简单

一款植物应用会根据光照和浇水需求,将室内植物分成不同的养护方案。起始代码包含 k from 1 to 8 的惯性值、一张图表,以及 cutoff。

  1. 从 k = 1 开始递增,当下一个 k 使惯性值的降幅小于 cutoff 时停止。打印这个 k。
  2. 绘制惯性值随 k 变化的图表,标出数据点,在你选定的 k 处画一条垂直虚线,然后显示图表。

对于另一个应用,cutoff 为 0.25:

Care plans: 3

一条标题为 Elbow: Care Plans 的 k from 1 to 8 惯性曲线,每个 k 处都有一个数据点:曲线先陡降至 k = 3,之后几乎持平,并在 3 处有一条垂直虚线

然后 Coddy 会描述你的图表。

亲手试试

import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans

# 不要修改下面的代码行
rng = np.random.default_rng(17)
# 4 类植物:各类的典型光照和水分需求,以及植物数量
kinds = [(8.5, 2, 35), (2.5, 7.5, 30), (5, 5, 30), (8, 8, 25)]
parts = []
for l, w, n in kinds:
    parts.append(np.column_stack([rng.normal(l, 0.8, n), rng.normal(w, 0.8, n)]))
# 120 株室内植物,每株占一行:光照和水分需求均按 1 到 10 评分
plants = np.clip(np.round(np.concatenate(parts), 1), 1, 10)

# k 从 1 到 8 时的惯性值,来自 Inertia
ks = list(range(1, 9))
inertias = []
for k in ks:
    km = KMeans(n_clusters=k, n_init=10, random_state=0)
    km.fit(plants)
    inertias.append(km.inertia_)

cutoff = float(input())
fig, ax = plt.subplots()
ax.set_title("Elbow: Care Plans")
ax.set_xlabel("k")
ax.set_ylabel("Inertia")

# 在下面编写你的代码
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

无监督学习中的所有课

自己练习: Python 在线编译器