【算法6】K-Means聚类

    聚类属于无监督分类算法。用得较多的有基于距离的聚类——K-Means,基于密度的聚类——DBSCAN。可以用作数据降维、数据离散压缩、客户分群等用途,这里直接进入主题:

K-Means

1 K-Means描述
    ⾸先,选择K个初始质心,其中K是我们指定的参数,即所期望的簇的个数。每个点指派到最近的质心,而指派到⼀一个质心的点集为⼀一个簇。然后,根据指派到簇的点,更更新每个簇的质心。重复指派和更更新步骤,直到簇不不发⽣生变化,或等价地,直到质⼼不发⽣生变化。K-Means的核⼼心任务就是根据我们设定好的K,找出K个最优的质心,并将离这些质心最近的数据分别分配到这些质心代表的簇中去。具体过程可以总结如下:
    创建k个点作为初始质⼼心(通常是随机选择)
    当任意⼀一个点的簇分配结果发⽣生改变时:
    对数据集中的每个点:
    对每个质⼼心:
    计算质⼼心与数据点之间的距离
    将数据点分配到据其最近的簇
    对每个簇,计算簇中所有点的均值并将均值作为新的质⼼心
    直到簇不不再发⽣生变化或者达到最⼤大迭代次数
    那什么情况下,质心的位置会不再变化呢?当我们找到一个质心,在每次迭代中被分配到这个质⼼上的样本都是一致的,即每次新生成的簇都是一致的,所有的样本点都不会再从一个簇转移到另一个簇,质心就不会变化了。

2 K-Means细节
    聚类算法聚出的类有什么含义呢?这些类有什么样的性质?我们认为, 被分在同⼀一个簇中的数据是有相似性的,而不同簇中的数据是不同的,当聚类完毕之后,我们就要分别去研究每个簇中的样本都有什么样的性质,从而根据业务需求制定不同的商业或者科技策略略。聚类算法的⽬目的就是追求“簇内差异小,簇外差异大”。⽽而这个“差异“,由样本点到其所在簇的质心的距离来衡量。对于一个簇来说,所有样本点到质心的距离之和越小,我们就认为这个簇中的样本越相似,簇内差异就越小。而距离的衡量方法有多种,令 表示簇中的一个样本点, 表示该簇中的质心, n表示每个样本点中的特征数目, i表示组成点 的每个特征,则该样本点到质心的距离可以由以下距离来度量。

3 距离种类

数据距离
    欧几里得距离:
d ( x , u ) = [ i = 1 n [ x i u i ] 2 ] 1 / 2 d(x,u)=[\sum_{i=1}^n [x_i-u_i]^2]^{1/2}
    曼哈顿距离:
d ( x , u ) = i = 1 n [ x i u i ] d(x,u)=\sum_{i=1}^n [|x_i-u_i|]
    闵可夫斯基距离:
d ( x , u ) = [ i = 1 n [ x i u i ] n ] 1 / 2 d(x,u)=[\sum_{i=1}^n [|x_i-u_i|]^n]^{1/2}     当为 n = 1 n=1 时,就是曼哈顿距离,当为 n = 2 n=2 时即为欧式距离,当 n n 趋于⽆无穷时,即为切⽐比雪夫距离。

文本距离
    余弦相关系数:
c o s ( Θ ) = i = 1 n [ x i u ] [ i = 1 n [ x i ] n ] 1 / 2 [ i = 1 n [ u i ] n ] 1 / 2 cos(\Theta)=\frac{\sum_{i=1}^n [| x_i*u|]}{[\sum_{i=1}^n [|x_i |]^n]^{1/2}*[\sum_{i=1}^n [| u_i|]^n]^{1/2}}
    杰卡德系数:
J ( A , B ) = A B A B J(A,B)=\frac{|A\bigcap B|}{|A\bigcup B|}
4 模型优化条件
    在聚类算法中, 组内误差平⽅方和( S S E SSE )是我们判断模型是否最优的重要指标,我们希望求得的模型是在给定K值得情况下 S S E SSE 最⼩小的模型,即在相同的K值情况下聚类模型 S S E SSE 越⼩小越好,这也是聚类算法最核⼼心的优化条件。
    聚类算法中的目标函数是实现聚类这一目标所使用的函数,如最小化对象到其所属类的质心距离等,这里需要注意,一般如果采用距离作为邻近度衡量标准,则目标函数往往是利用最小距离来构建聚类类别,而若采用相似度作为邻近度衡量标准,则⽬标函数就是利⽤用最大化相似度和来构建聚类类别.
    质心是聚类别的原型,一般可用均值或中位数来表示。但无论如何,在一旦确定距离衡量方法或邻近度函数(如欧式距离等),并在模型优化条件(SSE最小)的指导下,目标函数和质心选取⽅方法都会随之确定,常⽤用邻近度函数、质⼼心和目标函数组合如下:
在这里插入图片描述
    这一切实际上是建立在严格的数学理论推导的基础之上的,推导方法之一就是利利⽤用梯度下降进行计算。梯度下降是机器学习中最常用的局部最优化方法,我们在回归类算法中已经对其进行了详细的解释,此处简单介绍梯度下降在聚类算法中的应⽤用。首先,我们需要定义聚类算法中的符号集:
在这里插入图片描述
    那么:
S S E = i = 1 k x ϵ c i n [ c i x ] 2 SSE=\sum_{i=1}^k \sum_{x\epsilon c_i}^n [|c_i-x|]^2
其中 c i c_i 是第 i i 个簇, x x c i c_i 中的点, c i c_i 是第 i i 个簇的质心。我们这里验证最常用的,当采用欧式距离时当且仅当质心为均值的时候才能够保证在目标函数的聚类过程中 S S E SSE 保持最小。

5 python—sklearn实现K-Means

from sklearn.datasets import make_blobs
#⾃自⼰己创建数据集
X, y = make_blobs(n_samples=500,n_features=2,centers=4,random_state=1)
plt.scatter(X[:, 0], X[:, 1]
,marker='o' #点的形状
,s=8 #点的⼤大⼩小
);
#如果我们想要看⻅见这个点的分布,怎么办?
color = ["red","pink","orange","gray"]
for i in range(4):
plt.scatter(X[y==i, 0], X[y==i, 1]
,marker='o' #点的形状
,s=8 #点的⼤大⼩小
,c=color[i]
)

from sklearn.cluster import KMeans
n_clusters = 3
cluster = KMeans(n_clusters=n_clusters, random_state=0).fit(X)
#重要属性labels_,查看聚好的类别,每个样本所对应的类
y_pred = cluster.labels_
y_pred
#KMeans因为并不不需要建⽴立模型或者预测结果,因此我们只需要fit就能够得到聚类结果了了
#KMeans也有接⼝口predict和fit_predict,表示学习数据X并对X的类进⾏行行预测
#但所得到的结果和我们不不调⽤用predict,直接fit之后调⽤用属性labels⼀一模⼀一样
pre = cluster.fit_predict(X)
pre == y_pred
#我们什什么时候需要predict呢?当数据量量太⼤大的时候!
#其实我们不不必使⽤用所有的数据来寻找质⼼心,少量量的数据就可以帮助我们确定质⼼心了了
#当我们数据量量⾮非常⼤大的时候,我们可以使⽤用部分数据来帮助我们确认质⼼心
#剩下的数据的聚类结果,使⽤用predict来调⽤用
cluster_smallsub = KMeans(n_clusters=n_clusters, random_state=0).fit(X[:200])
y_pred_ = cluster_smallsub.predict(X)
y_pred == y_pred_
#但这样的结果,肯定与直接fit全部数据会不不⼀一致。有时候,当我们不不要求那么精确,或者我们的数据量量
实在太⼤大,那我们可以使⽤用这样的⽅方法。
#重要属性cluster_centers_,查看质⼼心
centroid = cluster.cluster_centers_
centroid
centroid.shape
#重要属性inertia_,查看总距离平⽅方和
inertia = cluster.inertia_
inertia
color = ["red","pink","orange","gray"]
for i in range(n_clusters):
plt.scatter(X[y_pred==i, 0], X[y_pred==i, 1]
,marker='o' #点的形状
,s=8 #点的⼤大⼩小
,c=color[i]
)
plt.scatter(centroid[:,0],centroid[:,1]
,marker="x"
,s=15
,c="black");

6 评估指标
聚类没有标签,即不知道真实答案的预测算法,我们必须完全依赖评价簇内的稠密程度(簇内差异小)和簇间的离散程度(簇外差异⼤)来评估聚类的效果。其中轮廓系数是最常⽤用的聚类算法的评价指标。它是对每个样本来定义的,它能够同时衡量量:
    1)样本与其自身所在的簇中的其他样本的相似度a,等于样本与同一簇中所有其他点之间的平均距离。
    2)样本与其他簇中的样本的相似度b,等于样本与下一个最近的簇中的所有点之间的平均距离。
    根据聚类的要求 ”簇内差异小,簇外差异大,我们希望b永远大于a,并且大得越多越好
    单个样本的轮廓系数计算为:
在这里插入图片描述
    这个公式可以被解析为:
在这里插入图片描述
    很容易易理理解轮廓系数范围是(-1,1),其中值越接近1表示样本与⾃自己所在的簇中的样本很相似,并且与其他簇中的样本不相似,当样本点与簇外的样本更相似的时候,轮廓系数就为负。当轮廓系数为0时,则代表两个簇中的样本相似度一致,两个簇本应该是一个簇。
    如果一个簇中的大多数样本具有比较高的轮廓系数,则簇会有较⾼的总轮廓系数,则整个数据集的平均轮廓系数越高,则聚类是合适的。如果许多样本点具有低轮廓系数甚至负值,则聚类是不合适的,聚类的超参数K可能设定得太大或者太小。

    轮廓系数的python检验:

from sklearn.metrics import silhouette_score
from sklearn.metrics import silhouette_samples
X
y_pred
silhouette_score(X,y_pred)
silhouette_score(X,cluster_.labels_)
#观察⼀一下不不同的K下,轮廓系数发⽣生什什么变化?
n_clusters = 5
cluster_ = KMeans(n_clusters=n_clusters, random_state=0).fit(X)
silhouette_score(X,cluster_.labels_)
silhouette_samples(X,y_pred)

    轮廓系数有很多优点,它在有限空间中取值,使得我们对模型的聚类效果有一个“参考”。并且,轮廓系数对数据的分布没有假设,因此在很多数据集上都表现良好。但它在每个簇的分割比较清洗时表现最好。但轮廓系数也有缺陷,它在凸型的类上表现会虚高,比如基于密度进⾏行行的聚类,或通过DBSCAN获得的聚类结果,如果使用轮廓系数来衡量,则会表现出比真实聚类效果更高的分数。
    关于K-Means聚类就先写到这里,再会。。。。

发布了39 篇原创文章 · 获赞 42 · 访问量 4859

猜你喜欢

转载自blog.csdn.net/weixin_41774099/article/details/102174874