分类有标签可学,聚类只能看「哪些点离得近」。 KMeans 四步:挑中心、归堆、挪中心、重复,直到中心不动。 分三类时调整兰德指数 1.0000,硬分五类掉到 0.7370。
上一篇有 y,模型知道每个点该属于哪一类。这一篇没有 y,只能靠距离。 数据用 make_blobs 造九十个点,真实三类,但训练时假装不知道。
一、和分类的根本区别
分类学的是「什么样的点该分到哪一类」,有标准答案。 聚类没有答案,只能看「哪些点长得像」。判断标准是距离。 所以聚类没有「对不对」,只有「分得合不合用」。这是它最麻烦的地方。
fit 也只接一个 X,没有 y——这是它和前面几个算法最明显的差别。
二、KMeans 的四步
第一步,随便挑 k 个点当中心。 第二步,每个点归到离它最近的中心。 第三步,把每个堆的中心挪到这堆点的平均位置。
第四步,重复二三步,直到中心不再移动。 它一定会停,但不保证停在最好的地方。所以要换几组初始中心各跑一遍。
三、跑一次看看
九十个点分成三类,每类正好 30 个。 三个中心是 (4.652, 2.069)、(-7.066, -6.610)、(-2.709, 8.810)。 inertia 是「每个点到它自己中心的距离平方和」,这次是 155.68。
inertia 越小说明堆越紧。但它是绝对值,不同数据之间没法比。
n_init=10 是「换十组初始中心各跑一遍,取 inertia 最小的」。省了它会不稳。
四、分得准不准
真实标签其实有,刚才只是假装没有。现在拿来对一下。 调整兰德指数 1.0000,说明分得一点不差。 1 是完全一致,0 是跟瞎猜差不多。这个指标已经扣掉了「碰巧对上」的成分。
真实场景里没有真实标签,这个指标根本用不了——所以下一篇讲别的评价办法。
五、分错堆长什么样
硬分成五类,调整兰德指数掉到 0.7370。 k 选错,结果就散。但注意,inertia 反而更小了:五类肯定比三类紧。 所以不能拿 inertia 选 k。分一百类,每类一个点,inertia 直接是 0。
这也是聚类最容易踩的坑:指标越「好」,结果越没用。
六、动手 Demo:聚类:没有标签怎么分堆
造九十个点,真实三类,但训练时只给坐标不给标签。 分完再拿真实标签对照,最后故意分成五类看结果怎么散。
import numpy as np
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
from sklearn.metrics import adjusted_rand_score
X, y_true = make_blobs(n_samples=90, centers=3, cluster_std=1.0,
random_state=42)
km = KMeans(n_clusters=3, n_init=10, random_state=42).fit(X)
for c in range(3):
print("第 %d 类:%d 个点" % (c, int((km.labels_ == c).sum())))
print("inertia %.2f" % km.inertia_)
print("调整兰德指数 %.4f" % adjusted_rand_score(y_true, km.labels_))
km5 = KMeans(n_clusters=5, n_init=10, random_state=42).fit(X)
print("硬分五类:inertia %.2f,调整兰德指数 %.4f"
% (km5.inertia_, adjusted_rand_score(y_true, km5.labels_)))
print("第一个中心 %s" % np.round(km.cluster_centers_[0], 3).tolist())
实跑输出:
--------------------------------------------------------------------
聚类:没有标签怎么分堆
--------------------------------------------------------------------
① 和分类的区别
--------------------------------------------------------------------
分类有标签,模型学「什么样的点该分到哪一类」。
聚类没标签,模型只能自己看「哪些点长得像」。
判断标准是距离:离得近的归一堆。就这么朴素。
! 聚类没有标准答案,所以评价也难。这是它和分类最大的不同。
② KMeans 的四步
--------------------------------------------------------------------
第一步,随便挑 k 个点当中心。
第二步,每个点归到最近的中心。
第三步,把每个堆的中心挪到这堆点的平均位置。
第四步,重复二三步,直到中心不再移动。
! 它一定会停,但不保证停在最好的地方。所以要多试几个初始中心,取最好的。
③ 跑一次
--------------------------------------------------------------------
九十个点,真实是三类,但我们假装不知道。
分成三类之后,每类的点数:
第 0 类 30 个点
第 1 类 30 个点
第 2 类 30 个点
三个中心点:
[4.652, 2.069]
[-7.066, -6.61]
[-2.709, 8.81]
inertia 是「每个点到它自己中心的距离平方和」,越小越紧。这次是 155.68。
! n_init=10 是「换十组初始中心,各跑一遍,取 inertia 最小的」。省了它会不稳。
④ 分得准不准
--------------------------------------------------------------------
真实标签我们其实有,只是刚才假装没有。现在拿来对一下。
调整兰德指数 1.0000。
1 是完全一致,0 是跟瞎猜差不多。这次正好是 1.0000,分得一点不差。
! 真实场景里没有真实标签,这个指标用不了。所以聚类评价要靠轮廓系数。
⑤ 分错堆长什么样
--------------------------------------------------------------------
硬分成五类,调整兰德指数掉到 0.7370。
k 选错,结果就散。但 inertia 会一直变小——五类肯定比三类紧。
所以不能拿 inertia 选 k,得用轮廓系数或者肘部法。
! 这是聚类最容易踩的坑:以为 inertia 越小越好,结果分出一百类,每类一个点,inertia 是 0。
labels_ 是每个点被分到的类号。类号本身没有含义,0 类不一定是「第一类」。
cluster_centers_ 是算出来的中心坐标,可以拿去解释「这一堆大概长什么样」。
注意五类时 inertia 更小、兰德指数更差,这一对矛盾就是选 k 的难点。
30 秒实验
- 把 n_clusters 改成 2 和 4,各跑一次,看调整兰德指数。
- 把 n_init 改成 1,连跑五次,看 inertia 是不是每次都一样。
- 想一想:真实场景里没有真实标签,你怎么知道分得对不对?
常见误区
- 拿 inertia 选 k:加类必然变小,分一百类 inertia 是 0,毫无意义。
- 把类号当顺序:0、1、2 只是编号,没有大小和先后。
- 忘了 n_init:初始中心随机,跑一次的结果可能很糟。
- 以为聚类有标准答案:真实数据里没有,只能说「合不合用」。
自测三问(点开对答案)
1. 聚类和分类最根本的区别? —— 分类有标签可学,聚类只有坐标,靠距离自己分。 2. KMeans 的四步是什么? —— 挑初始中心、按最近归堆、把中心挪到堆的平均位置、重复到中心不动。 3. 为什么不能用 inertia 选 k? —— 类越多每堆越紧,inertia 必然越小,它没有下限。分完了却不知道怎么评价。下一篇:造数据的生成器,和不用标签的评价指标。
- ☐ (本篇完,下一篇 8.6 聚类数据生成器与评价)