动手写机器学习算法:K-Means聚类算法

Posted 七月在线实验室

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动手写机器学习算法:K-Means聚类算法相关的知识,希望对你有一定的参考价值。

K-Means算法是无监督的聚类算法,它实现起来比较简单,聚类效果也不错,因此应用很广泛。今天小七和你一起用Python实现机K-Means聚类算法。


全部代码

https://github.com/lawlite19/MachineLearning_Python/blob/master/K-Means/K-Menas.py


聚类过程

聚类属于无监督学习,不知道y的标记分为K类

K-Means算法分为两个步骤

第一步:簇分配,随机选K个点作为中心,计算到这K个点的距离,分为K个簇

第二步:移动聚类中心:重新计算每个簇的中心,移动中心,重复以上步骤。

如下图所示:

随机分配的聚类中心

动手写机器学习算法:K-Means聚类算法

重新计算聚类中心,移动一次

动手写机器学习算法:K-Means聚类算法

最后10步之后的聚类中心

动手写机器学习算法:K-Means聚类算法

计算每条数据到哪个中心最近实现代码:

# 找到每条数据距离哪个类中心最近    

def findClosestCentroids(X,initial_centroids):

    m = X.shape[0]                  # 数据条数

    K = initial_centroids.shape[0]  # 类的总数

    dis = np.zeros((m,K))           # 存储计算每个点分别到K个类的距离

    idx = np.zeros((m,1))           # 要返回的每条数据属于哪个类

    

    '''计算每个点到每个类中心的距离'''

    for i in range(m):

        for j in range(K):

            dis[i,j] = np.dot((X[i,:]-initial_centroids[j,:]).reshape(1,-1),(X[i,:]-initial_centroids[j,:]).reshape(-1,1))

    

    '''返回dis每一行的最小值对应的列号,即为对应的类别

    - np.min(dis, axis=1)返回每一行的最小值

    - np.where(dis == np.min(dis, axis=1).reshape(-1,1)) 返回对应最小值的坐标

     - 注意:可能最小值对应的坐标有多个,where都会找出来,所以返回时返回前m个需要的即可(因为对于多个最小值,属于哪个类别都可以)

    '''  

    dummy,idx = np.where(dis == np.min(dis, axis=1).reshape(-1,1))

    return idx[0:dis.shape[0]]  # 注意截取一下


计算类中心实现代码:

# 计算类中心

def computerCentroids(X,idx,K):

    n = X.shape[1]

    centroids = np.zeros((K,n))

    for i in range(K):

        centroids[i,:] = np.mean(X[np.ravel(idx==i),:], axis=0).reshape(1,-1)   # 索引要是一维的,axis=0为每一列,idx==i一次找出属于哪一类的,然后计算均值

    return centroids


目标函数

也叫做失真代价函数

动手写机器学习算法:K-Means聚类算法

最后我们想得到:动手写机器学习算法:K-Means聚类算法

其中动手写机器学习算法:K-Means聚类算法表示第i条数据距离哪个类中心最近,其中动手写机器学习算法:K-Means聚类算法即为聚类的中心


聚类中心的选择

随机初始化,从给定的数据中随机抽取K个作为聚类中心

随机一次的结果可能不好,可以随机多次,最后取使代价函数最小的作为中心


实现代码:(这里随机一次)

# 初始化类中心--随机取K个点作为聚类中心

def kMeansInitCentroids(X,K):

    m = X.shape[0]

    m_arr = np.arange(0,m)      # 生成0-m-1

    centroids = np.zeros((K,X.shape[1]))

    np.random.shuffle(m_arr)    # 打乱m_arr顺序    

    rand_indices = m_arr[:K]    # 取前K个

    centroids = X[rand_indices,:]

    return centroids


聚类个数K的选择

聚类是不知道y的label的,所以不知道真正的聚类个数

肘部法则(Elbow method)

作代价函数J和K的图,若是出现一个拐点,如下图所示,K就取拐点处的值,下图此时K=3 

动手写机器学习算法:K-Means聚类算法

若是很平滑就不明确,人为选择。

第二种就是人为观察选择


应用——图片压缩

将图片的像素分为若干类,然后用这个类代替原来的像素值

执行聚类的算法代码:

# 聚类算法

def runKMeans(X,initial_centroids,max_iters,plot_process):

    m,n = X.shape                   # 数据条数和维度

    K = initial_centroids.shape[0]  # 类数

    centroids = initial_centroids   # 记录当前类中心

    previous_centroids = centroids  # 记录上一次类中心

    idx = np.zeros((m,1))           # 每条数据属于哪个类

    

    for i in range(max_iters):      # 迭代次数

        print u'迭代计算次数:%d'%(i+1)

        idx = findClosestCentroids(X, centroids)

        if plot_process:    # 如果绘制图像

            plt = plotProcessKMeans(X,centroids,previous_centroids) # 画聚类中心的移动过程

            previous_centroids = centroids  # 重置

        centroids = computerCentroids(X, idx, K)    # 重新计算类中心

    if plot_process:    # 显示最终的绘制结果

        plt.show()

    return centroids,idx    # 返回聚类中心和数据属于哪个类


使用scikit-learn库中的线性模型实现聚类

https://github.com/lawlite19/MachineLearning_Python/blob/master/K-Means/K-Means_scikit-learn.py


导入包

from sklearn.cluster import KMeans 


使用模型拟合数据

model = KMeans(n_clusters=3).fit(X) # n_clusters指定3类,拟合数据 


聚类中心

centroids = model.cluster_centers_  # 聚类中心 


运行结果

二维数据类中心的移动

动手写机器学习算法:K-Means聚类算法


图片压缩

动手写机器学习算法:K-Means聚类算法


https://github.com/lawlite19/MachineLearning_Python#

相关文章:






点击下方“阅读全文”,即刻学Python

以上是关于动手写机器学习算法:K-Means聚类算法的主要内容,如果未能解决你的问题,请参考以下文章

K-Means算法:基于聚类的无监督机器学习算法

机器学习(25)之K-Means聚类算法详解

机器学习笔记之谱聚类k-Means聚类算法介绍

机器学习笔记之谱聚类k-Means聚类算法介绍

机器学习算法之 k-means 聚类算法

机器学习--聚类系列--K-means算法