机器学习 之 Kmeans聚类

什么是Kmeans聚类

Kmeans聚类算法为一般的无监督的数据挖掘算法,它是在没有给定结果值的情况下,对于这类数据进行建模。聚类算法的目的就是根据已知的数据,将相似度较高的样本集中到各自的簇中。
在这里插入图片描述

Kmeans聚类思想

Kmeans就是不断的计算各样本点与簇中心之间的距离,直到收敛为止,大致分为以下4个步骤:

  1. 从数据中随机挑选K个样本点作为原始的簇中心
  2. 计算剩余样本与促中心的距离,并把各样本标记为离K个簇中心最近的类别(距离的度量可选择欧式距离,曼哈顿距离等)
  3. 重新计算各簇中样本点的均值,并以均值作为新的K个簇中心
  4. 不断循环2和3,直到簇中心的变化趋于稳定,形成K个簇

一次循环:
在这里插入图片描述

Kmeans重要参数和接口

Kmeans(n_clusters=4 # 对于指定聚类的簇数,无默认值
		,init="random" # 表示从数据集中随机挑选K个样本点作为初始簇中心
		,n_init=10 # 用于指定该算法运行次数,每次运行时都会选择不同的初始促中心,目的是防止算法收敛于局部最优,默认10
		,max_iter=300 # 表示单次运行的迭代次数,默认300
		,tol=0.0001 # 算法收敛阈值,默认0.0001
		,random_state
		)

labels_ # 聚类结果标签
cluster_centers_ # 质心坐标
inertia_#总距平方和,受n_clusters影响
需要通过训练好的模型进行调用

注意如果量纲不统一,要进行标准化处理消除大量纲对结果的较大偏差。

聚类小例子

import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
import numpy as np
from sklearn.datasets import make_blobs

X, y = make_blobs(n_samples=500,n_features=2,centers=4,random_state=0)
clu=KMeans(n_clusters=4,random_state=10).fit(X)
# 聚类结果的每个样本的标签
clu_label=clu.labels_

fig=plt.figure(figsize=(8,5))
ax=fig.add_subplot(111)
ax.scatter(X[:, 0]  # 所有点的横坐标
            , X[:, 1] # 所有点的纵坐标
            ,marker='o' # 离散点的图形
            ,s=8  # 大小
            ,c=clu_label
            # 当该值为字符串时,则所有的点为字符串所对应的颜色
            # 若为列表则他会根据列表值,分别对于不同类别的点进行不同颜色的分配
            )
centers = clu.cluster_centers_
# 画出质心
ax.scatter(centers[:, 0], centers[:, 1], marker='x',c="red", alpha=1, s=200)
plt.show()

在这里插入图片描述

可能有疑惑了,那我们怎么知道这些数据应该被分为几簇呢?
接下来就来探究一下

n_clusters的探究

聚类结果评价指标

1.轮廓系数(常用):

轮廓系数

from sklearn.metrics import silhouette_score
from sklearn.metrics import silhouette_samples
silhouette_score(原始数据值,数据对应的聚类结果)#总体模型打分

#silhouette_samples(newimage,labels).mean()与上结果同
silhouette_samples(newimage,labels)#单个数据点打分
#结果越近1越好,近-1越不好

2.卡林斯基—哈拉巴斯评估

转载地址
在这里插入图片描述

from sklearn.metrics import calinski_harabasz_score
calinski_harabasz_score(数据值,数据对应的聚类结果)
#结果越大越好,无具体值
拐点法
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs

x,y=make_blobs(n_samples=[400,400,400,400],n_features=2,cluster_std=[1,1,1,1],random_state=10)
inertia_list=[]
for i in range(1,13):
    kmeans=KMeans(n_clusters=i).fit(x)
    inertia_list.append(kmeans.inertia_)

fig=plt.figure(figsize=(10,4))
ax1=fig.add_subplot(121)
ax1.plot(range(1, 13), inertia_list)
ax1.set_ylabel("inertia_")
ax1.set_xlabel("n_clusters")
ax2=fig.add_subplot(122)
ax2.scatter(x[:,0],x[:,1])
plt.show()

在这里插入图片描述
当簇数为4的时候形成了一个明显的拐点,因为K值从1~4时折线的斜率都比较大,但是 K=5时突然就降低了很多,并且之后的数对应的斜率变动很小,所以合理的K值应该为4,与虚拟的三个簇数据相吻合

轮廓系数法

为更好的理解下面的代码,先了解一下这个画图函数:

fill_betweenx

fig=plt.figure(figsize=(8,5))
ax=fig.add_subplot(111)

ax.fill_betweenx([1,2,3,4], # 纵向位置
				[0.4,0.8,0.1,0.5], # 横向长度
				facecolor="red", 
				alpha=0.7
				)
# ax.fill_betweeny同理
plt.show()

在这里插入图片描述

单一的n_clusters聚类效果直观化
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score,silhouette_samples
import matplotlib.cm as cm
import numpy as np
from sklearn.datasets import make_blobs

X, y = make_blobs(n_samples=500,n_features=2,centers=4,random_state=0)
n_cluster=4

# 创建画布并确定大小
fig=plt.figure(figsize=(12,5))
# 将画布分为两部分,并分别指定区域建立画布子对象
ax1=fig.add_subplot(1,2,1)
ax2=fig.add_subplot(122)

# 限制X轴和Y轴图像的显示坐标范围
ax1.set_xlim([-0.1,1])
ax1.set_ylim([0,X.shape[0]+10*(n_cluster+1)])
# 聚类实例化并训练
clu=KMeans(n_clusters=n_cluster,random_state=10).fit(X)

# 拿出500个样本对应分类好的结果的标签
clu_label=clu.labels_

# 根据500个样本的结果进行打分(轮廓系数)
silhouette_avg=silhouette_score(X,clu_label)

# 取出500个样本点各自的打分
sample_silhouette_value=silhouette_samples(X,clu_label)

# 确定一范围下端值,以便颜色填充
y_lower=10

# 对每一个簇进行遍历画图
for i in range(n_cluster):
    # 取出样本结果为i的样本点
    each_silhouette_values = sample_silhouette_value[clu_label == i]
    # 对该簇中每个点的轮廓系数进行排序
    each_silhouette_values.sort()
    # 确定每个簇占纵坐标的高度
    size_cluster_i = each_silhouette_values.shape[0]
    # 用算出来的高度加上该簇最低点的值算出最高点,以此来确定颜色高度范围
    y_upper = y_lower + size_cluster_i
    # 随机颜色确定,cm.nipy_spectral()中填入浮点数即可,可以不是float(i)/n_cluster
    color = cm.nipy_spectral(float(i)/n_cluster)
    #
    ax1.fill_betweenx(np.arange(y_lower, y_upper), each_silhouette_values, facecolor=color, alpha=0.7)
    #ax1.text(-0.05, y_lower + 0.5 * size_cluster_i, str(i))
    ax1.text(-0.05 # 添加文本的横坐标位置
            ,  y_lower + 0.5 * size_cluster_i  # 添加文本的纵坐标位置,这里表示最下端加上一半的高度,就是中间。
            , str(i)  # 格式化输出score,去掉不必要的0
            , size=8  # 大小

            # 文本框类型
            , bbox=dict(boxstyle="round", alpha=0.5, facecolor="green")# 圆形透明度为0.5绿色的文本框
            , horizontalalignment="right"  # 以文本框的右侧为基准线
            )
    # 转换最下端的纵坐标值已备下一簇使用
    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])

ax2.scatter(X[:, 0]  # 所有点的横坐标
            , X[:, 1] # 所有点的纵坐标
            ,marker='o' # 离散点的图形
            ,s=8  # 大小

            ,c=clu_label
            # 当该值为字符串时,则所有的点为字符串所对应的颜色
            # 若为列表则他会根据列表值,分别对于不同类别的点进行不同颜色的分配
            )
# 取出质心坐标
centers = clu.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_cluster)
             ,fontsize=14,# 大小
             fontweight='bold' # 字体类型
             )
plt.show()

我们发现这4个簇中都有一些超过了平均分,在一定程度上,对于模型的效果有一定的可能存在的效果提升
在这里插入图片描述

不同的n_clusters效果
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score,silhouette_samples
import matplotlib.cm as cm
import numpy as np
from sklearn.datasets import make_blobs

X, y = make_blobs(n_samples=500,n_features=2,centers=4,random_state=0)
fig=plt.figure(figsize=(10,8))
j=0
for n_cluster in range(3,6):
    j+=1
    ax1 = fig.add_subplot(3, 2, j)
    ax1.set_xlim([-0.1, 1])
    ax1.set_ylim([0, X.shape[0] + 10 * (n_cluster + 1)])
    clu = KMeans(n_clusters=n_cluster, random_state=10).fit(X)
    clu_label = clu.labels_
    silhouette_avg = silhouette_score(X, clu_label)
    sample_silhouette_value = silhouette_samples(X, clu_label)
    y_lower = 10
    for i in range(n_cluster):
        each_silhouette_values = sample_silhouette_value[clu_label == i]

        each_silhouette_values.sort()

        size_cluster_i = each_silhouette_values.shape[0]

        y_upper = y_lower + size_cluster_i
        color = cm.nipy_spectral(float(i) / n_cluster)
        #
        ax1.fill_betweenx(np.arange(y_lower, y_upper), each_silhouette_values, facecolor=color, alpha=0.7)
        ax1.text(-0.05
                 , y_lower + 0.5 * size_cluster_i
                 , str(i)
                 , size=8
                 , bbox=dict(boxstyle="round", alpha=0.5, facecolor="green")
                 , horizontalalignment="right"
                 )

        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])
    j+=1
    ax2 = fig.add_subplot(3, 2, j)
    ax2.scatter(X[:, 0]  , X[:, 1] , marker='o', s=8 ,c=clu_label)
    centers = clu.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.n_clusters= %d " % n_cluster)
    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 = n"),fontsize=14,fontweight='bold')
plt.tight_layout()# 自动调节子图与子图之间的间距。
plt.show()

在这里插入图片描述
在n_clusters为3编号为2的和在n_clusters为5编号为3的簇中基本上全部在平均的轮廓系数下,所以对于模型的效果有拉低的现象,可以直观看出模型效果,不过对于聚类算法来说也没有特别固定最好的n_clusters值,所以有时候我们还要根据实际情况问题具体分析。

Kmeans聚类在图片上的应用

import matplotlib.pyplot as plt
from sklearn.datasets import load_sample_image
from sklearn.cluster import KMeans
from sklearn.utils import shuffle

china=load_sample_image("china.jpg")
plt.imshow(china)#只接受三维数组
newimage=china.reshape((427*640,3))# 将数据由三维转化为二维
image_china=shuffle(newimage,random_state=1)[:1111]
#将图片的数据打乱,并且随机选出1111(任意)个像素点用于确定质心
kmeans=KMeans(n_clusters=64#聚类质心个数
              #,max_iter=300最大迭代次数
              #,return_n_iter=True显示最佳迭代次数
              #,tol=1e-4梯度下降最小下降距离
                ).fit(image_china)
labels=kmeans.predict(newimage)

#用kmeans聚类结果替换到原始数据中
for i in range(427*640):
    newimage[i]=kmeans.cluster_centers_[labels[i]]
    
plt.figure()
plt.imshow(newimage.reshape((427,640,3)))

结果:聚类算法处理颐和园图形

原数据量为427*640,处理过后的数据量为64,数据处理量减小
4270倍,却几乎保留了原数据全部特征。极大减小了计算机在
运算过程的数据处理量。
  • 6
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

「 25' h 」

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

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

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

打赏作者

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

抵扣说明:

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

余额充值