聚类算法及其模型评估

聚类(Clustering)就是按照某个特定标准把一个数据集分割成不同的类或簇,使得同一个簇内的数据对象的相似性尽可能大,同时不在同一个簇中的数据对象的差异性也尽可能地大。即聚类后同一类的数据尽可能聚集到一起,不同类数据尽量分离。

主要的聚类方法可以划分成如下几类:划分方法、层次方法、基于密度的方法、基于网络的方法、基于模型的方法。

聚类和分类有什么区别

聚类(Clustering)

聚类,简单地说就是把相似的东西分到一组,聚类的时候,我们并不关心某一类是什么,我们需要实现的目标只是把相似的东西聚到一起。一个聚类算法通常只需要知道如何计算相似度就可以开始工作了,因此聚类通常并不需要使用训练数据进行学习,在机器学习中属于无监督学习

分类(Classifification)

分类,对于一个分类器,通常需要你告诉它“这个东西被分为某某类”。一般情况下,一个分类器会从它 得到的训练集中进行学习,从而具备对未知数据进行分类的能力,在机器学习中属于监督学习

k-means算法

k-means是划分方法中较经典的聚类算法之一。由于该算法的效率高,所以在对大规模数据进行聚类时被广泛应用。目前,许多算法均围绕着该算法进行扩展和改进。 k-means算法以k为参数,把n个对象分成k个簇,使簇内具有较高的相似度,而簇间的相似度较低。

k-means.png

k-means的算法流程

输入:包含n个对象的数据和簇的数目k

(1) 随机地选择k个对象,它们初始地代表着k个簇的中心或者说平均值

(2) 对每个对象,根据其与各簇中心的距离,将它划分给最近的簇

(3) 重新计算每个簇的平均值

(4) 重复步骤(2)、(3)知道簇中心不再变化

输出:n个对象到k个簇,使平方误差准则最小

平方误差准则定义如下:

E = \sum\limits_{i=1}^k\sum\limits_{p\in C_i}||p - m_i||^2

这里E是数据中所有对象的平方误差的总和,p是对象,m_i是簇的平均值,C_i是每个簇的对象集。该目标函数使生成的簇尽可能紧凑独立,使用的距离度量是欧氏距离,当然也可以用其他距离度量。当平方误差最小,簇中心不再变化,循环结束。

k-means算法的优缺点

优点:

​ 简单、速度快、适合发现球形聚类

缺点:

  1. k值不好选取,解决方案:可用GridSearch
  2. 对初始聚类中心敏感,解决方案:多初始化几遍,选取损失函数小的
  3. 对噪音和异常值免疫能力差
  4. 不能解决非凸数据

DBSCAN

DBSCAN(Density-Based Spatial Clustering of Applications with Noise,具有噪声的基于密度的聚类方法)是一种典型的基于密度的空间聚类算法。该算法将具有足够密度的区域划分为簇,并在具有噪声的空间数据库中发现任意形状的簇,它将簇定义为密度相连的点的最大集合。

要理解DNSCAN算法的流程,首先要熟悉几个概念:

  1. 算法需要给定两个参数:邻域半径eps和密度阈值minPts。

    这两个算法参数实际可以刻画什么叫密集——当邻域半径eps内的点的个数大于密度阈值minPts时,就是密集。

  2. 3种点的类别:核心点,边界点和噪声点。

    邻域半径eps内样本点的数量大于等于minPts的点叫做核心点。不属于核心点但在某个核心点的邻域内的点叫做边界点。既不是核心点也不是边界点的是噪声点。

DBSCAN3种点的类别.jpg
  1. 4种点的关系:密度直达,密度可达,密度相连,非密度相连。

    如果P为核心点,Q在P的eps邻域内,那么称P到Q密度直达。任何核心点到其自身密度直达,密度直达不具有对称性,如果P到Q密度直达,那么Q到P不一定密度直达。

    如果存在核心点P2,P3,……,Pn,且P1到P2密度直达,P2到P3密度直达,……,P(n-1)到Pn密度直达,Pn到Q密度直达,则P1到Q密度可达。密度可达也不具有对称性。

    如果存在核心点S,使得S到P和Q都密度可达,则P和Q密度相连。密度相连具有对称性,如果P和Q密度相连,那么Q和P也一定密度相连。密度相连的两个点属于同一个聚类簇。

    如果两个点不属于密度相连关系,则两个点非密度相连。非密度相连的两个点属于不同的聚类簇,或者其中存在噪声点。

DBSCAN4种点的关系.jpg

DBSCAN的算法流程

输入:邻域半径eps,密度阈值minPts

(1) 扫描数据集中每点,如果某点p的eps邻域半径范围内包含的点多于minPts个,则将其纳入核心点列表,并将其密度直达的点形成对应的临时聚类簇。

(2) 对于每一个临时聚类簇,检查其中的点是否为核心点,如果是,将该点对应的临时聚类簇和当前临时聚类簇合并,得到新的临时聚类簇。重复此操作,直到当前临时聚类簇中的每一个点要么不在核心点列表,要么其密度直达的点都已经在该临时聚类簇,该临时聚类簇升级成为聚类簇。最终所有临时簇全部被处理为止。

输出:簇的划分结果

DBSCAN算法的优缺点

优点:

  1. 不需要指定簇的个数
  2. 可以发现任意形状的簇
  3. 擅长找到离群点

缺点:

  1. 对于高维度数据不好处理
  2. 参数难以选择

分层聚类

分层聚类(Hierarchical Clustering)是通过计算不同类别数据点间的相似度来创建一棵有层次的嵌套聚类树。在聚类树中,不同类别的原始数据点是树的最低层,树的顶层是一个聚类的根节点。创建聚类树有自下而上合并(凝聚)和自上而下分裂两种方法。

分层聚类的算法流程:

注:这里以自下而上凝聚的方法为例。

  1. 初始化,把每个样本(假设一共N个样本)各自归为一类,计算每两个类之间的距离,也就是样本与样本之间的相似度
  2. 寻找各个类之间最相近的两个类,把他们归为同一类
  3. 重新计算新生成的这个类与各个旧类之间的距离
  4. 重复(2)、(3)步骤,知道所有样本都归为一类,算法结束(当然,我们可以事先给定n_clusters参数,表示分成几个聚类簇,当算法达到这个阈值时,迭代也会结束。)
分层聚类.gif

通过这张gif图,就能更加清楚地看出分层聚类的工作流程了。

关于如何判断两个类之间的距离,也就是相似度,有不少办法,这里介绍三种:

  1. Single Linkage

    Single Linkage方法是将两个组合数据点中距离最近的两个数据点间的距离作为这两个组合数据点的距离。这种方法容易受到极端值的影响。两个很相似的组合数据点可能由于其中的某个极端的数据点距离较近而组合在一起。

  2. Complete Linkage

    complete Linkage的计算方法与Single Linkage相反,将两个组合数据点中距离最远的两个数据点间的距离作为这两个组合数据点的距离。Complete Linkage的问题也与Single Linkage相反,两个不相似的组合数据点可能由于其中的极端值距离较远而无法组合在一起。

  3. Average Linkage

    Average Linkage的计算方法是计算两个组合数据点中的每个数据点与其他所有数据点的距离。将所有距离的均值作为两个组合数据点间的距离。这种方法计算量比较大,但结果比前两种方法更合理。

分层算法的优缺点

优点:

  1. 可以发现类的层次关系
  2. 能帮助解决k-means不能解决的非凸数据

缺点:

  1. 时间复杂度高
  2. 贪心算法,一步错步步错

聚类模型评估

评价聚类方法分簇的最佳数量和分簇效果。

1.轮廓系数(silhouette coefficient)

轮廓系数综合考虑了内聚度和分离度两种因素。

样本i轮廓系数:

s(i) = \frac{b(i) - a(i)}{max\{a(i), b(i)\} }

a(i)表示样本i与其所在簇内其他样本的平均距离,b(i)表示样本i与其他簇样本的平均距离

聚类总的轮廓系数SC为:

SC = \frac{1}{N}\sum\limits_{i=1}^{N}s(i)

轮廓系数取值范围为[-1,1],取值越接近1则说明聚类性能越好,相反,取值越接近-1则说明聚类性能越差。轮廓系数最高的簇的数量表示簇的数量的最佳选择。

轮廓系数使用案例

  1. 准备数据
# 导包
import numpy as np
from sklearn import datasets
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
from sklearn.metrics import silhouette_score

# 生成数据
X, y = datasets.make_blobs(random_state=100)    # make_blobs 默认100样本,2个特征
print(X.shape)    # (100, 2)
plt.scatter(X[:, 0], X[:, 1], c=y)

生成的数据如下所示,从图中可以看出分为3簇最好:

准备数据.png
  1. 计算轮廓系数
score = []
for i in range(2, 7):
    kmeans = KMeans(n_clusters = i)
    kmeans.fit(X)
    y_ = kmeans.predict(X)    # 预测类别 == 标签

    print('当聚类类别数量是%d的时候,评价指标的轮廓系数是:'%i, silhouette_score(X, y_))
    score.append(silhouette_score(X, y_))

plt.rcParams['font.sans-serif'] = ['KaiTi']   # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
plt.rcParams['font.size'] = 18  # 设置字体大小
plt.plot(range(2,7), score)
plt.xlabel('K值')
plt.ylabel('轮廓系数')

得到如下结果:

当聚类类别数量是2的时候,评价指标的轮廓系数是: 0.6380785232724551
当聚类类别数量是3的时候,评价指标的轮廓系数是: 0.8353147343303
当聚类类别数量是4的时候,评价指标的轮廓系数是: 0.692708669793985
当聚类类别数量是5的时候,评价指标的轮廓系数是: 0.5318434130364085
当聚类类别数量是6的时候,评价指标的轮廓系数是: 0.3814586763403103

轮廓系数.png

当k值为3时,轮廓系数最高,聚类效果最好。

2.兰德系数(adjusted rand index)

如果 C 是一个真实簇的标签分配, K 是簇的个数,我们定义a和b为:

  • a,在 C 中的相同集合的与 K 中的相同集合中的元素对数
  • b,在 C 中的不同集合与 K 中的不同集合中的元素对数

兰德系数为:

RI = \frac{a + b}{C_2^{n_{samples}}}

其中C_2^{n_{samples}}是数据集中可能的数据对的总数。RI取值范围为[0,1],值越大意味着聚类结果与真实情况越吻合。

兰德系数使用案例

  1. 准备数据

数据仍用上文轮廓系数的数据。

  1. 计算兰德系数
from sklearn.metrics import adjusted_rand_score    # 兰德系数

score2 = []
for i in range(2, 7):
    kmeans = KMeans(n_clusters = i)
    kmeans.fit(X)
    y_ = kmeans.predict(X)    # 预测类别 == 标签

    print('当聚类类别数量是%d的时候,评价指标的兰德系数是:'%i, adjusted_rand_score(y, y_))
    score2.append(adjusted_rand_score(y, y_))

plt.plot(range(2,7), score2)
plt.xlabel('K值')
plt.ylabel('兰德系数')

得到如下结果:

当聚类类别数量是2的时候,评价指标的兰德系数是: 0.5628321618378193
当聚类类别数量是3的时候,评价指标的兰德系数是: 1.0
当聚类类别数量是4的时候,评价指标的兰德系数是: 0.8704389719572353
当聚类类别数量是5的时候,评价指标的兰德系数是: 0.7187670100598754
当聚类类别数量是6的时候,评价指标的兰德系数是: 0.5789975932695749

兰德系数.png

当k为3是,兰德系数最大,聚类效果最好。

然而,RI得分不能保证随机标签分配(random label assignments)会获得接近零的值(特别是如果簇的数量与样本数量有着相同的规模排序)。

为了抵消这种影响,我们可以通过定义 adjusted Rand index 来低估(discount)随机标签的预期RI——E[RI],如下所示:

ARI = \frac{RI - E[RI]}{max(RI) - E[RI]}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容

  • 聚类算法 前面介绍的集中算法都是属于有监督机器学习方法,这章和前面不同,介绍无监督学习算法,也就是聚类算法。在无监...
    飘涯阅读 41,248评论 3 52
  • 其他 这篇文章的整体排版主要是根据个人的博客来哒,如果感兴趣的话可以去我的自己搭建的个人博客看这篇文章。 正文 聚...
    DeamoV阅读 1,186评论 0 2
  •   在《战国策·齐策三》中有这么一句话:“物以类聚,人以群分”,用于比喻同类的东西常聚在一起,志同道合的人相聚成群...
    小小何先生阅读 920评论 0 1
  • 1. 章节主要内容 “聚类”(clustering)算法是“无监督学习”算法中研究最多、应用最广的算法,它试图将数...
    闪电随笔阅读 5,003评论 1 24
  • 一瞬间的美好 只是短暂的 大多无用时有用
    无点有感阅读 169评论 0 8