【Python机器学习基础教程】第三章第五节:聚类


我们前面说过,聚类(clustering)是将数据集划分成组的任务,这些组叫作簇(cluster)。其目标是划分数据,使得一个簇内的数据点非常相似且不同簇内的数据点非常不同。与分类算法类似,聚类算法为每个数据点分配(或预测)一个数字,表示这个点属于哪个簇。

1. k均值聚类(k-means)

k 均值聚类是最简单也最常用的聚类算法之一。它试图找到代表数据特定区域的簇中心
(cluster center)。算法交替执行以下两个步骤:将每个数据点分配给最近的簇中心,然后将每个簇中心设置为所分配的所有数据点的平均值。如果簇的分配不再发生变化,那么算法结束。下面的例子(图 3-23)在一个模拟数据集上对这一算法进行说明:

在这里插入代码片

簇中心用三角形表示,而数据点用圆形表示。颜色表示簇成员。我们指定要寻找三个簇,
所以通过声明三个随机数据点为簇中心来将算法初始化(见图中“Initialization”/“初
始化”)。然后开始迭代算法。首先,每个数据点被分配给距离最近的簇中心(见图中
“Assign Points (1)”/“分配数据点(1)”)。接下来,将簇中心修改为所分配点的平均值
(见图中“Recompute Centers (1)”/“重新计算中心(1)”)。然后将这一过程再重复两次。在第三次迭代之后,为簇中心分配的数据点保持不变,因此算法结束。

给定新的数据点,k 均值会将其分配给最近的簇中心。下一个例子(图 3-24)展示了图
3-23 学到的簇中心的边界:

在这里插入代码片

用 scikit-learn 应用 k 均值相当简单。下面我们将其应用于上图中的模拟数据。我们将
KMeans 类实例化,并设置我们要寻找的簇个数 3。然后对数据调用 fit 方法:

在这里插入代码片

算法运行期间,为 X 中的每个训练数据点分配一个簇标签。你可以在 kmeans.labels_ 属性中找到这些标签:

在这里插入代码片

因为我们要找的是 3 个簇,所以簇的编号是 0 到 2。
你也可以用 predict 方法为新数据点分配簇标签。预测时会将最近的簇中心分配给每个新
数据点,但现有模型不会改变。对训练集运行 predict 会返回与 labels_ 相同的结果:

在这里插入代码片

可以看到,聚类算法与分类算法有些相似,每个元素都有一个标签。但并不存在真实的标
签,因此标签本身并没有先验意义。我们回到之前讨论过的人脸图像聚类的例子。聚类的
结果可能是,算法找到的第 3 个簇仅包含你朋友 Bela 的面孔。但只有在查看图片之后才能知道这一点,而且数字 3 是任意的。算法给你的唯一信息就是所有标签为 3 的人脸都是相似的。

对于我们刚刚在二维玩具数据集上运行的聚类算法,这意味着我们不应该为其中一组的标
签是 0、另一组的标签是 1 这一事实赋予任何意义。再次运行该算法可能会得到不同的簇
编号,原因在于初始化的随机性质。

下面又给出了这个数据的图像(图 3-25)。簇中心被保存在 cluster_centers_ 属性中,我
们用三角形表示它们:

在这里插入代码片

我们也可以使用更多或更少的簇中心(图 3-26):

在这里插入代码片

1.1 k均值的失败案例

即使你知道给定数据集中簇的“正确”个数,k 均值可能也不是总能找到它们。每个簇仅
由其中心定义,这意味着每个簇都是凸形(convex)。因此,k 均值只能找到相对简单的形状。k 均值还假设所有簇在某种程度上具有相同的“直径”,它总是将簇之间的边界刚好画在簇中心的中间位置。有时这会导致令人惊讶的结果,如图 3-27 所示:

在这里插入代码片

你可能会认为,左下方的密集区域是第一个簇,右上方的密集区域是第二个,中间密度较
小的区域是第三个。但事实上,簇 0 和簇 1 都包含一些远离簇中其他点的点。

k 均值还假设所有方向对每个簇都同等重要。图 3-28 显示了一个二维数据集,数据中包含
明确分开的三部分。但是这三部分被沿着对角线方向拉长。由于 k 均值仅考虑到最近簇中
心的距离,所以它无法处理这种类型的数据:

在这里插入代码片

如果簇的形状更加复杂,比如我们在第 2 章遇到的 two_moons 数据,那么 k 均值的表现也很差(见图 3-29):

在这里插入代码片

这里我们希望聚类算法能够发现两个半月形。但利用 k 均值算法是不可能做到这一点的。

1.2 矢量量化,或者将k均值看作分解

虽然 k 均值是一种聚类算法,但在 k 均值和分解方法(比如之前讨论过的 PCA 和 NMF)
之间存在一些有趣的相似之处。你可能还记得,PCA 试图找到数据中方差最大的方向,而
NMF 试图找到累加的分量,这通常对应于数据的“极值”或“部分”(见图 3-13)。两种方法都试图将数据点表示为一些分量之和。与之相反,k 均值则尝试利用簇中心来表示每个数据点。你可以将其看作仅用一个分量来表示每个数据点,该分量由簇中心给出。这种观点将 k 均值看作是一种分解方法,其中每个点用单一分量来表示,这种观点被称为矢量量化(vector quantization)。

我们来并排比较 PCA、NMF 和 k 均值,分别显示提取的分量(图 3-30),以及利用 100 个分量对测试集中人脸的重建(图 3-31)。对于 k 均值,重建就是在训练集中找到的最近的簇中心:

在这里插入代码片

利用 k 均值做矢量量化的一个有趣之处在于,可以用比输入维度更多的簇来对数据进行编
码。让我们回到 two_moons 数据。利用 PCA 或 NMF,我们对这个数据无能为力,因为它只有两个维度。使用 PCA 或 NMF 将其降到一维,将会完全破坏数据的结构。但通过使用更多的簇中心,我们可以用 k 均值找到一种更具表现力的表示(见图 3-32):

在这里插入代码片

我们使用了 10 个簇中心,也就是说,现在每个点都被分配了 0 到 9 之间的一个数字。我们可以将其看作 10 个分量表示的数据(我们有 10 个新特征),只有表示该点对应的簇中心的那个特征不为 0,其他特征均为 0。利用这个 10 维表示,现在可以用线性模型来划分两个半月形,而利用原始的两个特征是不可能做到这一点的。将到每个簇中心的距离作为特征,还可以得到一种表现力更强的数据表示。可以利用 kmeans 的 transform 方法来完成这一点:

在这里插入代码片

k 均值是非常流行的聚类算法,因为它不仅相对容易理解和实现,而且运行速度也相对较
快。k 均值可以轻松扩展到大型数据集,scikit-learn 甚至在 MiniBatchKMeans 类中包含了一种更具可扩展性的变体,可以处理非常大的数据集。

k 均值的缺点之一在于,它依赖于随机初始化,也就是说,算法的输出依赖于随机种子。
默认情况下,scikit-learn 用 10 种不同的随机初始化将算法运行 10 次,并返回最佳结果。

k 均值还有一个缺点,就是对簇形状的假设的约束性较强,而且还要求指定所要寻找
的簇的个数(在现实世界的应用中可能并不知道这个数字)。

接下来,我们将学习另外两种聚类算法,它们都在某些方面对这些性质做了改进。

2. 凝聚聚类

凝聚聚类(agglomerative clustering)指的是许多基于相同原则构建的聚类算法,这一原则是:算法首先声明每个点是自己的簇,然后合并两个最相似的簇,直到满足某种停止准则为止。scikit-learn 中实现的停止准则是簇的个数,因此相似的簇被合并,直到仅剩下指
定个数的簇。还有一些链接(linkage)准则,规定如何度量“最相似的簇”。这种度量总
是定义在两个现有的簇之间。

scikit-learn 中实现了以下三种选项。

ward 适用于大多数数据集,在我们的例子中将使用它。如果簇中的成员个数非常不同(比如其中一个比其他所有都大得多),那么 average 或 complete 可能效果更好。图 3-33 给出了在一个二维数据集上的凝聚聚类过程,要寻找三个簇。

在这里插入代码片

最开始,每个点自成一簇。然后在每一个步骤中,相距最近的两个簇被合并。在前四个步
骤中,选出两个单点簇并将其合并成两点簇。在步骤 5(Step 5)中,其中一个两点簇被
扩展到三个点,以此类推。在步骤 9(Step 9)中,只剩下 3 个簇。由于我们指定寻找 3 个簇,因此算法结束。

我们来看一下凝聚聚类对我们这里使用的简单三簇数据的效果如何。由于算法的工作原
理,凝聚算法不能对新数据点做出预测。因此 AgglomerativeClustering 没有 predict 方
法。为了构造模型并得到训练集上簇的成员关系,可以改用 fit_predict 方法。结果如图
3-34 所示。

在这里插入代码片

正如所料,算法完美地完成了聚类。虽然凝聚聚类的 scikit-learn 实现需要你指定希望
算法找到的簇的个数,但凝聚聚类方法为选择正确的个数提供了一些帮助,我们将在下
面讨论。

2.1 层次聚类与树状图

凝聚聚类生成了所谓的层次聚类(hierarchical clustering)。聚类过程迭代进行,每个点都从一个单点簇变为属于最终的某个簇。每个中间步骤都提供了数据的一种聚类(簇的个数也不相同)。有时候,同时查看所有可能的聚类是有帮助的。下一个例子(图 3-35)叠加显示了图 3-33 中所有可能的聚类,有助于深入了解每个簇如何分解为较小的簇:

在这里插入代码片

虽然这种可视化为层次聚类提供了非常详细的视图,但它依赖于数据的二维性质,因此不
能用于具有两个以上特征的数据集。但还有另一个将层次聚类可视化的工具,叫作树状图
(dendrogram),它可以处理多维数据集。

不幸的是,目前 scikit-learn 没有绘制树状图的功能。但你可以利用 SciPy 轻松生成树状
图。SciPy 的聚类算法接口与 scikit-learn 的聚类算法稍有不同。SciPy 提供了一个函数,
接受数据数组 X 并计算出一个链接数组(linkage array),它对层次聚类的相似度进行编码。然后我们可以将这个链接数组提供给 scipy 的 dendrogram 函数来绘制树状图(图 3-36)。

在这里插入代码片

树状图在底部显示数据点(编号从 0 到 11)。然后以这些点(表示单点簇)作为叶节点绘制一棵树,每合并两个簇就添加一个新的父节点。

从下往上看,数据点 1 和 4 首先被合并(正如你在图 3-33 中所见)。接下来,点 6 和 9 被合并为一个簇,以此类推。在顶层有两个分支,一个由点 11、0、5、10、7、6 和 9 组成,另一个由点 1、4、3、2 和 8 组成。这对应于图中左侧两个最大的簇。

树状图的 y 轴不仅说明凝聚算法中两个簇何时合并,每个分支的长度还表示被合并的簇之
间的距离。在这张树状图中,最长的分支是用标记为“three clusters”(三个簇)的虚线表
示的三条线。它们是最长的分支,这表示从三个簇到两个簇的过程中合并了一些距离非常
远的点。我们在图像上方再次看到这一点,将剩下的两个簇合并为一个簇也需要跨越相对
较大的距离。

不幸的是,凝聚聚类仍然无法分离像 two_moons 数据集这样复杂的形状。但我们要学习的下一个算法 DBSCAN 可以解决这个问题。

2.2

3. DBSCAN

另一个非常有用的聚类算法是 DBSCAN(density-based spatial clustering of applications with noise,即“具有噪声的基于密度的空间聚类应用”)。DBSCAN 的主要优点是它不需要用户先验地设置簇的个数,可以划分具有复杂形状的簇,还可以找出不属于任何簇的点。DBSCAN 比凝聚聚类和 k 均值稍慢,但仍可以扩展到相对较大的数据集。

DBSCAN 的原理是识别特征空间的“拥挤”区域中的点,在这些区域中许多数据点靠近在
一起。这些区域被称为特征空间中的密集(dense)区域。DBSCAN 背后的思想是,簇形
成数据的密集区域,并由相对较空的区域分隔开。

在密集区域内的点被称为核心样本(core sample,或核心点),它们的定义如下。DBSCAN有两个参数:min_samples 和 eps。如果在距一个给定数据点 eps 的距离内至少有 min_samples 个数据点,那么这个数据点就是核心样本。DBSCAN 将彼此距离小于 eps 的核心样本放到同一个簇中。

算法首先任意选取一个点,然后找到到这个点的距离小于等于 eps 的所有的点。如果
距起始点的距离在 eps 之内的数据点个数小于 min_samples,那么这个点被标记为噪
声(noise),也就是说它不属于任何簇。如果距离在 eps 之内的数据点个数大于 min_
samples,则这个点被标记为核心样本,并被分配一个新的簇标签。然后访问该点的所有
邻居(在距离 eps 以内)。如果它们还没有被分配一个簇,那么就将刚刚创建的新的簇标
签分配给它们。如果它们是核心样本,那么就依次访问其邻居,以此类推。簇逐渐增大,
直到在簇的 eps 距离内没有更多的核心样本为止。然后选取另一个尚未被访问过的点,并重复相同的过程。

最后,一共有三种类型的点:核心点、与核心点的距离在 eps 之内的点(叫作边界点,
boundary point)和噪声。如果 DBSCAN 算法在特定数据集上多次运行,那么核心点的聚
类始终相同,同样的点也始终被标记为噪声。但边界点可能与不止一个簇的核心样本相
邻。因此,边界点所属的簇依赖于数据点的访问顺序。一般来说只有很少的边界点,这种
对访问顺序的轻度依赖并不重要。

我们将 DBSCAN 应用于演示凝聚聚类的模拟数据集。与凝聚聚类类似,DBSCAN 也不允
许对新的测试数据进行预测,所以我们将使用 fit_predict 方法来执行聚类并返回簇标签。

在这里插入代码片

如你所见,所有数据点都被分配了标签 -1,这代表噪声。这是 eps 和 min_samples 默认参数设置的结果,对于小型的玩具数据集并没有调节这些参数。min_samples 和 eps 取不同值时的簇分类如下所示,其可视化结果见图 3-37。

在这里插入代码片

在这张图中,属于簇的点是实心的,而噪声点则显示为空心的。核心样本显示为较大的标
记,而边界点则显示为较小的标记。增大 eps(在图中从左到右),更多的点会被包含在一个簇中。这让簇变大,但可能也会导致多个簇合并成一个。增大 min_samples(在图中从上到下),核心点会变得更少,更多的点被标记为噪声。

参数 eps 在某种程度上更加重要,因为它决定了点与点之间“接近”的含义。将 eps 设置得非常小,意味着没有点是核心样本,可能会导致所有点都被标记为噪声。将 eps 设置得非常大,可能会导致所有点形成单个簇。

设置 min_samples 主要是为了判断稀疏区域内的点被标记为异常值还是形成自己的簇。如果增大 min_samples,任何一个包含少于 min_samples 个样本的簇现在将被标记为噪声。因此,min_samples 决定簇的最小尺寸。在图 3-37 中 eps=1.5 时,从min_samples=3 到 min_samples=5,你可以清楚地看到这一点。min_samples=3 时有三个簇:一个包含 4 个点,一个包含 5 个点,一个包含 3 个点。min_samples=5 时,两个较小的簇(分别包含 3 个点和 4个点)现在被标记为噪声,只保留包含 5 个样本的簇。

虽然 DBSCAN 不需要显式地设置簇的个数,但设置 eps 可以隐式地控制找到的簇的个数。使用 StandardScaler 或 MinMaxScaler 对数据进行缩放之后,有时会更容易找到 eps 的较好取值,因为使用这些缩放技术将确保所有特征具有相似的范围。

图 3-38 展示了在 two_moons 数据集上运行 DBSCAN 的结果。利用默认设置,算法找到了两个半圆形并将其分开:

在这里插入代码片

由于算法找到了我们想要的簇的个数(2 个),因此参数设置的效果似乎很好。如果将 eps减小到 0.2(默认值为 0.5),我们将会得到 8 个簇,这显然太多了。将 eps 增大到 0.7 则会导致只有一个簇。

在使用 DBSCAN 时,你需要谨慎处理返回的簇分配。如果使用簇标签对另一个数据进行
索引,那么使用 -1 表示噪声可能会产生意料之外的结果。

4. 聚类算法的对比与评估

4.1 用真实值评估聚类

4.2 在没有真实值的情况下评估聚类

4.3 在人脸数据集上比较算法

5. 聚类方法小结

  1. 本节的内容表明,聚类的应用与评估是一个非常定性的过程,通常在数据分析的探索阶段很有帮助。
  2. 我们学习了三种聚类算法:k 均值、DBSCAN 和凝聚聚类。这三种算法都可以控制聚类的粒度(granularity)。k 均值和凝聚聚类允许你指定想要的簇的数量,而DBSCAN 允许你用eps 参数定义接近程度,从而间接影响簇的大小。三种方法都可以用于大型的现实世界数据集,都相对容易理解,也都可以聚类成多个簇。
  3. 每种算法的优点稍有不同:
  • k 均值可以用簇的平均值来表示簇。它还可以被看作一种分解方法,每个数据点都由其簇中心表示。
  • DBSCAN 可以检测到没有分配任何簇的“噪声点”,还可以帮助自动判断簇的数量。与其他两种方法不同,它允许簇具有复杂的形状,正如我们在 two_moons 的例子中所看到的那样。DBSCAN 有时会生成大小差别很大的簇,这可能是它的优点,也可能是缺点。
  • 凝聚聚类可以提供数据的可能划分的整个层次结构,可以通过树状图轻松查看。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: K-means聚类算法是一种简单且常用的聚类算法,其原理图可用以下步骤进行解释: 1. 初始化:随机选择K个数据点作为初始的聚类中心。这些中心点被称为质心。 2. 分配数据点:将每个数据点分配给与其最近的质心。这个步骤通过计算数据点与每个质心之间的距离来完成。 3. 更新质心:计算每个聚类的所有数据点的平均值,将这个平均值作为新的质心。这个步骤通过重新计算质心的坐标来完成。 4. 迭代更新:重复步骤2和3,直到质心不再发生变化或达到提前停止的条件。 5. 结果输出:每个数据点根据最终的质心分配到一个聚类中。 K-means聚类算法的原理图描述了以上的步骤。首先,在原始数据空间中,随机选择K个数据点(用不同的符号表示)作为初始的质心。接着,根据每个数据点与每个质心之间的距离,将数据点划分到与其最近的质心所代表的聚类中(用相同的颜色表示)。然后,根据每个聚类中的数据点的坐标计算平均值,更新质心的坐标。在重新计算质心后,重复进行分配数据点和更新质心的步骤,直到质心稳定下来,即质心不再发生变化为止。最终,根据最终质心的位置将数据点分配到对应的聚类中。 K-means聚类算法的原理图直观地展示了聚类的过程和分组的结果,使人们更容易理解和掌握这一算法的工作原理。 ### 回答2: kmeans聚类算法是一种基于距离的无监督学习算法,主要用于将数据集中的样本分成多个不同的类别。其原理图如下: 1. 初始化:首先确定要分成的类别数K,并随机选择K个样本作为初始的聚类中心点。 2. 分类:对于每个样本数据,计算其与每个聚类中心点的距离,并将其归属为与其距离最近的聚类中心的类别。 3. 更新聚类中心点:对于每个类别,计算属于该类别的所有样本的平均值,将这些平均值作为新的聚类中心点。 4. 重复步骤2和3:重复执行步骤2和3,直到聚类中心点不再发生变化或达到预先设定的迭代次数。 5. 输出结果:得到经过聚类的样本类别结果,即每个样本被归为哪一个类别。 kmeans聚类算法的核心思想是通过最小化样本数据点与所属聚类中心点之间的距离,来实现样本点的聚类。该算法的优点在于简单和高效,适用于大规模数据集。然而,kmeans算法也有一些不足之处,比如对初始聚类中心点的选择敏感,容易陷入局部最优解,并且对噪声和异常值敏感。 总而言之,kmeans聚类算法通过将样本点分配到距离最近的聚类中心点,实现对数据集的聚类,是一种常用的聚类算法。 ### 回答3: K均值聚类算法是一种无监督的机器学习算法,其原理图如下: 1. 首先,选择k个初始的聚类中心点,可以是随机选择或自定义选择。 2. 将数据样本点根据与聚类中心点的距离,分配给最近的聚类中心点所属的类别。 3. 根据划分后的数据点集计算每个类别的质心,即计算每个类别中所有样本点的均值。 4. 将每个类别的质心作为新的聚类中心点。 5. 重复步骤2和步骤3,直到聚类中心点不再变化或者达到事先设定的迭代次数。 6. 最终得到聚类结果,即将每个数据点分配到相应的聚类中心点所属的类别。 K均值聚类算法的原理是通过不断迭代优化聚类中心点的位置,使得样本点与所属聚类中心点之间的距离最小化。算法的过程可以用原理图简单描述。 原理图中有两个主要的步骤:数据点的分配和质心的更新。在数据点的分配步骤中,每个数据点会根据与聚类中心点的距离选择属于哪个聚类中心点所代表的类别。而在质心的更新步骤中,根据分配后的数据点集,计算每个类别中所有样本点的均值,即得到每个类别的质心。 通过不断迭代这两个步骤,最终得到的聚类中心点和样本点之间的距离最小化,同时使得每个聚类中心点所代表的类别内部的样本点尽量相似,而不同类别之间的样本点尽量不相似。 K均值聚类算法原理图直观地展示了算法通过逐步分配和更新聚类中心点,不断优化聚类结果的过程,从而得到数据的聚类结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

调参侠鱼尾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值