Menu
CoddyTech

轮廓系数

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

惯性会随着 k 增大而不断改善,因此需要寻找肘部。轮廓系数会向每个点提出一个更公平的问题:它到自己所属组的距离是否比到下一个组更近?

一个黑点与所属组中的 8 个点之间用实线连接,平均长度 a = 1.3;与最近的其他组中的 8 个点之间用虚线连接,平均长度 b = 3.4。它的轮廓系数为 0.62

一个点的得分为 (b - a) / max(a, b):接近 1 表示它在所属组中很紧密,接近 0 表示它位于边界上,低于 0 表示它被分到了错误的组。平均得分用于评估聚类:

from sklearn.metrics import silhouette_score
for k in [2, 3, 4]:
    km = KMeans(n_clusters=k, n_init=10, random_state=0)
    km.fit(X)
    print(k, f"{silhouette_score(X, km.labels_):.3f}")

对于 apples,输出如下:

2 0.534
3 0.657
4 0.545

它在最佳 k 值处达到峰值,这里是 3,此时各个点最适合聚在一起。

challenge icon

挑战

简单

两位预报员对袭击他们海岸的风暴种类数量意见不一。初始代码包含 150 场风暴、最大风速和降雨量,并依次读取 Ana 的 k 和 Ben 的 k。

  1. 用轮廓系数为每个 k 评分,保留 3 位小数。
  2. 输出哪个人的 k 更合适。
  3. 输出 2 到 8 之间最佳的 k 及其得分。

对于另一段海岸:

Ana, k = 2: 0.512
Ben, k = 3: 0.574
Ben's k fits better
Best from 2 to 8: k = 3 (0.574)

亲手试试

import numpy as np
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score

# 不要修改下面的代码行
rng = np.random.default_rng(6)
# 四种风暴:各自典型的风速、降雨量和数量
kinds = [(30, 8, 40), (12, 34, 35), (21, 21, 30), (11, 9, 45)]
parts = []
for w, r, n in kinds:
    parts.append(np.column_stack([rng.normal(w, 2.5, n), rng.normal(r, 3, n)]))
# 某海岸的 150 场风暴,每场占一行:峰值风速(m/s)和每小时降雨量(mm)
storms = np.round(np.concatenate(parts), 1)

# 两位天气预报员预测的风暴种类数
k_ana = int(input())
k_ben = int(input())

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

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

无监督学习中的所有课

自己练习: Python 在线编译器