今天来聊聊聚类分析中最基础的一个算法:Kmeans。
Kmeans思想及算法流程:
首先Kmeans是一种无监督的聚类算法。对于给定的样本集,按照样本之间的距离大小,将样本划分为K个簇,让簇内的点尽量紧密的连接在一起,而让簇间的距离尽量的大。
算法流程:
1、给各个簇中心以适当的初值。
2、更新样本x1,x2,...,xn对应的簇标签y1,y2,...,yn。
argmin是使目标函数取最小值时的变量值
3、更新各个簇中心。
上式中, ny为属于簇y的样本总数。
4、直到簇标签达到收敛精度为止,否则重复2,3步的计算。
K值的确定:
在实际的应用中,主要两种方法进行K值的确定:
1、经验法:在实际的工作中,可以结合业务的场景和需求,来决定分几类以确定K值。
2、肘部法则:在使用聚类算法时,如果没有指定聚类的数量,即K值,则可以通过肘部法则来进行对K值得确定。肘部法则是通过成本函数来刻画的,其是通过将不同K值得成本函数刻画出来,随着K值的增大,平均畸变程度会不断减小且每个类包含的样本数会减少,于是样本离其重心会更近。但是,随着值继续增大,平均畸变程度的改善效果会不断减低。因此找出在K值增大的过程中,畸变程度下降幅度最大的位置所对应的K较为合理。
注:
成本函数:各个类的畸变程度之和与其内部成员位置距离的平方和,最优解是以成本函数最小化为目标。公式如下:
3、规则法:K= (此种方法存在一定的缺点:可能导致聚类的数目较大)
下面来说说Kmeans算法的模型效果评估,模型算法的评估主要是从以下几个方面来进行度量(当然还有其他的指标):
1、样本离最近聚类中心的总和(inertias)
inertias:其是K均值模型对象的属性,表示样本距离最近的聚类中心的总和,它是作为在没有真实分类标签下的非监督式评估指标,该值越小越好,值越小证明样本在类间的分布越集中,即类内的距离越小。
2、轮廓系数
轮廓系数:它用来计算所有样本的平均轮廓系数,使用平均群内距离和每个样本的平均最近簇距离来计算,它是一种非监督式评估指标。其最高值为1,最差值为-1,0附近的值表示重叠的聚类,负值通常表示样本已被分配到错误的集群。
3、兰德指数
调整后的兰德指数:兰德指数通过考虑在预测和真实聚类中在相同或不同的聚类中分配的所有样本对和计数对来计算两个聚类之间的相似性度量。调整后的兰德指数通过对兰德指数的调整得到独立于样本量和类别的接近于0的值,其取值范围为[-1,1],负数代表结果不好,越接近于1越好意味着聚类结果与真实情况吻合。
4、同质化得分
同质化得分(Homogeneity),如果所有的聚类都只包含属于单个类的成员的数据点,则聚类结果将满足同质性。其取值范围[0,1]值越大意味着聚类结果与真实情况越吻合。
优缺点小结
优点:1、原理简单,容易实现且收敛速度快。
2、聚类效果较好
缺点也很明显:
1、K值得选取不好确定
2、对于不是凸的数据集比较难收敛
3、如果各隐含类别的数据不平衡,比如各隐含类别的数据量严重失衡,或者各隐含类别的方差不同,则聚类效果较差
4、采用迭代方法,得到的结果只是局部最优。
5、对噪音和异常点比较的敏感
代码实例:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from scipy.spatial.distance import cdist
from sklearn import metrics #导入sklearn效果评估模块
#导入相关数据
raw_data=np.loadtxt('D:\data\chapter4\cluster.txt')
X=raw_data[:,:-1] #分割要聚类的数据
y_true=raw_data[:,-1]
#确定要聚类的数目:肘部法则
X=raw_data[:,:-1] #分割要聚类的数据
y_true=raw_data[:,-1]
plt.figure()
plt.axis([0, 2.5, 0, 2.5])
plt.grid(True)
plt.plot(X[:,0],X[:,1],'k.')
K = range(1, 10)
meandistortions = []
for k in K:
kmeans = KMeans(n_clusters=k)
kmeans.fit(X)
meandistortions.append(sum(np.min(cdist(X, kmeans.cluster_centers_, 'euclidean'), axis=1)) / X.shape[0])
plt.plot(K, meandistortions, 'bx-')
plt.xlabel('k')
plt.ylabel('meandistortions')
plt.title('best K of the model');
#训练聚类模型
n_clusters=3 #设置聚类数量
model_kmeans=KMeans(n_clusters=n_clusters,random_state=0) #建立聚类模型对象
model_kmeans.fit(X) #训练聚类模型
y_pre=model_kmeans.predict(X) #预测聚类模型
#模型效果评估
n_samples,n_features=X.shape #总样本量,总特征数
inertias=model_kmeans.inertia_ #样本距离最近的聚类中心的总和
adjusted_rand_s=metrics.adjusted_rand_score(y_true,y_pre) #调整后的兰德指数
homogeneity_s=metrics.homogeneity_score(y_true,y_pre) #同质化得分
silhouette_s=metrics.silhouette_score(X,y_pre,metric='euclidean') #平均轮廓系数
#模型效果可视化
centers=model_kmeans.cluster_centers_ #各类别中心
colors=['#4EACC5','#FF9C34','#4E9A06'] #设置不同类别的颜色
plt.figure() #建立画布
for i in range(n_clusters): #循环读取类别
index_sets=np.where(y_pre==i) #找到相同类的索引集合、
cluster=X[index_sets] #将相同类的数据划分为一个聚类子集
plt.scatter(cluster[:,0],cluster[:,1],c=colors[i],marker='.') #展示聚类子集内的样本点
plt.plot(centers[i][0],centers[i][1],'o',markerfacecolor=colors[i]
,markeredgecolor='k',markersize=6) #展示各聚类子集的中心
plt.show() #展示图像
肘部法确定K值:
从图中可以看出K值应该取3。
#模型效果评估:
ine ARI homo silh
300 0.96 0.94 0.63
----------------------------------------------------------------------
ine inertias
ARI adjuster_rand_s
homo homogeneity_s
silh silhouette_s
----------------------------------------------------------------------
模型效果的可视化:
从上表和图中可以看出,兰德指数得分0.96、平均轮廓系数得分0.94,轮廓系数0.63,说明聚类效果较好。