分类是算法基于已有标签的数据进行学习并对新数据进行分类,而聚类则是在完全没有标签的情况下,有算法“猜测”哪些数据像是应该“堆”在一起的,并且让算法给不同的“堆”里的数据贴上一个数字标签。
一、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_))
生成的数据集为:
经过KMEANS 聚类的结果为:
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()
执行结果如图:
从图中可以看到,凝聚聚类算法是自下而上,不断的合并相似的聚类中心,以便让类别越来越少,同时,每个聚类中心的距离也就 越来越远,这种逐渐生成聚类的方法称为 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()
执行结果为:
聚类标签为:
[-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]
可以看出,所有的点都变成了浅色,并不代表所有的点都是噪声,而是所有的点都被划归到一个类中了,因为增加了 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]
可以看出,浅色数据点变多了,也就是噪声变多了,即聚类中被划为 1 的数据点变少了。
DBSCAN聚类算法总结
1.虽然 DBSCAN 聚类算法并不直接指定 clusters的数量,但是通过 min_samples 和 eps 参数,相当于间接的指定了 clusters的数量。尤其是 eps 参数尤为重要,因为它规定了某一簇的范围大小。
2.在实际应用中,如果将数据集先用 StandardScaler 或者 MinMaxScaler 进行处理,那么 DBSCAN 聚类算法的表现会更好。因为,这两种预处理方法把数据的范围控制的比较集中。