机器学习--sklearn之k均值聚类

什么是簇?

简单来说,簇就是分类结果中的类,但实际上簇并没有明确的定义,并且簇的划分没有客观标准,我们可以利用下图来理解什么是簇。该图显示了20个点和将它们划分成簇的3种不同方法。标记的形状指示簇的隶属关系。下图分别将数据划分成两部分、四部分和六部分。将2个较大的簇每一个都划分成3个子簇可能是人的视觉系统造成的假象。此外,说这些点形成4个簇可能也不无道理。该图表明簇的定义是不精确的,而好的定义依赖于数据的特性和期望的结果。
在这里插入图片描述

k均值聚类原理

k均值是发现给定数据集的k个簇的算法。簇个数k是用户给定的,每一个簇通过其质心(centroid)来描述。
k均值聚类工作流程是这样的:首先,随机选择k个初始质心,其中k是用户指定的参数,即所期望的簇的个数。然后将数据集中的每个点指派到距离最近的质心,所有被指派到一个质心的点即为一个簇。然后,根据指派到簇的点,将每个簇的质心更新为该簇所有点的平均值。重复指派和更新步骤,直到簇不发生变化(或直到质心不发生变化)。

工作流程伪代码

创建k个点作为初始质心(通常是随机选择) 
当任意一个点的簇分配结果发生改变时:    
	对数据集中的每个点:        
		对每个质心:            
			计算质心与数据点之间的距离        
		将数据点分配到据其近的簇    
	对每个簇,计算簇中所有点的均值并将均值作为新的质心 
直到簇不再发生变化或者达到大迭代次数 

这个过程可以由下图来显示,我们规定,将数据分为4簇(k=4),其中白色X代表质心的位置:
在这里插入图片描述

距离的算法

聚类算法追求的是“簇内差异小,簇外差异大”。而这个“差异“,我们由样本点到其所在簇的质心的距离来衡量。
对于一个簇来说,所有样本点到质心的距离之和越小,我们就认为这个簇中的样本越相似,簇内差异就越小。而距离的衡量方法有多种,令 x x x表示簇中的一个样本点, μ \mu μ表示该簇中的质心, n n n表示每个样本点中的特征数目, i i i表示组成点 x x x的每个特征,则该样本点到质心的距离可以由以下距离来度量:

在这里插入图片描述
如我们采用欧几里得距离,则一个簇中所有样本点到质心的距离的平方和为:
在这里插入图片描述
其中, m m m为一个簇中样本的个数, j j j是每个样本的编号。这个公式被称为簇内平方和(cluster Sum of Square),又叫做Inertia。而将一个数据集中的所有簇的簇内平方和相加,就得到了整体平方和(Total Cluster Sum of Square),又叫做total inertia。Total Inertia越小,代表着每个簇内样本越相似,聚类的效果就越好。因此 K-Means追求的是,求解能够让Inertia最小化的质心。实际上,在质心不断变化不断迭代的过程中,总体平方和是越来越小的。我们可以使用数学来证明,当整体平方和最小的时候,质心就不再发生变化了。如此,K-Means的求解过程,就变成了一个最优化问题。

python解决聚类问题

from sklearn.datasets import make_blobs  # 允许自己创建数据
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans

# 创建数据
X, y = make_blobs(n_samples=500,n_features=2,centers=4,random_state=1)

# 将生成的点画出来
fig, ax1 = plt.subplots(1) 
ax1.scatter(X[:, 0], 
            X[:, 1], 
            marker='o',  # 点的形状
            s=8  # 点的大小
           ) 
plt.show()

color = ["red","pink","orange","gray"] 
fig, ax1 = plt.subplots(1)
 
for i in range(4):
    ax1.scatter(X[y==i, 0], X[y==i, 1], 
                marker='o', 
                s=8, 
                c=color[i]) 
plt.show()

n_clusters = 3
cluster = KMeans(n_clusters=n_clusters, random_state=0).fit(X)
y_pred = cluster.labels_  # 查看聚好的类
y_pred 

pre = cluster.fit_predict(X)  # 判断X在聚类结果上会被分到哪一类,无监督学习不需要调用
pre == y_pred

centroid = cluster.cluster_centers_  # 查看质心坐标
centroid

inertia = cluster.inertia_  # 查看总距离平方和
inertia

color = ["red","pink","orange","gray"] 
fig, ax1 = plt.subplots(1)

for i in range(n_clusters):
    ax1.scatter(X[y_pred==i, 0], X[y_pred==i, 1], 
                marker='o', 
                s=8, 
                c=color[i]
               ) 
ax1.scatter(centroid[:,0], centroid[:,1],
            marker="x", 
            s=15, 
            c="black"
           ) 
plt.show()

# 将k换成4
n_clusters = 4

cluster_ = KMeans(n_clusters=n_clusters, random_state=0).fit(X) 
inertia_ = cluster_.inertia_ 
inertia_ 

如何评价聚类的效果?-- 轮廓系数

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

python计算轮廓系数

from sklearn.metrics import silhouette_score 
from sklearn.metrics import silhouette_samples

silhouette_score(X,y_pred)  # 总轮廓系数(分三个簇)
silhouette_score(X,cluster_.labels_)  # 总轮廓系数(分四个簇)
silhouette_samples(X,y_pred)  # 返回每个样本点自己的轮廓系数(三个簇)
silhouette_samples(X,cluster_.labels_)  # 返回每个样本点自己的轮廓系数(四个簇)

基于轮廓系数来选择n_clusters

import matplotlib.cm as cm 
import numpy as np
 
for n_clusters in [2,3,4,5,6,7]:
    fig, (ax1, ax2) = plt.subplots(1, 2)
    fig.set_size_inches(18, 7)
    ax1.set_xlim([-0.1, 1])

    ax1.set_ylim([0, X.shape[0] + (n_clusters + 1) * 10])
    clusterer = KMeans(n_clusters=n_clusters, random_state=10).fit(X)
    cluster_labels = clusterer.labels_

    silhouette_avg = silhouette_score(X, cluster_labels)
    print("For n_clusters =", n_clusters,
          "The average silhouette_score is :", silhouette_avg)
 
    sample_silhouette_values = silhouette_samples(X, cluster_labels)
    y_lower = 10
 
    for i in range(n_clusters):
        ith_cluster_silhouette_values = sample_silhouette_values[cluster_labels == i]
        ith_cluster_silhouette_values.sort()
        size_cluster_i = ith_cluster_silhouette_values.shape[0]
        y_upper = y_lower + size_cluster_i
        color = cm.nipy_spectral(float(i)/n_clusters)
        ax1.fill_betweenx(np.arange(y_lower, y_upper),ith_cluster_silhouette_values,facecolor=color,alpha=0.7)
        ax1.text(-0.05, y_lower + 0.5 * size_cluster_i,str(i))
        y_lower = y_upper + 10
    ax1.set_title("The silhouette plot for the various clusters.")
    ax1.set_xlabel("The silhouette coefficient values")
    ax1.set_ylabel("Cluster label")
    ax1.axvline(x=silhouette_avg, color="red", linestyle="--")
    ax1.set_yticks([])
    ax1.set_xticks([-0.1, 0, 0.2, 0.4, 0.6, 0.8, 1])
    colors = cm.nipy_spectral(cluster_labels.astype(float) / n_clusters)
    ax2.scatter(X[:, 0], X[:, 1],marker='o' #点的形状
                ,s=8 #点的大小
                ,c=colors)
    centers = clusterer.cluster_centers_
    ax2.scatter(centers[:, 0], centers[:, 1], marker='x',c="red", alpha=1, s=200)
    ax2.set_title("The visualization of the clustered data.")
    ax2.set_xlabel("Feature space for the 1st feature")
    ax2.set_ylabel("Feature space for the 2nd feature")
    plt.suptitle(("Silhouette analysis for KMeans clustering on sample data "
                  "with n_clusters = %d" % n_clusters),
                  fontsize=14, fontweight='bold')
    plt.show()
  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cofisher

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值