呕心沥血干完K-Means聚类

呕心沥血干完K-Means聚类

K-Means简介

K-Means 是一种非监督学习。

K 代表的是 K 类,Means 代表的是中心,它有点像全自动分类。聚类方法几乎可以应用于所有对象,簇内的对象越相似,聚类的效果越好。

主要思想是:在给定K值K个初始类簇中心点的情况下,把每个点(也就是数据)分到离其最近的类簇中心点所代表的类簇中,所有点分配完毕之后,根据一个类簇内的所有点重新计算该类簇的中心点(取平均值),然后再迭代的进行分配点和更新类簇中心点的步骤,直至类簇中心点的变化很小,或者达到指定的迭代次数。

基本概念

也就是类,假定有一些数据,现在将相似数据归到一起,簇识别会告诉我们这些簇到底都是些什么。

K

簇个数,是自己给定的,k是多少就有多少个簇。

质心

均值,即向量各维取平均,即簇中所有点的中心来描述。

距离的度量

常用欧氏距离 ( x 2 + y 2 ) \sqrt{x^2+y^2} ) x2+y2 ​)和余弦相似度(通过测量两个向量的夹角的余弦值来度量它们之间的相似性),大多情况下都要先标准化

欧氏距离

假定给定数据样本X,包含了n个对象 X = { X 1 , X 2 , X 3 , . . . , X n } X =\lbrace X_1 , X_2 , X_3 , . . . , X_n \rbrace X={X1​,X2​,X3​,...,Xn​},其中每个对象都具有m个维度的属性。Kmeans算法的目标是将n个对象依据对象间的相似性聚集到指定的k个类簇中,每个对象属于且仅属于一个该对象到类簇中心距离最小的类簇中

对于Kmeans,首先需要初始化k个聚类中心 { C 1 , C 2 , C 3 , . . . , C k } \lbrace C_1,C_2,C_3,...,C_ k \rbrace {C1​,C2​,C3​,...,Ck​},然后通过计算每一个对象到每一个聚类中心的欧式距离,如下式所示:

d i s ( X i , C j ) = ∑ t = 1 m ( X i t − C i t ) 2 dis(X_i,C_j)=\sqrt{\sum_{t=1}^m (X_{it}-C_{it})^2} dis(Xi​,Cj​)=t=1∑m​(Xit​−Cit​)2

上式中 X i X_i Xi​表示第i个对象 1 ≤ i ≤ n 1\leq i \leq n 1≤i≤n

C j C_j Cj​表示第j个聚类中心的 1 ≤ j ≤ k 1\leq j \leq k 1≤j≤k

X i t X_{it} Xit​表示第i个对象的第t个属性 1 ≤ t ≤ m 1\leq t \leq m 1≤t≤m 表示第j个聚类中心的第t个属性。

比如一组对象是三维空间的许多点,其中一点a具体表示为( a 1 , b 1 , c 1 a_1,b_1,c_1 a1​,b1​,c1​)、b表示为( a 2 , b 2 , c 2 a_2,b_2,c_2 a2​,b2​,c2​)…
其某个聚类中心为o点( x 0 , y 0 , z ( 0 ) x_0,y_0,z_(0) x0​,y0​,z(​0),那么a点到o点的距离为:

d i s ( a , o ) = ( a 1 − x 0 ) 2 + ( b 1 − y 0 ) 2 + ( c 1 − z 0 ) 2 dis(a,o)=\sqrt {(a_1-x_0)^2+(b_1-y_0)^2+(c_1-z_0)^2} dis(a,o)=(a1​−x0​)2+(b1​−y0​)2+(c1​−z0​)2

依次比较每一个对象到每一个聚类中心的距离,将对象分配到距离最近的聚类中心的类簇中,得到k个类簇 { S 1 , S 2 , S 3 , . . . , S k } \lbrace S_1,S_2,S_3,...,S_ k \rbrace {S1​,S2​,S3​,...,Sk​}

聚类中心计算

Kmeans算法用中心定义了类簇的原型,类簇中心就是类簇内所有对象在各个维度的均值,其计算公式如下:
C j = ∑ X i ∈ S p X i ∣ N S p ∣ C_j=\frac{\sum_{X_i\in S_p}X_i}{\lvert{N_{S_p}}\rvert} Cj​=∣NSp​​∣∑Xi​∈Sp​​Xi​​

C j C_j Cj​表示第j个聚类中心, 1 ≤ j ≤ k 1\leq j \leq k 1≤j≤k; ∣ N S p ∣ \lvert{N_{S_p}}\rvert ∣NSp​​∣表示第p个类簇中对象的个数; X i X_i Xi​表示第j个类簇中的第i个对象, 1 ≤ i ≤ ∣ N S p ∣ 1\leq i \leq \lvert{N_{S_p}}\rvert 1≤i≤∣NSp​​∣

比如一个二维平面上某一个聚类中心,里面有10个点,这十个点的聚类中心:

X轴坐标为: x = x 1 + x 2 + . . . + x 10 10 x=\frac{x_1+x_2+...+x_{10}}{10} x=10x1​+x2​+...+x10​​

Y轴坐标为: y = y 1 + y 2 + . . . + y 10 10 y=\frac{y_1+y_2+...+y_{10}}{10} y=10y1​+y2​+...+y10​​

所以该聚类中心就是 ( x , y ) (x,y) (x,y)

K-Means 工作原理

呕心沥血干完K-Means聚类
呕心沥血干完K-Means聚类

总结来说:

  1. 选取 K 个点作为初始的类中心点,这些点一般都是从数据集中随机抽取的;
  2. 将每个点分配到最近的类中心点,这样就形成了K 个类,然后重新计算每个类的中心点;
  3. 重复第二步,直到类不发生变化,或者你也可以设置最大迭代次数,这样即使类中心点发生变化,但是只要达到最大迭代次数就会结束。

算法流程

我现在选择了我的桌面对图像进行实例分割

呕心沥血干完K-Means聚类

导入图片、查看大小

#导入相关包
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
#读取图片,转为numpy 数组,向量为长宽的像素值,rgb通道数为3
img = np.array(Image.open("dog.png"))
# 展示图像
plt.imshow(img)

# reshape,将长宽拉成一个一维的向量
x = img.reshape(-1,3)
print(img.shape,x.shape)

呕心沥血干完K-Means聚类

图像中每个像素点可以看做是一个数据点(三维向量 x = ( x 0 , x 1 , x 2 ) x=(x_0,x_1,x_2) x=(x0​,x1​,x2​))总共组成了1212714个三维向量集

生成随机聚类中心

在数据集中随机选取k个中心点, 用Z表示k个三维向量构成的数组

#随机初始化Z
def init_center(x,k):
    # 从x的第一维度的长度中随机选k个数
    index = np.random.choice(np.arange(x.shape[0]),k)
    # 返回x在该行的值
    return x[index]
#k 为要聚类的中心数
k = 2
z = init_center(x,k)
z

呕心沥血干完K-Means聚类

计算距离

分别计算每个数据点到k个中心点的距离,根据距离对该数据点进行分类。

def classify(x,Z):
    Z_new = np.ones(Z.shape[0:])
    #计算距离
    temp = np.sum((x.reshape(1,-1,3) - Z.reshape(Z.shape[0],-1,3)) ** 2,axis=2)
    index = np.argmin(temp,axis=0)
    for i in range(Z.shape[0]):
        # 同类的向量求和取均值,返回更新的Z与距离
        Z_new[i] = np.mean(x[index==i],axis=0)
        # 返回更新的Z,距离与分类情况
    return Z_new,np.sum(temp),index


Z_new,distant,index = classify(x,z)
print("待更新的Z\n{}\n数据点到聚类中心距离和{}\n分类情况{}".format(Z_new,distant,index))

迭代求中心

def kmean(x,k):
    #x (个数,特征维度)
    #k 聚类个数
    #index (个数,)对应k类别的索引
    Z = init_center(x,k)#初始Z
    epoch = 100#迭代次数 使用迭代的方法得到最终距离收敛的结果
    for step in range(epoch):
        Z,D,index = classify(x,Z)
        if(step%10==0):
            print("第{}次循环,距离{}".format(step+1,D))
    return index,D

index,D = kmean(x,k)

结果展示

plt.imshow(index.reshape(img.shape[0:2]))

呕心沥血干完K-Means聚类

上一篇:K-means算法的参数详解


下一篇:【机器学习】K-Means聚类算法原理