聚类算法
前言
- 与回归与分类不同,聚类是无监督学习算法,无监督指的是只需要数据,不需要标记结果,自己给自己分类。
- 在现实生活中,很少直接用聚类算法,因为聚类效果的好坏不容易衡量(因为没有标记,就没有标准答案),有时候会用做监督学习中稀疏特征的预处理,把混乱的数据先分分看,看看大类如何。
1.算法思想
聚类算法,顾名思义是将数据聚集起来的算法,所谓“物以类聚,人以群分”的道理。聚类算法的主要思想就是以一定的标准将所有数据分成若干类,是一个无监督学习方法。在周志华老师的西瓜书中描述为“将数据集中的样本划分为若干个通常是不想交的子集,每个子集称为一个簇”。而所谓的标准,实则为各种的距离。在本博客中,主要讲述三个聚类方法,分别是K-means聚类,层次聚类(AgglomerativeClustering),
密度聚类(DBSCAN)。
聚类算法以数据集中的距离作为分类的标准,最常用到的距离有:
欧式距离
d
(
x
,
z
)
=
∣
∣
x
−
z
∣
∣
=
∑
i
=
1
N
(
x
i
−
z
i
)
2
d(x,z)=||x-z||=\sqrt{\sum_{i=1}^{N}(x_i-z_i)^2}
d(x,z)=∣∣x−z∣∣=i=1∑N(xi−zi)2
曼哈顿距离
d
(
x
,
z
)
=
∑
i
=
1
N
∣
x
i
−
z
i
∣
d(x,z)=\sum_{i=1}^{N}|x_i-z_i|
d(x,z)=i=1∑N∣xi−zi∣
2.K-means聚类
K-means算法是很典型的基于距离的聚类算法。它是通过将样本划分为k个方差齐次的类来实现数据聚类。该算法需要指定划分的类的个数,即在最小化误差函数的基础上将数据划分为预定的类数K,采用距离作为相似性的评价指标,即认为两个对象的距离越近,其相似度就越大。该算法认为簇是由距离靠近的对象组成的,因此把得到紧凑且独立的簇作为最终目标。
2.1 算法步骤:
- 1) 选取数据空间中的K个对象作为初始中心,每个对象代表一个聚类中心;
- 2) 在n次迭代中,对于样本中的数据对象,根据它们与这些聚类中心的欧氏距离,按距离最近的准则将它们分到距离它们最近的聚类中心(最相似)所对应的类;
- 3) 更新聚类中心:将每个类别中所有对象所对应的均值作为该类别的聚类中心,计算目标函数的值;
- 4) 判断聚类中心和目标函数的值是否发生改变,若不变,则终止迭代并输出结果,若改变,则返回步骤2)再进行计算。
2.2 算法特征
特点:
- 对于k值选取要求比较高,并且需要进行试探性去取值
- 在处理类间方差差异大的样本时,有着很好的效果。
- 处理类规模较大的效果很好
缺点:
- 在簇的平均值被定义的情况下才能使用,这对于处理符号属性的数据不适用。
- 必须事先给出k(要生成的簇的数目),而且对初值敏感,对于不同的初始值,可能会导致不同结果。
- 它对于“躁声”和孤立点数据是敏感的,少量的该类数据能够对平均值产生极大的影响。
总结:
K-means算法不适合处理比较离散的数据.同时对于k值得选取至关重要,换句话说,我们对k值得选取比较被动.在k值得选取方面可能需要多做尝试,最后指定相应的关于k值得散点图
python实现主要参数(Sklearn)
参数 | 值 | 详细 |
---|---|---|
n_clusters | int,optional,默认值:8 | 要形成的簇数以及要生成的质心数。 |
init | ‘k-means ++’,'random’或ndarray | 初始化方法,默认为’k-means ++’:‘k-means ++’:以智能方式选择初始聚类中心进行k均值聚类,以加速收敛。有关更多详细信息,请参阅k_init中的注释部分。‘random’:从初始质心的数据中随机选择k个观测值(行)。如果传递了ndarray,它应该是形状(n_clusters,n_features)并给出初始中心。 |
n_init | int,默认值:10 | 使用不同质心种子运行k-means算法的时间。在惯性方面,最终结果将是n_init连续运行的最佳输出。 |
max_iter | int,默认值:300 | 单次运行的k-means算法的最大迭代次数。 |
3.层次聚类(AgglomerativeClustering)
层次聚类(Hierarchical Clustering)是聚类算法的一种,通过计算不同类别数据点间的相似度来创建一棵有层次的嵌套聚类树。在聚类树中,不同类别的原始数据点是树的最低层,树的顶层是一个聚类的根节点。
3.1 算法步骤
- 1.把数据集中的每个数据看作一个簇。
- 2.每次找到距离相近的两个簇合并为一个。
- 3.直到合并数量达到参数K。
3.2 算法特征
特点:
- 层次聚类算法对于k值选取要求也比较高,并且也需要进行试探性去取值
- 对较为离散的数据,分类效果比Kmeans好
缺点:
- 计算复杂度高,不适合数据量大的数据集;
总结:
层次聚类与KMeans比较类似,k值对结果的影响都很明显,同时对于簇的数据量也有一定的要求.但是聚类效果比KMEANS比较有优势.特别是对于离散数据的聚类效果,对于数据量方面也略优于KMEANS。但是层次聚类的时间复杂度较高.总而言之,层次聚类在聚类效果方面较优于KMEANS,虽然系统聚类效果比K-Means好,但是系统聚类需要样本距离的定义以及类间距离的定义,也就是离差平方和,然后进行计算距离,需要的时间复杂度很高,因此在处理大数据,系统聚类并不适合。
python实现主要参数(Sklearn)
参数 | 值 | 详细 |
---|---|---|
n_clusters | int或None,可选(默认= 2) | 要查找的集群数。必须None如果 distance_threshold不是None。 |
affinity | string或callable,默认值:“euclidean” | 用于计算链接的度量标准。可以是“euclidean”,“l1”,“l2”,“manhattan”,“cosine”或“precomputed”。如果联系是“病房”,则只接受“欧几里德”。如果“预先计算”,则需要距离矩阵(而不是相似度矩阵)作为拟合方法的输入。 |
memory | 具有joblib.Memory接口的None,str或object,可选 | 用于缓存树计算的输出。默认情况下,不进行缓存。如果给出了字符串,则它是缓存目录的路径。 |
代码实现
import matplotlib.pyplot as plt
from sklearn.datasets import make_moons #半月数据集
from sklearn.cluster import KMeans,AgglomerativeClustering,DBSCAN
plt.figure(figsize=(12,12))
#创建半月数据集,x为样本,y为标签
X,y = make_moons(n_samples=300,noise=0.05,random_state=0)
plt.subplot(221) #画图所在位置
plt.scatter(X[:,0],X[:,1])
plt.title('moon')
#KMeans模型
plt.subplot(222)
km = KMeans(n_clusters=2,random_state=0)
y_km = km.fit_predict(X)
plt.scatter(X[y_km==0,0],X[y_km==0,1],c='blue',marker='+',label='0')
plt.scatter(X[y_km==1,0],X[y_km==1,1],c='red',marker='*',label='1')
plt.title('K-means clustering')
#层次聚类凝聚模型
plt.subplot(223)
ac=AgglomerativeClustering(n_clusters=2,affinity='euclidean',linkage='complete')#全连接,欧式距离计算联合矩阵
y_ac= ac.fit_predict(X)
plt.scatter(X[y_ac==0,0],X[y_ac==0,1],c='blue',marker='+',label='0')
plt.scatter(X[y_ac==1,0],X[y_ac==1,1],c='red',marker='*',label='1')
plt.title('Agglomerative clustering')
#密度聚类DBSCAN,成功对半月形数据进行分类
plt.subplot(224)
db =DBSCAN(eps=0.2,min_samples=5,metric='euclidean')#欧式距离,样本点数量5,半径0.2
y_db = db.fit_predict(X)
plt.scatter(X[y_db==0,0],X[y_db==0,1],c='lightblue',marker='+',label='0')
plt.scatter(X[y_db==1,0],X[y_db==1,1],c='red',marker='*',label='1')
plt.title('DBSCAN clustering')
plt.show()
程序结果