聚类算法

分类是算法基于已有标签的数据进行学习并对新数据进行分类,而聚类则是在完全没有标签的情况下,有算法“猜测”哪些数据像是应该“堆”在一起的,并且让算法给不同的“堆”里的数据贴上一个数字标签。

一、K 均值聚类算法

关于k-means,可以 参考 k-means学习笔记》
用手工生成的数据集来展示聚类算法的工作原理。

#聚类算法
import numpy as np
import matplotlib.pyplot as plt #导入画图工具
from sklearn.datasets import make_blobs #导入数据生成工具
from sklearn.cluster import KMeans #导入 KMeans 工具

#生成份数为1的数据集
blobs = make_blobs(random_state=1, centers=1)
X_blobs = blobs[0]

#绘制散点图
plt.scatter(X_blobs[:,0], X_blobs[:,1],c='r', edgecolors='k')
#plt.show()

#要求 KMeans 将数据聚为3类
kmeans = KMeans(n_clusters=3)

kmeans.fit(X_blobs)

#画图
x_min, x_max = X_blobs[:, 0].min()-0.5, X_blobs[:, 0].max() + 0.5
y_min, y_max = X_blobs[:, 1].min()-0.5, X_blobs[:, 1].max() + 0.5
xx, yy = np.meshgrid(np.arange(x_min, x_max, .02),
                     np.arange(y_min, y_max, .02))
Z = kmeans.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.figure(1)
plt.clf()
plt.imshow(Z, interpolation='nearest',
           extent=(xx.min(), xx.max(), yy.min(), yy.max()),
           cmap=plt.cm.summer, aspect='auto', origin='lower')

plt.plot(X_blobs[:,0], X_blobs[:,1], 'r.', markersize=5)

#用蓝色的叉号代表聚类的中心
centeroids= kmeans.cluster_centers_
plt.scatter(centeroids[:, 0], centeroids[:, 1],
            marker='x', s=150, linewidths=3, color='b', zorder=10)
plt.xlim(x_min, x_max)
plt.ylim(y_min, y_max)
plt.xticks(())
plt.yticks(())
plt.show()

#打印 KMEANS 进行聚类的标签
print(" K均值的聚类标签:\n{}".format(kmeans.labels_))

生成的数据集为:


9.4blobs.png

经过KMEANS 聚类的结果为:


9.4k_means.png
 K均值的聚类标签:
[1 1 0 2 2 2 1 1 0 2 1 2 1 0 1 2 2 1 0 0 2 0 1 1 1 1 2 1 1 1 0 0 1 1 2 0 2
 0 1 0 2 1 0 0 2 2 2 1 0 1 0 1 2 0 2 2 0 2 2 1 2 0 2 1 0 2 0 0 1 2 2 1 2 2
 2 1 2 1 1 0 2 0 2 2 0 1 2 1 0 0 2 1 0 0 2 2 1 2 2 1]

1. 如图所示,指定了K 均值的n_clusters=3,所以K 均值将数据点聚为3类,图中的X号,就代表了K均值对数据进行聚类的3个中心点。
2. K均值对数据的聚类和分类有点相似,是用 0, 1, 2三个数字来代表数据的类,并且存储在.labels_属性中。
3. K均值算法的局限性是,塔认为,每个数据点到聚类中心的方向都是同等重要的,这样一来,对于“形状”复杂的数据集来说。 K均值就不能很好的工作。

二、凝聚聚类算法

凝聚聚类(agglomerative clustering)指的是许多基于相同原则构建的聚类算法,这一原则是:算法首先声明每个点是自己的簇,然后合并两个最相似的簇,直到满足某种停止准则为止。scikit-learn中实现的停止准则是簇的个数,因此相似的簇被合并,直到仅剩下指定个数的簇。

1.可以参考 《聚类算法:凝聚层次聚类》
2.关于树状图的绘制可以参考 《python 凝聚聚类之树状图》
以下以图形化的方式来展现凝聚聚类算法的工作机制(数据集仍旧使用上述生成值)

#凝聚聚类算法机制可视化
import matplotlib.pyplot as plt #导入画图工具
from sklearn.datasets import make_blobs #导入数据生成工具
from scipy.cluster.hierarchy import dendrogram, ward

#生成份数为1的数据集
blobs = make_blobs(random_state=1, centers=1)
X_blobs = blobs[0]

#使用连线的方式进行可视化
# 在数据组 X_blobs 上应用 ward 聚类函数,返回聚类过程中所跨越距离的数组
linkage = ward(X_blobs)
# 绘制树状图
dendrogram(linkage)
ax= plt.gca()

plt.xlabel("Ssmple index")
plt.ylabel("Cluster distance")
plt.show()

执行结果如图:


9.5.png

从图中可以看到,凝聚聚类算法是自下而上,不断的合并相似的聚类中心,以便让类别越来越少,同时,每个聚类中心的距离也就 越来越远,这种逐渐生成聚类的方法称为 Hierarchy clustering.
与K 均值聚类类似,凝聚聚类算法也无法对“形状”复杂的数据进行正确的聚类。

三、DBSCAN聚类算法

DBSCAN 基于密的有噪声应用空间聚类(Density-Based Spatial Clustering of Applications with Noise)是一个比较有代表性的基于密度的聚类算法,与机遇层次聚类方法不同,它将簇定义为密度相连的点的最大集合,能够把具有足够高密度的区域划分为簇,并可在噪声的空间数据库中发现任意形状的聚类。
简单讲,DBSCAN 是通过对特征空间内的密度进行检测,密度大的地方它会认为是一个类,而密度相对小的地方它会认为是一个分界线。

详细的原理以及介绍可以参考这篇博文 《DBSCAN方法及应用》

仍旧使用上述的数据进行聚类。

#DBSCAN 聚类算法
from sklearn.datasets import make_blobs #导入数据生成工具
from sklearn.cluster import DBSCAN
import matplotlib.pyplot as plt #导入画图工具

#生成份数为1的数据集
blobs = make_blobs(random_state=1, centers=1)
X_blobs = blobs[0]

db = DBSCAN()

cluster = db.fit_predict(X_blobs)

#绘制散点图
plt.scatter(X_blobs[:,0], X_blobs[:,1],c=cluster, cmap=plt.cm.cool,
            s=60, edgecolors='k')

plt.xlabel("Feature 0")
plt.ylabel("Feature 1")

plt.show()

执行结果为:


9.6DBSCAN.png
聚类标签为:
[-1  0 -1  0 -1  0  0  0  0  0  0  0  0  0 -1  0  0  0  0  0  0  0  0  0  0
 -1  0  0 -1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 -1  0  0
  0  0  0  0  0  0  0 -1  0  0  0  0  0  0 -1  0  0  0  0  0  0  0  0  0 -1
 -1  0  0  0  0 -1  0  0 -1  0  0 -1  0  0  0  0  0  0  0  0 -1  0  0  0 -1]

从图中可以看出,中间深色的数据点密度相对较大,因此 DBSCAN 把它们归为一类,外围浅色的数据点,DBSCAN 认为不属于任何一类,所以放入了“噪声”这个类别,因此,聚类标签中会有-1这种 类别,代表噪声。

注:关于DBSCAN 的参数详解,可以参考《 用scikit-learn学习DBSCAN聚类 》
下面再尝试调整 DBSCAN 中非常重要的两个参数

3.1 eps

eps :考虑划入同一类的样本有多远,该值设置越大,则聚类所覆盖的数据点越多。eps默认是0.5

#DBSCAN 聚类算法
from sklearn.datasets import make_blobs #导入数据生成工具
from sklearn.cluster import DBSCAN
import matplotlib.pyplot as plt #导入画图工具

#生成份数为1的数据集
blobs = make_blobs(random_state=1, centers=1)
X_blobs = blobs[0]

#2.设置 eps =2
db1 = DBSCAN(eps=2)
clusters1 = db1.fit_predict(X_blobs)
#绘制散点图
plt.scatter(X_blobs[:,0], X_blobs[:,1],c=clusters1, cmap=plt.cm.cool,
            s=60, edgecolors='k')

plt.xlabel("Feature 0")
plt.ylabel("Feature 1")

plt.show()

#打印聚类个数
print('\n\neps=2时,聚类标签为:\n{}'.format(clusters))

执行结果如下:

eps=2时,聚类标签为:
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
9.6eps=2.png

可以看出,所有的点都变成了浅色,并不代表所有的点都是噪声,而是所有的点都被划归到一个类中了,因为增加了 eps 的值,所以把更远的数据点都拉入到这个聚类中了。

3.2 min_samples

min_samples:指定的是在某个数据点周围,被看成聚类核心点的个数,即样本点要成为核心对象所需要的ϵ-邻域的样本数阈值。值越大,则核心数据点越少,噪声也就越多。min_samples 默认为 5。

#DBSCAN 聚类算法
from sklearn.datasets import make_blobs #导入数据生成工具
from sklearn.cluster import DBSCAN
import matplotlib.pyplot as plt #导入画图工具

#生成份数为1的数据集
blobs = make_blobs(random_state=1, centers=1)
X_blobs = blobs[0]

#3.设置 min_samples=20
db2 = DBSCAN(min_samples=20)
clusters2 = db2.fit_predict(X_blobs)
#绘制散点图
plt.scatter(X_blobs[:,0], X_blobs[:,1],c=clusters2, cmap=plt.cm.cool,
            s=60, edgecolors='k')

plt.xlabel("Feature 0")
plt.ylabel("Feature 1")

plt.show()

#打印聚类个数
print('\n\nmin_samples=20时,聚类标签为:\n{}'.format(clusters2))

执行结果如下:

min_samples=20时,聚类标签为:
[-1 -1 -1 -1 -1 -1 -1 -1 -1  0 -1 -1  0 -1 -1 -1 -1 -1  0 -1 -1  0  0  0 -1
 -1  0  0 -1 -1 -1 -1 -1 -1 -1  0 -1 -1  0  0  0 -1  0 -1  0 -1 -1 -1 -1 -1
  0 -1 -1 -1 -1  0 -1 -1 -1  0 -1 -1 -1 -1 -1 -1 -1 -1 -1  0 -1 -1 -1 -1 -1
 -1 -1  0 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1  0 -1 -1 -1 -1 -1 -1 -1 -1]
9.6min_samples=20.png

可以看出,浅色数据点变多了,也就是噪声变多了,即聚类中被划为 1 的数据点变少了。

DBSCAN聚类算法总结

1.虽然 DBSCAN 聚类算法并不直接指定 clusters的数量,但是通过 min_samples 和 eps 参数,相当于间接的指定了 clusters的数量。尤其是 eps 参数尤为重要,因为它规定了某一簇的范围大小。
2.在实际应用中,如果将数据集先用 StandardScaler 或者 MinMaxScaler 进行处理,那么 DBSCAN 聚类算法的表现会更好。因为,这两种预处理方法把数据的范围控制的比较集中。

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

推荐阅读更多精彩内容