从0了解机器学习:6——聚类

本文章将介绍无监督学习中的聚类,以及一些其他有关概念

(如果文章中的公式不能正常显示,请刷新该页面。如果还不能解决,请邮箱联系我,谢谢...)

聚类(Clustering)

在监督学习的分类中,我们是这样的:

对于训练集:\(\{(x^{(1)},y^{(1)}),(x^{(2)},y^{(2)}),(x^{(3)},y^{(3)}),...\}\)

每一个输入都有对应的标签,在图中反映为不同的颜色

而在无监督学习中:

对于训练集:\(\{x^{(1)},x^{(2)},x^{(3)},x^{(4)},... \}\)

没有标签,在图中反映为数据都是同样的颜色

目标是找出数据中的一些有趣的东西或者规律,像图中的就是将两簇数据聚为两类,也就是聚类

聚类的具体应用在之前的文章《从0了解机器学习:1——机器学习的基本分类》中有提到,这里不做赘述

K-means

这是在聚类中使用最广泛的算法,让我们看看是怎么实现的

这里给出一个例子:

上图是一堆数据的分布,怎么将左下和右上两类数据进行聚类呢

我们可以先在图上随机生成两个点,这两个点作为两簇数据的中心,让这个点自己去找他们的同类

这两个点可以称为:簇质心(cluster centroid)

怎么找到他们各自的同伴呢,正所谓“远乡不如近邻”,我们可以看看这些点,哪些离他们近就把近的点归为他们的同类

所以,计算每个点到两个簇质心的距离,将二者中最短的点标记为其同类:

标记好同类之后,此时两个簇质心向着各自同类的质心移动:

移动之后,重新计算所有点到簇质心的距离,取最短的距离标记为同类:

标记好同类之后,两个簇质心继续向着各自同类的质心移动:

移动之后,重新计算所有点到簇质心的距离,取最短的距离标记为同类:

标记好同类之后,两个簇质心继续向着各自同类的质心移动

移动之后,重新计算所有点到簇质心的距离,取最短的距离标记为同类

重复上述操作后,得到最终图像为:

简单来说,上述这个算法就是:

  • 随机两个簇质心
  • 计算各个点到他们的距离,将最短的点标记为同类
  • 移动簇质心到新的质心
  • 重复2、3步骤

K-means算法

数据集有 \(m\) 个点,随机初始化 \(K\) 个簇质心:\(\mu_1,\mu_2,\mu_3,...,\mu_k\)

重复以下步骤:

  • 分配各个数据点给每个簇质心
    • 从1~m 个数据点:\(c^{(i)}:=\) 离数据点 \(x^{(i)}\) 最近的簇质心的下标(1~k)
    • \(c^{(i)}:=min_k|| x^{(i)}-\mu_k ||^2\qquad(L_2范数)\)
  • 移动簇质心
    • 从1~k 个簇质心:\(\mu_k:=\) 分配给簇质心k的点的平均值(就是同类数据点的对应坐标值相加取平均值)
    • 例如:\(\mu_1=\frac{1}{4}(x^{(1)}+x^{(5)}+x^{(6)}+x^{(10)})\) 其中的 \(x\) 都是含有两个数 \((x_1,x_2)\) 的向量

对于第一步的图解:

分配各个数据点给每个簇质心:

对于第二步的图解:

移动簇质心:

如果因为簇质心初始化有问题,导致一些簇质心没有分配到坐标点该怎么办,就像这样:

簇质心 \(\mu_2\) 没有分配到任何数据点!

通常情况下,如果程序执行完后,存在簇质心没有任何的数据点,那么我们一般会将那个没有任何数据点的簇质心删去

也就是进行\(k-1\) 的操作,去除 \(\mu_2\) 只保留 \(\mu_1\)

但是也可以重新进行簇质心的初始化

K-means优化器(Optimization)

定义如下参数:

\(c^{(i)}\) = 距离 \(x^{(i)}\) 最近的簇质心的下标

\(\mu_k\) = 簇质心 k

\(\mu_c^{(i)}\) = 距离 \(x^{(i)}\) 最近的簇质心的位置坐标

损失函数: \[ J(c^{(1)},...,c^{(m)},\mu_1,...,\mu_k)=\frac{1}{m}\sum_{i=1}^m|| x^{(i)}-\mu_c^{(i)} ||^2 \] 上述函数计算的是已分配簇质心的数据点到其簇质心的平均距离,我们要做到就是减小这个损失函数: \[ \begin{gather} min \\ c^{(1)},...,c^{(m)} \\ \mu_1,...,\mu_k \end{gather} J(c^{(1)},...,c^{(m)},\mu_1,...,\mu_k) \] 这个函数也叫做失真函数(distortion function)

和梯度下降不同,这个函数是通过选择不同的质心 \(\mu_c^{(i)}\) 来减小

对于之前提到的第一步:

根据上图,\(\mu_1\)\(x^{(i)}\) 的距离是更短的,所以损失函数会选择 \(\mu_1\) ,在函数中体现为:

选择了 \(\mu_1\) 也就是改变了 \(c^{(i)}\) 对于函数: \[ \frac{1}{m}\sum_{i=1}^m|| x^{(i)}-\mu_c^{(i)} ||^2 \] 其中的 \(\mu_c^{(i)}\) 也由于选择了更短的 \(\mu_1\) 而变为其坐标,从而使得该函数更小

对于之前的第二步:

在移动簇质心之前,我们计算一些其到左右两个数据点的平均距离(其实也就是损失函数): \[ \begin{gather} \frac{1}{m}\sum_{i=1}^m|| x^{(i)}-\mu_c^{(i)} ||^2=\frac{1}{2}[(1-2)^2+(11-2)^2] \\ =\frac{1}{2}(1^2+9^2) \\ =41 \end{gather} \] 将簇质心移动到两个数据点的平均坐标上时,我们计算其平均距离: \[ \begin{gather} \frac{1}{m}\sum_{i=1}^m|| x^{(i)}-\mu_c^{(i)} ||^2=\frac{1}{2}[(1-6)^2+(11-6)^2] \\ =\frac{1}{2}(5^2+5^2) \\ =25 \end{gather} \] 移动之后,损失函数减小了:\(41-25=16\)

所以说,第二步中移动 \(\mu_k\) 能够减小损失函数

这个损失函数将会一直减小不会增大,如果不是这样的话,就检查你的代码是否存在bug

当这个函数停止减小了,或者减小的幅度很慢,就可以考虑它是不是收敛了

K-means初始化(Initializati0n)

如何随机选择簇质心呢,我们常常这么做:

  • 选择 \(k<m\)
  • 随机取出 \(k\) 个训练数据
  • 将取出的 \(k\) 个训练数据的数据点作为 \(k\) 个簇质心

但是,如果只是初始化一次的话,会出现以下问题:

对于这种情况,我们只需要进行多次初始化,之后从收敛的损失函数中选出最小值作为最佳的初始化

写出最终算法:

循环 \(n\) 次(n的值一般为50~100):

  • 随机初始化K-means
    • 选择 \(k<m\)
    • 随机取出 \(k\) 个训练数据
    • 将取出的 \(k\) 个训练数据的数据点作为 \(k\) 个簇质心
  • 运行K-means算法,获取 \(c^{(1)},...,c^{(m)},\mu_1,...,\mu_k\)
  • 计算损失函数:\(J(c^{(1)},...,c^{(m)},\mu_1,...,\mu_k)\)

最后取出最小的 \(J(c^{(1)},...,c^{(m)},\mu_1,...,\mu_k)\) 此时的簇质心就是比较合适的簇质心

簇质心数量的选择

上面说了那么多,我们到底要取多少个簇质心呢?

对于一些数据来说,选择簇质心的数量可能并没有那么简单:

对于上面的数据,分为两类合理,分为四类也合理,到底应该分为几类呢?

肘法(elbow method)

我们可以画出损失函数关于簇质心数量的曲线:

当损失函数出现转折点时,当时的转折点的簇质心数量就是最佳数量

那如果损失函数没有转折点该怎么办?

其实最好的办法就是:根据实际出发

如果你有一家服装店,经过多年积累,你手上有众多客户的身高体重的数据,此时你想要看看,将哪些范围的身高体重设置为衣服的对应尺码:S、M、L 码

可以像这样分为三个尺码

但是如果客户对服装尺码的差异比较敏感的话,也可以这样分:

我的意思是,其实没有什么标准答案,我们需要考虑的是现实情况,然后去选择一个最合适的簇质心数量,每一个选择对你或者对其他人来说,可能都是适合的或者不适合的,这要看你如何处理

其实我们学习机器学习算法,目的就是要帮助人们解决生活中的问题,跳脱出算法的禁锢,回到生活中来,你将会有新的发现!

总结

本文章讲了无监督学习中的聚类,同时也讲了一些其他概念:K-means算法等

在接下来,我们将开始学习无监督学习中的第二个算法——异常检测(Anomaly detection)

从0了解机器学习:6——聚类

http://www.heimaolala.top/2025/01/07/ML6/

作者

heimaolala

发布于

2025-01-07

更新于

2025-03-10

许可协议

评论