轮廓系数
本课属于 Coddy Machine Learning 学习旅程的“无监督学习”单元。第 8 课,共 51 课。
惯性会随着 k 增大而不断改善,因此需要寻找肘部。轮廓系数会向每个点提出一个更公平的问题:它到自己所属组的距离是否比到下一个组更近?
一个点的得分为 (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,此时各个点最适合聚在一起。
挑战
简单两位预报员对袭击他们海岸的风暴种类数量意见不一。初始代码包含 150 场风暴、最大风速和降雨量,并依次读取 Ana 的 k 和 Ben 的 k。
- 用轮廓系数为每个 k 评分,保留 3 位小数。
- 输出哪个人的 k 更合适。
- 输出 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())
# 在下面编写你的代码
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
无监督学习中的所有课
自己练习: Python 在线编译器