聚类--KMeans算法

本文详细介绍了K-Means聚类算法的原理和流程,包括随机选择初始聚类中心,计算样本点与聚类中心的距离,更新聚类中心等步骤。同时,讨论了算法的局限性,如易受初始中心影响和k值选择的挑战。通过Python代码展示了算法的实现,并使用肘部法则确定最佳k值。最后,通过绘制聚类结果和误差变化来评估模型性能。
摘要由CSDN通过智能技术生成

算法流程

从数据集中随机选取k个聚类样本作为初始的聚类中心,然后计算数据集中每个样本到这k个聚类中心的距离(一般为欧氏距离),选取距离最小的聚类中心所对应的类别作为该样本点的类别;将所有样本点归类后,重新计算每个类别的聚类中心(取每类别样本集的均值)。重复上述过程,直到聚类中心不再更新或者达到阈值(如最大迭代次数)。

算法缺点

  1. k-means是局部最优的,容易受到初始聚类中心(即质心)的影响,造成次优的聚类结果;
  2. k值的选取也会影响聚类结果,最优聚类的k值应与样本数据本身的结构信息相吻合,而这种结构信息是很难去掌握,因此选取最优k值是非常困难的。

python代码实现

假设对如下数据进行聚类,首先可视化数据:

import numpy as np
import matplotlib.pyplot as plt
import scipy.io as sio
%matplotlib notebook
path='D:\code\python\database\ex7data2'
data=sio.loadmat(path)
X=data['X']
plt.scatter(X[:,0],X[:,1])
<IPython.core.display.Javascript object>
<matplotlib.collections.PathCollection at 0x1fac633d198>

定义模型并训练


class KMeans:
    #初始化模型参数
    def __init__(self,k,max_iter=50):
        self.k = k  #聚类簇数
        self.max_iter = max_iter #最大迭代次数
        self.all_centroids = []  #存放迭代的聚类中心

    #初始化聚类中心,从样本中随机选取
    def initCentroids(self,X):
        m,n = X.shape
        centroids = np.zeros((self.k,n))
        index = np.random.randint(0,m,self.k)
        for i in range(len(centroids)):
            centroids[i] = X[index[i]]
        return centroids

    #寻找每个样本点的最近簇
    def findClosestCentroids(self,X,centroids):
        m = X.shape[0]
        label = np.zeros(m)
        for i in range(m):
            min_dist = np.inf
            for j in range(len(centroids)):
                dist = np.sum((X[i]-centroids[j])**2)
                if min_dist > dist:
                    min_dist = dist
                    label[i] = j
        return label

    #计算聚类中心
    def getCentroids(self,X,label):
        centroids = np.zeros((self.k,X.shape[1]))
        for i in range(self.k):
            centroids[i] = X[label==i].mean(axis=0)
        return centroids

    #训练模型
    def fit(self,X):
        #centroids = self.initCentroids(X) #初始化聚类中心
        centroids = np.array([[3,3],[6,2],[8,5]])#以该聚类中心展示效果
        for i in range(self.max_iter):
            self.all_centroids.append(centroids)
            label = self.findClosestCentroids(X,centroids)  #每个样本点所属类别
            centroids = self.getCentroids(X,label)  #更新聚类中心
        self.label = self.findClosestCentroids(X,centroids)

    #绘制KMeans算法结果
    def plotKMeans(self,X):
        x, y = [], []  
        #绘制聚类结果
        plt.scatter(X[:, 0], X[:, 1], c=self.label, cmap='rainbow')
        for i in range(self.max_iter):
            x.append(self.all_centroids[i][:,0])
            y.append(self.all_centroids[i][:,1])
        #绘制聚类中心迭代路径
        plt.plot(x,y,marker='*')
        plt.show()

    #计算模型平方误差
    def squareError(self,X):
        error = 0
        final_centroids = self.all_centroids[-1]
        for i in range(X.shape[0]):
            j = int(self.label[i])
            error += np.sum((X[i]-final_centroids[j])**2)
        return error
    
model = KMeans(3,10)
model.fit(X)
model.plotKMeans(X)
<IPython.core.display.Javascript object>

利用肘部法则选取k的值,选k=3。

error = []
for k in range(1,9):
    model = KMeans(k,10)
    model.fit(X)
    error.append(model.squareError(X))
plt.xlabel('k')
plt.ylabel('error')
plt.plot(range(1,9),error)
D:\a\python\anaconda.install\lib\site-packages\ipykernel_launcher.py:35: RuntimeWarning: Mean of empty slice.
D:\a\python\anaconda.install\lib\site-packages\numpy\core\_methods.py:73: RuntimeWarning: invalid value encountered in true_divide
  ret, rcount, out=ret, casting='unsafe', subok=False)



<IPython.core.display.Javascript object>
[<matplotlib.lines.Line2D at 0x1fac6f39668>]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值