kmeans聚类详解

**
(1) kmeans简介
K-means算法是很典型的基于距离的聚类算法,采用距离作为相似性的评价指标,即认为两个对象的距离越近,其相似度就越大。该算法认为簇是由距离靠近的对象组成的,因此把得到紧凑且独立的簇作为最终目标。
k个初始类聚类中心点的选取对聚类结果具有较大的影响,因为在该算法第一步中是随机的选取任意k个对象作为初始聚类的中心,初始地代表一个簇。该算法在每次迭代中对数据集中剩余的每个对象,根据其与各个簇中心的距离将每个对象重新赋给最近的簇。当考察完所有数据对象后,一次迭代运算完成,新的聚类中心被计算出来。如果在一次迭代前后,J的值没有发生变化,说明算法已经收敛。
(2)算法过程如下
1.计算欧氏距离
2.随机选取k个初始聚类中心点
3.更新簇的中心点
4.迭代,直到收敛
通常停止迭代的条件:

  • 达到指定的迭代次数
  • 质心不再发生明显的变化,即收敛
    这里采用了设置迭代次数而停止迭代
    (3)实现步骤
    导入库和模块

导入数据.画出未聚类的图

kmeans聚类算法核心思想 kmeans聚类算法原理与步骤_kmeans


kmeans聚类算法核心思想 kmeans聚类算法原理与步骤_kmeans_02


计算欧氏距离

kmeans聚类算法核心思想 kmeans聚类算法原理与步骤_kmeans_03


初始化质心, 将给定数据集构建一个包含K个随机质心的数组

kmeans聚类算法核心思想 kmeans聚类算法原理与步骤_kmeans_04


开始kmeans聚类

kmeans聚类算法核心思想 kmeans聚类算法原理与步骤_聚类_05


更新质心

kmeans聚类算法核心思想 kmeans聚类算法原理与步骤_kmeans_06


开始迭代,迭代10次

kmeans聚类算法核心思想 kmeans聚类算法原理与步骤_聚类_07


第一次迭代

kmeans聚类算法核心思想 kmeans聚类算法原理与步骤_聚类_08


第二次迭代

kmeans聚类算法核心思想 kmeans聚类算法原理与步骤_迭代_09


第三次迭代

kmeans聚类算法核心思想 kmeans聚类算法原理与步骤_聚类_10


第四次迭代

kmeans聚类算法核心思想 kmeans聚类算法原理与步骤_聚类_11


第五次迭代

kmeans聚类算法核心思想 kmeans聚类算法原理与步骤_kmeans聚类算法核心思想_12


第六次迭代

kmeans聚类算法核心思想 kmeans聚类算法原理与步骤_迭代_13


第七次迭代

kmeans聚类算法核心思想 kmeans聚类算法原理与步骤_聚类_14


第八次迭代

kmeans聚类算法核心思想 kmeans聚类算法原理与步骤_python3_15


第九次迭代

kmeans聚类算法核心思想 kmeans聚类算法原理与步骤_kmeans聚类算法核心思想_16


第十次迭代

kmeans聚类算法核心思想 kmeans聚类算法原理与步骤_迭代_17


最后画出聚类结果图

kmeans聚类算法核心思想 kmeans聚类算法原理与步骤_kmeans_18


最后的聚类结果图,聚成了4类,在k=4的时候聚类效果最好

kmeans聚类算法核心思想 kmeans聚类算法原理与步骤_kmeans_19


(4)对kmeans算法的认识

• 聚类是一种无监督的学习方法

• K均值算法需要用户指定创建的簇数k

• K均值算法在大数据集上收敛较慢

优点

K-Means聚类算法的优点主要集中在:

1.算法快速、简单;

2.对大数据集有较高的效率并且是可伸缩性的;

3.时间复杂度近于线性,而且适合挖掘大规模数据集。K-Means聚类算法的时间复杂度是O(nkt) ,其中n代表数据集中对象的数量,t代表着算法迭代的次数,k代表着簇的数目

缺点

① 在 K-means 算法中 K 是事先给定的,这个 K 值的选定是非常难以估计的

② 在 K-means 算法中,首先需要根据初始聚类中心来确定一个初始划分,然后对初始划分进行优化。这个初始聚类中心的选择对聚类结果有较大的影响,一旦初始值选择的不好,可能无法得到有效的聚类结果,这也成为 K-means算法的一个主要问题。

③ 从 K-means 算法框架可以看出,该算法需要不断地进行样本分类调整,不断地计算调整后的新的聚类中心,因此当数据量非常大时,算法的时间开销是非常大的。所以需要对算法的时间复杂度进行分析、改进,提高算法应用范围。

(5)源代码展示

"""
Created on Mon Dec 10 13:53:35 2018

@author: liushengzhen
"""
#%%导入使用的库
import numpy as np
import random
import matplotlib.pyplot as plt  
                                                  
#%%导入数据                                         
def loadDataSet(fileName):
    data = np.loadtxt(fileName,delimiter='\t')
    return data
x = loadDataSet("testSet.txt")
#print(x)                      #输出数据
plt.scatter(x[:,0],x[:,1])   
plt.title('original data')  #画出未聚类的图
plt.show()

#%%计算欧氏距离
def distance(sub1,sub2):                          #numpy的数组可以对一个向量做减法,得到的还是一个向量
    return np.sqrt(np.sum(np.square(sub1-sub2))) #对向量做平方,求和,开方,得到sub1和sub2的欧式距离
#%%初始化质心    
K=4 
# 将给定数据集构建一个包含K个随机质心的数组           
tempclass=np.zeros(x.shape[0]) #获得x的第0列的维度(行数)
center = random.sample(range(x.shape[0]),K)#从x的第0列数中随机挑选k个数
centerArray = x[center,:]      #从x中获得以center的序列内容为行的向量,列数是从第0列到最后一列
#至此完成了对 kmeans 中心点的生成(质心)

#%%kmeans聚类
def kmeans(centerArray):
    for i in range(80):               #因为是80行数据,这里要准备逐条遍历x的80行数据
        mindis=10000;                 #质心的最小距离  
        sub1=x[i,:]                   #获取矩阵x的第i行数据
        for j in range(K):            #遍历质心
            sub2=centerArray[j,:]     # 按行读取质心列表中的行向量
            temp = distance(sub1,sub2) # 逐个元素计算与质心的距离
            #print ("the disctent %d"%(temp)) #输出的是80个数据依次到4个质心的距离(一次迭代320)
            if (temp<mindis):         # 在k个质心里面选择距离最小的
                mindis=temp           #
                tempclass[i]=j        #得到样本i 距离最近质心
    print (tempclass)
#%%
    #更新质心
    for j in range(K): #遍历质心                    #按照质心个数,统计每个质心下面的样本
        tempclassResult = x[tempclass==j]  #从聚类结果里面分别拿到每个类的样本
        x1=np.mean(tempclassResult[:,0])   #取出tempclassResult里面第0列的值序列,并对这个序列计算均值
        x2=np.mean(tempclassResult[:,1])   
        centerArray[j,:]=[int(x1),int(x2)] #更新质心数组里面的质心坐标

#%%开始迭代        
#迭代10次
for i in range(10):
    print("i=%d"%i)
    kmeans(centerArray)
        
#%%绘图显示  
for i,c in zip(range(K),['r','m','b','g','y']): #zip()函数用于将可迭代的对象作为参数,将对象中
    cla=x[tempclass==i]                         #对应的元素打包成一个元组,m品红
    p1=plt.scatter(cla[:,0],cla[:,1],marker='o',color=c,label='data')  
p2=plt.scatter(centerArray[:,0],centerArray[:,1],marker='x',color='black',label='x')
plt.title('Clustering results')  
plt.legend(loc='upper right')  
plt.show()