聚类分析:原型K-Means/K-Means++聚类、层次聚类;密度聚类DBSCAN
聚类分析–处理无标签数据
from IPython.display import Image
%matplotlib inline
1.使用K-Means方法按照相似度对对象进行分组
1.1使用sklearn实现K-Means聚类
from sklearn.datasets import make_blobsX, y = make_blobs(n_samples=150, n_features=2, centers=3, cluster_std=0.5, shuffle=True, random_state=0)
import matplotlib.pyplot as pltplt.scatter(X[:, 0], X[:, 1], c='white', marker='o', edgecolor='black', s=50)
plt.grid()
plt.tight_layout()
#plt.savefig('images/11_01.png', dpi=300)
plt.show()
from sklearn.cluster import KMeanskm = KMeans(n_clusters=3, init='random', n_init=10, max_iter=300,tol=1e-04,random_state=0)y_km = km.fit_predict(X)
1.2K-Means算法步骤总结
1.从样本中随机选择 K K K个质心作为初始簇的中心;
2.将每个样本分配给最近的质心 μ ( j ) \mu ^{(j)} μ(j),其中 j ∈ { 1 , 2 , 3 , ⋯ , K } j\in\{1,2,3,\cdots,K\} j∈{1,2,3,⋯,K};
3.在新形成的簇中重新计算质心;
4.重复步骤2和3,直到达到最大迭代次数或用户定义的容忍度或者簇不再发生变化就停止;
如何衡量对象之间的相似性?
这里将相似性定义为距离的反义词,且对于具有连续特征的示例进行聚类的常用距离是平方欧氏距离:
d ( x , y ) 2 = ∑ j = 1 m ( x j − y j ) 2 = ∥ x − y ∥ 2 2 d(\boldsymbol{x}, \boldsymbol{y})^{2}=\sum_{j=1}^{m}\left(x_{j}-y_{j}\right)^{2}=\|\boldsymbol{x}-\boldsymbol{y}\|_{2}^{2} d(x,y)2=j=1∑m(xj−yj)2=∥x−y∥22
基于上述欧氏距离,我们可以将K-Means算法描述为一个简单的优化问题,一种用于迭代求解实现最小化的方法是使用SSE:
S S E = ∑ i = 1 n ∑ j = 1 k w ( i , j ) ∥ x ( i ) − μ ( j ) ∥ 2 2 S S E=\sum_{i=1}^{n} \sum_{j=1}^{k} w^{(i, j)}\left\|\boldsymbol{x}^{(i)}-\boldsymbol{\mu}^{(j)}\right\|_{2}^{2} SSE=i=1∑nj=1∑kw(i,j)∥∥∥x(i)−μ(j)∥∥∥22
这里的 μ ( j ) \mu^{(j)} μ(j)代表的是簇 j j j的质心,其中 w ( i , j ) w^{(i,j)} w(i,j)定义如下:
w ( i , j ) = { 1 , if x ( i ) ∈ j 0 , otherwise w^{(i, j)}=\left\{\begin{array}{ll} 1, & \text { if } x^{(i)} \in j \\ 0, & \text { otherwise } \end{array}\right. w(i,j)={1,0, if x(i)∈j otherwise
如果在达到最大迭代次数之前,算法已经收敛了,则sklearn中的K-Means会提前停止。
然而,对于一些特定的情况,K-Means可能无法收敛,即便是选择了相对较大的迭代次数。
处理收敛问题的一种方法是,选择相对较大的tol参数值,该参数控制簇内部SSE中该表的容忍度以声明收敛。
K-Means算法的一个问题是一个或者多个簇可能是空的。但对于K-medoids或者模糊fuzzy C-Means中将不存在此问题。
Sklearn中,解决了上述问题。如果簇是空的,则算法会搜索距离空簇的质心最远的样本,然后它会将质心重新指定为最远的点。
当使用欧氏距离度量法的时候,希望确保在相同的尺度上度量特征尺度,在必要的时候使用z-score标准化或者线性函数归一化实现特征缩放。
plt.scatter(X[y_km == 0, 0],X[y_km == 0, 1],s=50, c='lightgreen',marker='s', edgecolor='black',label='Cluster 1')plt.scatter(X[y_km == 1, 0],X[y_km == 1, 1],s=50, c='orange',marker='o', edgecolor='black',label='Cluster 2')plt.scatter(X[y_km == 2, 0],X[y_km == 2, 1],s=50, c='lightblue',marker='v', edgecolor='black',label='Cluster 3')plt.scatter(km.cluster_centers_[:, 0],km.cluster_centers_[:, 1],s=250, marker='*',c='red', edgecolor='black',label='Centroids')plt.legend(scatterpoints=1)
plt.grid()
plt.tight_layout()
#plt.savefig('images/11_02.png', dpi=300)
plt.show()
上述方法需要提前指定簇的个数,当数据维度很高的时候,将非常困难。
2.使用K-Means++来更智能地选择初始聚类中心
经典的K-Means算法,使用随机种子来确定初始质心,如果质心选择不当,则可能会导致聚类效果不好或者收敛速度过慢。
解决此问题的一种方法是::在数据集上多次运行K-Means算法,并且根据SSE选择最佳性能的模型。
使用K-Means++算法:
通过将初始质心放置在远离彼此的位置,这将会比经典K-Means算法产生更好个更加一致的结果。
K-Means++算法步骤总结:
1.初始化一个空的集合 M M M,用于存储选出来的 K K K个初始聚类中心;
2.从输入样本中随机选择第一个聚类中心 μ ( j ) \mu^{(j)} μ(j),并将其指派到集合 M M M中;
3.对于每个样本 x ( i ) x^{(i)} x(i),(该样本不属于集合 M M M),求出其与集合 M M M中所有初始聚类中心的最小平方距离 d ( x ( i ) , M ) 2 d(x^{(i)}, M)^2 d(x(i),M)2;
4.为了随机选择下一个质心 μ ( p ) \mu^{(p)} μ(p),使用一个加权概率分布 d ( μ ( p ) , M ) 2 ∑ i d ( x ( i ) , M ) 2 \frac{d\left(\boldsymbol{\mu}^{(p)}, \mathbf{M}\right)^{2}}{\sum_{i} d\left(\boldsymbol{x}^{(i)}, \mathbf{M}\right)^{2}} ∑id(x(i),M)2d(μ(p),M)2;
5.重复上述步骤2,3,直到选出了 K K K个聚类中心;
6.继续使用经典的K-Means算法;
使用的方法是,在初始化对象的时候,将参数初始化微init='K-means++'
from sklearn.cluster import KMeanskm = KMeans(n_clusters=3, init='k-means++', n_init=10, max_iter=300,tol=1e-04,random_state=0)y_km = km.fit_predict(X)plt.scatter(X[y_km == 0, 0],X[y_km == 0, 1],s=50, c='lightgreen',marker='s', edgecolor='black',label='Cluster 1')plt.scatter(X[y_km == 1, 0],X[y_km == 1, 1],s=50, c='orange',marker='o', edgecolor='black',label='Cluster 2')plt.scatter(X[y_km == 2, 0],X[y_km == 2, 1],s=50, c='lightblue',marker='v', edgecolor='black',label='Cluster 3')plt.scatter(km.cluster_centers_[:, 0],km.cluster_centers_[:, 1],s=250, marker='*',c='red', edgecolor='black',label='Centroids')plt.legend(scatterpoints=1)
plt.grid()
plt.tight_layout()
#plt.savefig('images/11_02.png', dpi=300)
plt.show()
3.硬聚类和软聚类
硬聚类(Hard clustering):描述了一系列算法,其中数据集中的每一个样本都被分配给了一个簇,比如前面的K-Means算法和K-Means++算法。
软聚类或者模糊聚类(soft clustering或者fuzzy clustering):将样本分配给一个或者多个簇。
一种流行的软聚类算法为:fuzzy C-Means(FCM),也被称为soft K-Means or fuzzy K-Means.
FCM过程与K-Means非常相似,但是使用的是属于每个聚类的点的概率值来替代硬聚类分配。在K-Means算法中,使用二进制值的稀疏向量来表示样本 x x x的簇成员;
[ x ∈ μ ( 1 ) → w ( i , j ) = 0 x ∈ μ ( 2 ) → w ( i , j ) = 1 x ∈ μ ( 3 ) → w ( i , j ) = 0 ] \left[\begin{array}{ll} x \in \mu^{(1)} & \rightarrow w^{(i, j)}=0 \\ x \in \mu^{(2)} & \rightarrow w^{(i, j)}=1 \\ x \in \mu^{(3)} & \rightarrow w^{(i, j)}=0 \end{array}\right] ⎣⎡x∈μ(1)x∈μ(2)x∈μ(3)→w(i,j)=0→w(i,j)=1→w(i,j)=0⎦⎤
这里的值为1的索引位置表示簇的质心。
与上述不同,FCM算法描述如下:
[ x ∈ μ ( 1 ) → w ( i , j ) = 0.1 x ∈ μ ( 2 ) → w ( i , j ) = 0.85 x ∈ μ ( 3 ) → w ( i , j ) = 0.05 ] \left[\begin{array}{lll} x \in \mu^{(1)} & \rightarrow w^{(i, j)}=0.1 \\ x \in \mu^{(2)} & \rightarrow w^{(i, j)}=0.85 \\ x \in \mu^{(3)} & \rightarrow w^{(i, j)}=0.05 \end{array}\right] ⎣⎡x∈μ(1)x∈μ(2)x∈μ(3)→w(i,j)=0.1→w(i,j)=0.85→w(i,j)=0.05⎦⎤
这里的每个值都在 [ 0 , 1 ] [0,1] [0,1]之间,分别代表每个样本输入某簇成员的概率值。
FCM算法步骤如下:
1.指定簇的数量 K K K,并随机分配每个簇所包含的成员;
2.计算聚类中心 μ ( j ) \mu^{(j)} μ(j),其中 j ∈ { 1 , ⋯ , K } j\in\{1,\cdots,K\} j∈{1,⋯,K};
3.为每个质心更新其所包含的簇成员;
4.重复步骤2,3,直到隶属系数不再改变或者达到用户定义的公差,或者达到最大迭代次数;
FCM算法的目标函数:
J m = ∑ i = 1 n ∑ j = 1 k w ( i , j ) m ∥ x ( i ) − μ ( j ) ∥ 2 2 J_{m}=\sum_{i=1}^{n} \sum_{j=1}^{k} w^{(i, j)^{m}}\left\|\boldsymbol{x}^{(i)}-\boldsymbol{\mu}^{(j)}\right\|_{2}^{2} Jm=i=1∑nj=1∑kw(i,j)m∥∥∥x(i)−μ(j)∥∥∥22
注意:这里的 w ( i , j ) w^{(i,j)} w(i,j)不再是二进制值,而代表的是概率。这里的指数 m m m:任何大于或者等于1(通常设置m=2),其代表的是模糊系数,或者称为模糊器,用于控制模糊度。
这里的 m m m越大,则 w ( i , j ) w^{(i,j)} w(i,j)变得越小,意味着簇成员资格越小,就会导致更加模糊的簇。
w ( i , j ) = [ ∑ c = 1 k ( ∥ x ( i ) − μ ( j ) ∥ 2 ∥ x ( i ) − μ ( c ) ∥ 2 ) 2 m − 1 ] − 1 w^{(i, j)}=\left[\sum_{c=1}^{k}\left(\frac{\left\|x^{(i)}-\mu^{(j)}\right\|_{2}}{\left\|x^{(i)}-\mu^{(c)}\right\|_{2}}\right)^{\frac{2}{m-1}}\right]^{-1} w(i,j)=⎣⎡c=1∑k(∥∥x(i)−μ(c)∥∥2∥∥x(i)−μ(j)∥∥2)m−12⎦⎤−1
示例,如果选择了三个簇,则:
w ( i , j ) = [ ( ∥ x ( i ) − μ ( j ) ∥ 2 ∥ x ( i ) − μ ( 1 ) ∥ 2 ) 2 m − 1 + ( ∥ x ( i ) − μ ( j ) ∥ 2 ∥ x ( i ) − μ ( 2 ) ∥ 2 ) 2 m − 1 + ( ∥ x ( i ) − μ ( j ) ∥ 2 ∥ x ( i ) − μ ( 3 ) ∥ 2 ) 2 m − 1 ] − 1 w^{(i, j)}=\left[\left(\frac{\left\|\boldsymbol{x}^{(i)}-\boldsymbol{\mu}^{(j)}\right\|_{2}}{\left\|\boldsymbol{x}^{(i)}-\boldsymbol{\mu}^{(1)}\right\|_{2}}\right)^{\frac{2}{m-1}}+\left(\frac{\left\|\boldsymbol{x}^{(i)}-\boldsymbol{\mu}^{(j)}\right\|_{2}}{\left\|\boldsymbol{x}^{(i)}-\boldsymbol{\mu}^{(2)}\right\|_{2}}\right)^{\frac{2}{m-1}}+\left(\frac{\left\|\boldsymbol{x}^{(i)}-\boldsymbol{\mu}^{(j)}\right\|_{2}}{\left\|\boldsymbol{x}^{(i)}-\boldsymbol{\mu}^{(3)}\right\|_{2}}\right)^{\frac{2}{m-1}}\right]^{-1} w(i,j)=⎣⎡(∥∥x(i)−μ(1)∥∥2∥∥x(i)−μ(j)∥∥2)m−12+(∥∥x(i)−μ(2)∥∥2∥∥x(i)−μ(j)∥∥2)m−12+(∥∥x(i)−μ(3)∥∥2∥∥x(i)−μ(j)∥∥2)m−12⎦⎤−1
这里的 μ ( j ) \mu^{(j)} μ(j)计算如下:
μ ( j ) = ∑ i = 1 n w ( i , j ) m x ( i ) ∑ i = 1 n w ( i , j ) m \boldsymbol{\mu}^{(j)}=\frac{\sum_{i=1}^{n} w^{(i, j)^{m}} \boldsymbol{x}^{(i)}}{\sum_{i=1}^{n} w^{(i, j)^{m}}} μ(j)=∑i=1nw(i,j)m∑i=1nw(i,j)mx(i)
4.使用手肘法求出最优簇数
使用sklearn不需要显示地计算簇内的SSE,其可以通过inertia属性进行访问:
print('Distortion: %.2f' % km.inertia_)
Distortion: 72.48
手肘法,基于簇内部的SSE。
distortions = []
for i in range(1, 11):km = KMeans(n_clusters=i, init='k-means++', n_init=10, max_iter=300, random_state=0)km.fit(X)distortions.append(km.inertia_)
plt.plot(range(1, 11), distortions, marker='o')
plt.xlabel('Number of clusters')
plt.ylabel('Distortion')
plt.tight_layout()
#plt.savefig('images/11_03.png', dpi=300)
plt.show()
从上图可以看出,elbow位于当K=3的时候,该值对当前数据集来讲,是很好的选择。
5.使用轮廓图量化聚类质量
步骤如下:
1.计算簇的内聚力 α ( i ) \alpha{(i)} α(i),作为一个样本和同一个簇中所有其它点之间的平均距离;
2.计算簇的散度 b ( i ) b^{(i)} b(i),作为从下一个最近的簇和簇中所有其它点之间的平均距离;
3.计算轮廓 s ( i ) s^{(i)} s(i),用于反映簇内聚和簇散度差异的大小程度,定义如下:
s ( i ) = b ( i ) − a ( i ) max { b ( i ) , a ( i ) } s^{(i)}=\frac{b^{(i)}-a^{(i)}}{\max \left\{b^{(i)}, a^{(i)}\right\}} s(i)=max{b(i),a(i)}b(i)−a(i)
轮廓系数在正负一之间,从上式可知,当聚类散度和内聚力相同的时候,轮廓系数为零。
若, b ( i ) ≫ a ( i ) b^{(i)} \gg a^{(i)} b(i)≫a(i),将得到接近于1的理想轮廓系数,因为 b ( i ) b^{(i)} b(i)量化了一个示例与其他簇的不同程度。 a ( i ) a^{(i)} a(i)反映了当前样本与其内部簇中的其他样本的相似程度。
import numpy as np
from matplotlib import cm
from sklearn.metrics import silhouette_sampleskm = KMeans(n_clusters=3, init='k-means++', n_init=10, max_iter=300,tol=1e-04,random_state=0)y_km = km.fit_predict(X)cluster_labels = np.unique(y_km)
n_clusters = cluster_labels.shape[0]
silhouette_vals = silhouette_samples(X, y_km, metric='euclidean')
y_ax_lower, y_ax_upper = 0, 0
yticks = []for i, c in enumerate(cluster_labels):c_silhouette_vals = silhouette_vals[y_km == c]c_silhouette_vals.sort()y_ax_upper += len(c_silhouette_vals)color = cm.jet(float(i) / n_clusters)plt.barh(range(y_ax_lower, y_ax_upper), c_silhouette_vals, height=1.0, edgecolor='none', color=color)yticks.append((y_ax_lower + y_ax_upper) / 2.)y_ax_lower += len(c_silhouette_vals)silhouette_avg = np.mean(silhouette_vals)
plt.axvline(silhouette_avg, color="red", linestyle="--") plt.yticks(yticks, cluster_labels + 1)
plt.ylabel('Cluster')
plt.xlabel('Silhouette coefficient')plt.tight_layout()
#plt.savefig('images/11_04.png', dpi=300)
plt.show()
图中虚线为平均轮廓系数。
将上述聚类结果与一个相对较差的聚类相对比。
km = KMeans(n_clusters=2,init='k-means++',n_init=10,max_iter=300,tol=1e-04,random_state=0)
y_km = km.fit_predict(X)plt.scatter(X[y_km == 0, 0],X[y_km == 0, 1],s=50,c='lightgreen',edgecolor='black',marker='s',label='Cluster 1')
plt.scatter(X[y_km == 1, 0],X[y_km == 1, 1],s=50,c='orange',edgecolor='black',marker='o',label='Cluster 2')plt.scatter(km.cluster_centers_[:, 0], km.cluster_centers_[:, 1],s=250, marker='*', c='red', label='Centroids')
plt.legend()
plt.grid()
plt.tight_layout()
#plt.savefig('images/11_05.png', dpi=300)
plt.show()
cluster_labels = np.unique(y_km)
n_clusters = cluster_labels.shape[0]
silhouette_vals = silhouette_samples(X, y_km, metric='euclidean')
y_ax_lower, y_ax_upper = 0, 0
yticks = []
for i, c in enumerate(cluster_labels):c_silhouette_vals = silhouette_vals[y_km == c]c_silhouette_vals.sort()y_ax_upper += len(c_silhouette_vals)color = cm.jet(float(i) / n_clusters)plt.barh(range(y_ax_lower, y_ax_upper), c_silhouette_vals, height=1.0, edgecolor='none', color=color)yticks.append((y_ax_lower + y_ax_upper) / 2.)y_ax_lower += len(c_silhouette_vals)silhouette_avg = np.mean(silhouette_vals)
plt.axvline(silhouette_avg, color="red", linestyle="--") plt.yticks(yticks, cluster_labels + 1)
plt.ylabel('Cluster')
plt.xlabel('Silhouette coefficient')plt.tight_layout()
#plt.savefig('images/11_06.png', dpi=300)
plt.show()
可以看出,轮廓图现在具有折明显不同的长度和宽度,充分表明这是一个相对较差的聚类结果。
6.将簇组织为层次树
层次聚类是另一种基于原型的聚类方法,
层次聚类的一个优点:允许绘制树状图,即二进制分层聚类的可视化。而且无需预先指定簇的数量。
层次聚类的两种主要方法:凝聚型和分裂型
在分裂的分层聚类中,从一个包含完整数据集的簇开始,迭代地将簇划分为更小的簇,直到每个簇中仅包含一个样本实例。
在凝聚型聚类中,将每个样本实例作为单个簇开始,并合并最近的簇对,直至剩下一个簇。
6.1以自底向上的方式对簇进行分组
凝聚层次聚类的两种标准算法是单链接算法和完全链接算法。
利用单链接算法::计算每一对聚类中最相似成员之间的距离,并将具有最相似成员之间的距离最小的两个聚类合并。
完全链接算法::不是比较每一对簇中最相似的成员,而是比较最不相似的成员来执行合并。
完全链接算法几何表示如下:
Image(filename='./images/11_07.png', width=400)
其他类型的链接:
包括平均链接、Ward’s链接。
在平均链接中,根据两个聚类中所有成员之间的最小平均距离来合并簇对儿。
在Ward’s链接中,导致簇内SSE总量增幅最小的两个簇将被合并。
完全链接的凝聚型层次聚类:
1.计算所有样本的距离矩阵;
2.将每个数据点单独表示为一个簇;
3.基于最不相近(遥远)成员之间的距离合并两个最近的簇;
4.更新相似性矩阵;
5.重复上述2,3, 4,步骤,直到形成唯一的一个簇;
# 首先生成一个随机数据样本
# 行代表不同的观测值(id 0-4),列代表不同的特征import pandas as pd
import numpy as npnp.random.seed(123)variables = ['X', 'Y', 'Z']
labels = ['ID_0', 'ID_1', 'ID_2', 'ID_3', 'ID_4']X = np.random.random_sample([5, 3])*10
df = pd.DataFrame(X, columns=variables, index=labels)
df
X | Y | Z | |
---|---|---|---|
ID_0 | 6.964692 | 2.861393 | 2.268515 |
ID_1 | 5.513148 | 7.194690 | 4.231065 |
ID_2 | 9.807642 | 6.848297 | 4.809319 |
ID_3 | 3.921175 | 3.431780 | 7.290497 |
ID_4 | 4.385722 | 0.596779 | 3.980443 |
6.2在距离矩阵上执行层次聚类
# 为了计算距离矩阵,作为层次聚类的输入,这里使用Scipy的pdist函数。from scipy.spatial.distance import pdist, squareformrow_dist = pd.DataFrame(squareform(pdist(df, metric='euclidean')),columns=labels,index=labels)
row_dist
ID_0 | ID_1 | ID_2 | ID_3 | ID_4 | |
---|---|---|---|---|---|
ID_0 | 0.000000 | 4.973534 | 5.516653 | 5.899885 | 3.835396 |
ID_1 | 4.973534 | 0.000000 | 4.347073 | 5.104311 | 6.698233 |
ID_2 | 5.516653 | 4.347073 | 0.000000 | 7.244262 | 8.316594 |
ID_3 | 5.899885 | 5.104311 | 7.244262 | 0.000000 | 4.382864 |
ID_4 | 3.835396 | 6.698233 | 8.316594 | 4.382864 | 0.000000 |
# 1. 不正确的方法: Squareform distance matrixfrom scipy.cluster.hierarchy import linkagerow_clusters = linkage(row_dist, method='complete', metric='euclidean')pd.DataFrame(row_clusters,columns=['row label 1', 'row label 2','distance', 'no. of items in clust.'],index=['cluster %d' % (i + 1)for i in range(row_clusters.shape[0])])
D:\installation\anaconda3\lib\site-packages\ipykernel_launcher.py:5: ClusterWarning: scipy.cluster: The symmetric non-negative hollow observation matrix looks suspiciously like an uncondensed distance matrix"""
row label 1 | row label 2 | distance | no. of items in clust. | |
---|---|---|---|---|
cluster 1 | 0.0 | 4.0 | 6.521973 | 2.0 |
cluster 2 | 1.0 | 2.0 | 6.729603 | 2.0 |
cluster 3 | 3.0 | 5.0 | 8.539247 | 3.0 |
cluster 4 | 6.0 | 7.0 | 12.444824 | 5.0 |
# 2. 正确的方法: Condensed distance matrixrow_clusters = linkage(pdist(df, metric='euclidean'), method='complete')pd.DataFrame(row_clusters,columns=['row label 1', 'row label 2','distance', 'no. of items in clust.'],index=['cluster %d' % (i + 1) for i in range(row_clusters.shape[0])])
row label 1 | row label 2 | distance | no. of items in clust. | |
---|---|---|---|---|
cluster 1 | 0.0 | 4.0 | 3.835396 | 2.0 |
cluster 2 | 1.0 | 2.0 | 4.347073 | 2.0 |
cluster 3 | 3.0 | 5.0 | 5.899885 | 3.0 |
cluster 4 | 6.0 | 7.0 | 8.316594 | 5.0 |
# 3. correct approach: Input matrixrow_clusters = linkage(df.values, method='complete', metric='euclidean')
pd.DataFrame(row_clusters,columns=['row label 1', 'row label 2','distance', 'no. of items in clust.'],index=['cluster %d' % (i + 1)for i in range(row_clusters.shape[0])])
row label 1 | row label 2 | distance | no. of items in clust. | |
---|---|---|---|---|
cluster 1 | 0.0 | 4.0 | 3.835396 | 2.0 |
cluster 2 | 1.0 | 2.0 | 4.347073 | 2.0 |
cluster 3 | 3.0 | 5.0 | 5.899885 | 3.0 |
cluster 4 | 6.0 | 7.0 | 8.316594 | 5.0 |
链接矩阵由几行组成,每一行表示一次合并。第一列和第二列表示每个集群中最不相似的成员,第三列报告这些成员之间的距离。最后一列返回每个簇中的成员计数。
from scipy.cluster.hierarchy import dendrogram# make dendrogram black (part 1/2)
# from scipy.cluster.hierarchy import set_link_color_palette
# set_link_color_palette(['black'])row_dendr = dendrogram(row_clusters, labels=labels,# make dendrogram black (part 2/2)# color_threshold=np.inf)
plt.tight_layout()
plt.ylabel('Euclidean distance')
#plt.savefig('images/11_11.png', dpi=300,
# bbox_inches='tight')
plt.show()
# 上述图概括了基于欧式距离度量的最相似的例子,ID_0和ID_4,然后是ID_1和ID_2.
6.3将树状图连接到热力图上
# plot row dendrogram
fig = plt.figure(figsize=(8, 8), facecolor='white')
axd = fig.add_axes([0.09, 0.1, 0.2, 0.6])# note: for matplotlib < v1.5.1, please use orientation='right'
row_dendr = dendrogram(row_clusters, orientation='left')# reorder data with respect to clustering
df_rowclust = df.iloc[row_dendr['leaves'][::-1]]axd.set_xticks([])
axd.set_yticks([])# remove axes spines from dendrogram
for i in axd.spines.values():i.set_visible(False)# plot heatmap
axm = fig.add_axes([0.23, 0.1, 0.6, 0.6]) # x-pos, y-pos, width, height
cax = axm.matshow(df_rowclust, interpolation='nearest', cmap='hot_r')
fig.colorbar(cax)
axm.set_xticklabels([''] + list(df_rowclust.columns))
axm.set_yticklabels([''] + list(df_rowclust.index))#plt.savefig('images/11_12.png', dpi=300)
plt.show()
6.4通过sklearn应用凝聚聚类
from sklearn.cluster import AgglomerativeClusteringac = AgglomerativeClustering(n_clusters=3, affinity='euclidean', linkage='complete')
labels = ac.fit_predict(X)
print('Cluster labels: %s' % labels)
Cluster labels: [1 0 0 2 1]
这里允许我们指定希望返回的簇的数量,对于修建分层的分层簇树,很有用。通过将n_cluster参数设置为3,可以将使用相同的基于欧氏距离的完全链接方法将输入实例分为三组。
从结果中可以看出,第一个和第五个样本被划分到了同一个簇,标签都为1.ID_1和ID_2被划分到另一个簇,标签为0.ID_3的样本被放入子集的簇,标签为2.
# 设置簇的个数为2,用于对比
ac = AgglomerativeClustering(n_clusters=2, affinity='euclidean', linkage='complete')
labels = ac.fit_predict(X)
print('Cluster labels: %s' % labels)
Cluster labels: [0 1 1 0 0]
7.通过DBSCAN定位高密度区域
基于密度的DBSCAN聚类,不会假设像K-Means这样的球状聚类,也不会将数据划分为需要手动截断点的层次结构。
基于密度的聚类基于点的密集区域分配聚类标签。但DBSCAN中,密度的概念定义为指定半径内点的数量。
准则:
1.如果在指定的半径内至少有指定数量的相邻点,则将该点视为一个核心点;
2.边界点定义为:若一个比1中半径内有着更少的点,但该点依然位于1中的半径内的点;
3.其他所有既不是核心点,也不是边界点的余下点,都被视为噪声;
Image(filename='images/11_13.png', width=500)
使用DBSCAN的一个主要优点是,不需要像K-Means那样假定簇具有球形特征。
DBSCAN与K-Means以及分层聚类的不同之处在于,不一定将每个点分配给一个簇,但其能够去除噪声点。
# 构建半月形数据集
from sklearn.datasets import make_moonsX, y = make_moons(n_samples=200, noise=0.05, random_state=0)
plt.scatter(X[:, 0], X[:, 1])
plt.tight_layout()
#plt.savefig('images/11_14.png', dpi=300)
plt.show()
首先使用K-Means算法和完全链接聚类,看其是否可以有效识别出半月形作为单独的聚类。
f, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 3))km = KMeans(n_clusters=2, random_state=0)
y_km = km.fit_predict(X)
ax1.scatter(X[y_km == 0, 0], X[y_km == 0, 1],edgecolor='black',c='lightblue', marker='o', s=40, label='cluster 1')
ax1.scatter(X[y_km == 1, 0], X[y_km == 1, 1],edgecolor='black',c='red', marker='s', s=40, label='cluster 2')
ax1.set_title('K-means clustering')ac = AgglomerativeClustering(n_clusters=2,affinity='euclidean',linkage='complete')
y_ac = ac.fit_predict(X)
ax2.scatter(X[y_ac == 0, 0], X[y_ac == 0, 1], c='lightblue',edgecolor='black',marker='o', s=40, label='Cluster 1')
ax2.scatter(X[y_ac == 1, 0], X[y_ac == 1, 1], c='red',edgecolor='black',marker='s', s=40, label='Cluster 2')
ax2.set_title('Agglomerative clustering')plt.legend()
plt.tight_layout()
#plt.savefig('images/11_15.png', dpi=300)
plt.show()
使用密度聚类:
from sklearn.cluster import DBSCANdb = DBSCAN(eps=0.2, min_samples=5, metric='euclidean')
y_db = db.fit_predict(X)
plt.scatter(X[y_db == 0, 0], X[y_db == 0, 1],c='lightblue', marker='o', s=40,edgecolor='black', label='Cluster 1')
plt.scatter(X[y_db == 1, 0], X[y_db == 1, 1],c='red', marker='s', s=40,edgecolor='black', label='Cluster 2')
plt.legend()
plt.tight_layout()
#plt.savefig('images/11_16.png', dpi=300)
plt.show()
聚类分析:原型K-Means/K-Means++聚类、层次聚类;密度聚类DBSCAN相关推荐
- 【机器学习】聚类【Ⅴ】密度聚类与层次聚类
主要来自周志华<机器学习>一书,数学推导主要来自简书博主"形式运算"的原创博客,包含自己的理解. 有任何的书写错误.排版错误.概念错误等,希望大家包含指正. 由于字数限 ...
- Python基于聚类算法实现密度聚类(DBSCAN)计算
本文实例讲述了Python基于聚类算法实现密度聚类(DBSCAN)计算.分享给大家供大家参考,具体如下: 算法思想 基于密度的聚类算法从样本密度的角度考察样本之间的可连接性,并基于可连接样本不断扩展聚 ...
- dbscan聚类算法matlab_密度聚类DBSCAN、HDBSCAN(转)
# 密度聚类DBSCAN.HDBSCAN DBSCAN DBSCAN(Density-Based Spatial Clustering of Applications with Noise,具有噪声 ...
- R语言聚类算法之密度聚类(Density-based Methods)
1.原理解析: 1.从数据集中选择一个未处理的样本点 2.以1为圆心,做半径为E的圆,由于圆内圈入点的个数为3,满足密度阈值Minpts,因此称点1为核心对象(黑色实心圆点),且将圈内的4个点形成一个 ...
- dbscan和谱聚类_R 无监督聚类算法(1)K-means和层次聚类
首先我们要解决几个问题 聚类算法主要包括哪些算法? 主要包括:K-means.DBSCAN.Density Peaks聚类(局部密度聚类).层次聚类.谱聚类. 什么是无监督学习? • 无监督学习也是相 ...
- 【R】【密度聚类、层次聚类、期望最大化聚类】
文章目录 1.对数据集进行加载.预处理集可视化 1.1 加载数据集 1.2 数据预处理 1.3 将样本点进行可视化 2.密度聚类(DBSCAN 算法) 2.1 加载程序包 2.2 设置聚类参数阈值并可 ...
- k-means聚类,密度聚类,层次聚类优缺点
k-means: 优点: 1,简单,易于理解和实现: 2,时间复杂度低 缺点: 1,需要对均值给出定义, 2,需要指定要聚类的数目: 3,一些过大的异常值会带来很大影响: 4,算法对初始选值敏感: 5 ...
- 【聚类学习】时间序列聚类—10年回顾概括性综述
目录 一.引言 二.时间序列聚类的作用 三.时间序列数据的聚类问题正式定义 四.时序数据的聚类的挑战 五.时间序列数据聚类有什么用 六.时间序列聚类技术的分类 七.时间序列聚类的四步骤: 1.时间序列 ...
- 密度聚类之DBSCAN算法原理
DBSCAN(Density-Based Spatial Clustering of Applications with Noise,具有噪声的基于密度的聚类方法)是一种很典型的密度聚类算法,和K-M ...
- 机器学习实战——密度聚类算法
机器学习实战--密度聚类算法 1 密度聚类 2 sklearn中的实现 1 密度聚类 密度聚类假设聚类结构能够通过样本分布的密集程度确定,通常情形下,密度聚类算法从样本密度的角度来考察样本之间的可连接 ...
最新文章
- win10安装jdk1.8
- Javascript 面向对象编程
- HDU 3966 Aragorn's Story (树链点权剖分,成段修改单点查询)
- 【Pytorch神经网络实战案例】14 构建条件变分自编码神经网络模型生成可控Fashon-MNST模拟数据
- 【RippleNet】(一)preprocessor.py【未完】
- Docker 安装zookeeper
- jQuery:ajax调用成功后返回数据
- C++与STL简单介绍( C/C++机试)
- html 表格转换为dbf,DBF Excel 文件相互转换-完美教程资讯
- ListView列表项View复用--ViewHolder模式
- indows蓝屏PROCESS1_INITIALIZATION_FAILED STOP:0x0000006B 解决方法
- Java练习题2-基础(含解析)
- iPhone iPad下载NBA2K22苹果版下载
- 小米手机与计算机如何连接网络连接,小米手机连接不上电脑怎么办 图文教你小米手机怎么连接电脑...
- 微信企业红包php,微信公众号发红包和企业付款实现方法
- Python大作业-爬取成都链家租房信息(大作业)源码
- 移动硬盘损坏怎么恢复?看完再也不怕丢失数据
- 【Godot】通过属性检查器显示对应节点的脚本属性
- 分组急救技能竞赛方法在急诊专科护士培训中的运用
- 解决Win10频繁禁用IME的问题