Lesson 7.2 Mini Batch K-Means与DBSCAN密度聚类

简介: Lesson 7.2 Mini Batch K-Means与DBSCAN密度聚类

文章目录



  • 除了 K-Means 快速聚类意外,还有两种常用的聚类算法。
  • (1) 是能够进一步提升快速聚类的速度的 Mini Batch K-Means 算法.
  • (2) 则是能够和 K-Means 快速聚类形成性能上互补的算法 DBSCAN 密度聚类。
# 科学计算模块
import numpy as np
import pandas as pd
# 绘图模块
import matplotlib as mpl
import matplotlib.pyplot as plt
# 自定义模块
from ML_basic_function import *
# K-Means
from sklearn.cluster import KMeans



一、Mini Batch K-Means 算法原理与实现


K-Means 算法作为最常用的聚类算法,在长期的使用过程中也诞生了非常多的变种,典型的如提高迭代稳定性的二分 K 均值法、能够显著提升算法执行速度的 Mini Batch K-Means。

由于聚类算法的稳定性可以通过 k-means++ 以及多次迭代选择最佳划分方式等方法解决,此处重点介绍 Mini Batch K-Means 算法。

顾名思义,所谓 Mini Batch K-Means 算法,就是在 K-Means 基础上增加了一个 Mini Batch 的抽样过程,并且每轮迭代中心点时,不在带入全部数据、而是带入抽样的 Mini Batch 进行计算。即每一轮的迭代操作更新为

(1) 从数据集中随机抽取一些数据形成小批量,把他们分配给最近的质心;

(2) 根据小批量数据划分情况,更新质心。

此处可以用梯度下降和小批量(Mini Batch)梯度下降之间的差异进行类比。

在梯度下降的过程中,我们带入全部数据构造损失函数,相当于带入全部数据进行参数的更新,就类似于 K-Means 带入每个簇的全部数据进行中心点位置计算。


而在小批量梯度下降的过程中,实际上我们是借助小批数据构造损失函数并对参数进行更新,就类

似于 Mini Batch K-Means 中利用小批数据更新中心点。

而 Mini Batch K-Means 的有效性,其实也和小批量梯度下降的有效性类似,那就是对于一组规律

连贯的数据集来说,小批量数据能够很大程度反映整体数据集规律,因此带入小批量数据进行计算是有效的。


此外,Mini Batch K-Means 相比 K-Means 的优劣势,也和小批量梯度下降对比梯度下降过程类似,采用小批数据带入进行计算能够极大缩短单次运算时间,因此迭代速度会更快,但由于小批量数据还是和整体数据之间存在差异,因此每次计算结果的精度不如带入整体数据的计算结果。


不过对于 K-Means 是否会落入局部最小值陷阱,我们可以通过 k-means++ 以及重复多次训练模型来解决,因此 Mini Batch K-Means 并不用承担跨越局部最小值陷阱的职责,所以 Mini Batch K-

Means 对比 K-Means,其实就相当于牺牲了部分精度来换取聚类速度。


而聚类算法毕竟不是有监督学习算法,因此如果是面对海量数据的聚类,我们是可以考虑牺牲部分精度来换取聚类执行的速度的(当然这也要视情况而定)。


此处所谓小批量聚类精度不足,指的是小批量聚类和 K-Means 聚类结果上的差异,一般我们会认为 K-Means 聚类是精准的,而小批量聚类如果出现了和 K-Means 聚类不同的结果,则说明小批量聚类出现了误差,也就是精度不足。


接下来尝试调用相关评估器进行 Mini Batch K-Means 聚类:


from sklearn.cluster import MiniBatchKMeans
  • 我们发现,MiniBatchKMeans 中部分参数和 K-Means 中参数不同,我们针对这些不同的参数来进行解释。
MiniBatchKMeans?
Name Description
batch_size 小批量抽样的数据量
compute_labels 在聚类完成后,是否对所有样本进行类别计算


max_no_improvement 当SSE不发生变化时,质心最多再迭代多少次
init_size 用于生成初始中心点的样本数量
reassignment_ratio 某比例,数值越大、样本数越少的簇被重新计算中心点的概率就越大


能够发现,MiniBatchKMeans 在参数设置上和 K-Means 有两方面差异:

(1) 是在迭代收敛条件上,通过查看说明文档我们不难发现,MiniBatchKMeans 主要通过 max_no_improvement 和 max_iter 两个参数来控制收敛,在默认情况下不采用 tol 参数。其根本原因在于小批量聚类往往需要迭代很多轮,因而出实际未收敛、但现两次相邻的迭代结果中 SSE 变化值小于 tol 的情况的概率会显著增加,因此此时我们不能以 tol 条件作为收敛条件;

(2) 是在控制结果精度上,尽管小批量聚类是用精度换速度,但仍然提供了可以提升聚类精度的参数,也就是 reassignment_ratio,当发现聚类结果不尽如人意时,可以适当提升该参数的取值。

接下来,尝试调用相关评估器进行建模:


mbk = MiniBatchKMeans(n_clusters=2)
np.random.seed(23)
X, y = arrayGenCla(num_examples = 20, num_inputs = 2, num_class = 2, deg_dispersion = [2, 0.5])
plt.scatter(X[:, 0],X[:, 1],c=y)

0f812c5eaac945d297aad620d8bc3518.png

mbk.fit(X)
#MiniBatchKMeans(n_clusters=2)
# 观察聚类结果
plt.scatter(X[:, 0], X[:, 1], c=mbk.labels_)
plt.plot(mbk.cluster_centers_[0, 0], mbk.cluster_centers_[0, 1], 'o', c='red')
plt.plot(mbk.cluster_centers_[1, 0], mbk.cluster_centers_[1, 1], 'o', c='cyan')

3022938cb1b346bca0253f51789cf22c.png


  • 我们发现,在简单数据集的聚类过程中,MiniBatchKMeans 和 KMeans 并没有太大差异,接下来我们尝试在更大的数据集上来进行聚类,测试二者的精度和运算速度:
np.random.seed(23)
X, y = arrayGenCla(num_examples = 1000000, num_inputs = 10, num_class = 5, deg_dispersion = [4, 1])
km = KMeans(n_clusters=5, max_iter=1000)
mbk = MiniBatchKMeans(n_clusters=5, max_iter=1000)
# 导入时间模块
import time
# K-Means聚类用时
t0 = time.time()
km.fit(X)
t_batch = time.time() - t0
t_batch
#12.087070941925049
# MiniBatchKMeans聚类用时
t0 = time.time()
mbk.fit(X)
t_batch = time.time() - t0
t_batch
#3.6028831005096436


np.random.seed(23)
X, y = arrayGenCla(num_examples = 1000000, num_inputs = 10, num_class = 5, deg_dispersion = [4, 1])
km = KMeans(n_clusters=5, max_iter=1000)
mbk = MiniBatchKMeans(n_clusters=5, max_iter=1000)
# 导入时间模块
import time
# K-Means聚类用时
t0 = time.time()
km.fit(X)
t_batch = time.time() - t0
t_batch
#12.087070941925049
# MiniBatchKMeans聚类用时
t0 = time.time()
mbk.fit(X)
t_batch = time.time() - t0
t_batch
#3.6028831005096436


  • 能够发现,MiniBatchKMeans 聚类速度明显快于 K-Means 聚类,接下来查看二者 SSE 来对比其精度:
km.inertia_
#49994316.22276671
mbk.inertia_
#50166895.159873486


能够发现,MiniBatchKMeans 精度略低于 K-Means,但整体结果相差不大,基本可忽略不计,当然这也是因为当前数据集分类性能较好的原因。

不过经此也可验证 MiniBatchKMeans 聚类的有效性。一般来说,对于 2 万条以上的数据集,MiniBatchKMeans 聚类的速度优势就会逐渐显现。

当然,如果希望更进一步提高迭代速度,可以适度减少 batch_size、减少 reassignment_ratio、max_no_improvement 这三个参数,不过代价就是聚类的精度可能会进一步降低,而如果希望提高精度,则可以提升 reassignment_ratio 参数,不过相应的,运行时间将会有所提升。


二、DBSCAN 密度聚类基本原理与实践

1. K-Means 聚类算法的算法特性


尽管 MiniBatchKMeans 能够有效提高聚类速度、提升聚类效率,但从最终聚类效果上来看,MiniBatchKMeans 和 K-Means 聚类算法仍然属于同一类聚类——假设簇的边界是凸形的聚类。

换而言之,就是这种聚类能够较好的捕捉圆形/球形边界(直线边界可以看成是大直径的圆形边界),而对于非规则类边界,则无法进行较好的聚类,当然这也是和 K-Means 聚类的核心目的:让更相近同一个中线点的数据属于一个簇,息息相关。

但有些时候,更接近同一个中心点的数据却不一定应该属于一个簇,例如如下情况:

from sklearn.datasets import make_moons
X, y = make_moons(200, noise=0.05, random_state=24)
plt.scatter(X[:,0], X[:,1], c = y)


35273747c11d421aa561d4869ffb60b2.png



其中 make_moons 函数是 datasets 模块中创造数据集的函数,默认创建月牙形数据分布的数据集,并且 noise 参数取值越小、数据分布越贴近月牙形状。

当然此时我们发现,上述数据集明显可分为两个簇,但两个簇的边界却不是凸型的。此时如果我们用 K-Means 对其进行聚类,则会得到如下结果:


km = KMeans(n_clusters=2)
km.fit(X)
#KMeans(n_clusters=2)
plt.scatter(X[:,0], X[:,1], c = km.labels_)
plt.plot(km.cluster_centers_[:,0], km.cluster_centers_[:,1], 'ro')

7537c84582df4f65ac3ae2575cd387fd.png



从上述结果中也能很明显的看出 K-Means 聚类的凸型边界,但很明显,此时聚类结果并不合理,上图中有多处彼此相邻但却不属于同一类的情况出现。

此时如果我们希望捕获上述非凸的边界,则需要使用一种基于密度的聚类方法,也就是我们将要介绍的 DBSCAN 密度聚类。

不过此处需要强调的是,尽管上述情况主观判断不太合理,但最终上述结果是否可用,还是需要结合实际业务进行考虑,这也是无监督学习算法没有统一的评价标准的具体表现。

此处我们只能说 K-Means 算法性能使得其无法捕获不规则边界,但这个特性导致的结果好坏无法直接通过数据结果进行得出。


2. DBSCAN 密度聚类基本原理

  • 和 K-Means 依据中心点划分数据集的思路不同,DBSCAN 聚类则是试图通过寻找特征空间中点的分布密度较低的区域作为边界,并进一步以此划分数据集。

正是因为以低密度区域作为边界,DBSCAN 最终对数据的划分边界很有可能是不规则的,从而突破了 K-Means 依据中心点划分数据集从而使得边界是凸型的限制。

当然对于给予密度的聚类算法,最重要的是给出密度的相关的定义。在 DBSCAN 中,我们通过两个概念和密度密切相关:分别是半径(eps)与半径范围内点的个数(num_samples)。

对于数据集中任意一个点,只要给定一个 eps,就能算出对应的 num_samples,例如对于下述 A 点,在一个 eps 范围内,num_samples 为 7(包括自己)。

401fdc1605c547bf89f3eed63cc18555.png



当然,eps 越小、num_samples 越大,则说明该点所在区域密度较高。

当然,我们可以据此设置一组参数,即半径(eps)和半径范围内至少包含多少点(min_samples)作为评估指标,来对数据集中不同的点进行密度层面的分类。

例如我们令 eps=Eps(某个数),min_samples=6,并且如果某点在一个 Eps 范围内包含的点的个数大于 min_samples,则称该点为核心点(core point),如下图中的 A 点。

而如果某个点不是核心点,但是在某个核心点的一个 eps 领域内,则称该点为边界点,例如下图 B 点。

而如果某点既不是核心点也不是边界点,则成该点为噪声点,如下图的 C 点32521b5e4ebe4ac08691a9c5b813620f.png


32521b5e4ebe4ac08691a9c5b813620f.png32521b5e4ebe4ac08691a9c5b813620f.png


当我们对数据集中的所有点完成上述三类的划分之后,接下来,我们一个 eps 范围内的核心点化为一个簇,并且将边界点划归到一个临近的核心点所属簇中,并且抛弃噪声点,最终完成数据集整体的划分。

而实际上 DBSCAN 整体划分过程,就是在将高密度区域划分成一个簇,将低密度区域视作不同簇的分界线。

很明显,在 DBSCAN 聚类中,核心参数就是 eps 和 min_samples,其不仅可以控制高低密度区域的划分,并且可以实际控制聚成几类的结果:

当 eps 较小而 min_samples 较大时,核心点的定义较为严格、同一个簇对簇内的密度要求更高,此时更容易划分出多个簇;反之,划分成的簇的个数可能会更少。

接下来我们尝试在 sklearn 进行 DBSCAN 建模试验。



3. DBSCAN 密度聚类的 sklearn 实现

from sklearn.cluster import DBSCAN
DBSCAN?


  • 其中核心参数就是上面介绍的 eps 和 min_samples,其他参数都是距离计算相关和最近邻计算相关的参数,暂时可以不做考虑。接下来围绕上述月牙型数据进行建模:
# 实例化模型
DB = DBSCAN(eps=0.3, min_samples=10)
# 训练模型
DB.fit(X)
#DBSCAN(eps=0.3, min_samples=10)
# 查看聚类结果
plt.scatter(X[:,0], X[:,1], c = DB.labels_)


8b7902be34dd4068849fdc7fe95b5459.png

  • 能够发现,DBSCAN 通过捕获低密度区域作为聚类划分的边界线,使得最终聚类结果和预想中的情况更加接近。接下来我们尝试在上一小节定义的数据集中执行 DBSCAN 聚类:
np.random.seed(23)
X, y = arrayGenCla(num_examples = 20, num_inputs = 2, num_class = 2, deg_dispersion = [2, 0.5])
plt.scatter(X[:, 0],X[:, 1],c=y)


d74d2ac7fce0488c98eea07686bb4b3a.png

DB = DBSCAN(eps=0.5, min_samples=5).fit(X)
plt.scatter(X[:,0], X[:,1], c = DB.labels_)
DB.labels_
#array([ 0,  0,  0,  0,  0,  0,  0,  0,  0, -1,  0,  0,  0,  0,  0,  0,  0,
#        0, -1,  0,  1,  1,  1,  1,  1,  1,  1, -1,  1,  1,  1,  1,  1, -1,
#        1,  1,  1,  1,  1,  1])

61e4e60c87a44c90a0c26c019d49965f.png

  • 此时出现了更多的噪声点,而如果降低密度要求,则会有更多的点被划分到不同的簇中。
DB = DBSCAN(eps=0.6, min_samples=4).fit(X)
plt.scatter(X[:,0], X[:,1], c = DB.labels_)



791738987334457eb7894e0223acf272.png


至此,我们就完成了 DBSCAN 算法从理论到实践的全过程。

还是需要值得一提的是,由于聚类算法的特殊性,导致聚类算法本身的原理和应用难度都远低于有监督学习算法,并且在实际进行聚类的过程中,选择算法的过程要重于调参的过程,而且该过程需要加入实际业务背景作为聚类效果好坏评估的更加具体的指导意见。

目前介绍的 K-Means 和 DBSCAN,能够在实际分类性能上形成很好的互补,建议在使用的过程中先尝试 K-Means,如效果不佳,则可考虑尝试使用 DBSCAN 进行聚类。























目录
打赏
0
0
0
0
2
分享
相关文章
如何保证分布式文件系统的数据一致性
分布式文件系统需要向上层应用提供透明的客户端缓存,从而缓解网络延时现象,更好地支持客户端性能水平扩展,同时也降低对文件服务器的访问压力。当考虑客户端缓存的时候,由于在客户端上引入了多个本地数据副本(Replica),就相应地需要提供客户端对数据访问的全局数据一致性。
31853 78
如何保证分布式文件系统的数据一致性
HTML5+CSS3前端入门教程---从0开始通过一个商城实例手把手教你学习PC端和移动端页面开发第8章FlexBox布局(上)
HTML5+CSS3前端入门教程---从0开始通过一个商城实例手把手教你学习PC端和移动端页面开发第8章FlexBox布局
17655 18
灵骏可预期网络:Built for AI Infrastructure
通用人工智能离我们越来越近,全世界的关注和投入正在带来日新“周”异的变化。回顾人工智能的诞生和发展历程,人类计算能力的进步几乎牵动了每一次的重大技术突破,当前的大模型热潮更是如此,只是动辄千万亿参数级的模型体量,所需计算资源远超单颗芯片的上限,超大规模的计算集群成为支撑技术发展和应用创新的关键基础设施。面向智能:云基础设施网络技术面临新挑战如何突破单个芯片、单个服务器节点的算力上限,在超大规模情况
31193 10
灵骏可预期网络:Built for AI Infrastructure
设计模式(C++版)
看懂UML类图和时序图30分钟学会UML类图设计原则单一职责原则定义:单一职责原则,所谓职责是指类变化的原因。如果一个类有多于一个的动机被改变,那么这个类就具有多于一个的职责。而单一职责原则就是指一个类或者模块应该有且只有一个改变的原因。bad case:IPhone类承担了协议管理(Dial、HangUp)、数据传送(Chat)。good case:里式替换原则定义:里氏代换原则(Liskov 
36193 19
设计模式(C++版)
带你简单了解Chatgpt背后的秘密:大语言模型所需要条件(数据算法算力)以及其当前阶段的缺点局限性
带你简单了解Chatgpt背后的秘密:大语言模型所需要条件(数据算法算力)以及其当前阶段的缺点局限性
24468 14
重生之---我测阿里云U1实例(通用算力型)
阿里云产品全线降价的一力作,2023年4月阿里云推出新款通用算力型ECS云服务器Universal实例,该款服务器的真实表现如何?让我先测为敬!
36515 15
重生之---我测阿里云U1实例(通用算力型)
为笔记本更换固态硬盘的方法
本文介绍为笔记本电脑拆机、更换固态硬盘的具体方法~
18011 41
为笔记本更换固态硬盘的方法
Redis性能高30%,阿里云倚天ECS性能摸底和迁移实践
Redis在倚天ECS环境下与同规格的基于 x86 的 ECS 实例相比,Redis 部署在基于 Yitian 710 的 ECS 上可获得高达 30% 的吞吐量优势。成本方面基于倚天710的G8y实例售价比G7实例低23%,总性价比提高50%;按照相同算法,相对G8a,性价比为1.4倍左右。
【分布式技术专题】「分布式技术架构」手把手教你如何开发一个属于自己的限流器RateLimiter功能服务
随着互联网的快速发展,越来越多的应用程序需要处理大量的请求。如果没有限制,这些请求可能会导致应用程序崩溃或变得不可用。因此,限流器是一种非常重要的技术,可以帮助应用程序控制请求的数量和速率,以保持稳定和可靠的运行。
29747 52
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问