机器学习(五):聚类

一、基本原理

聚类(clustering)是一种无监督学习(unsupervised learning),即没有标记信息,通过对无标记训练样本的学习发现数据的内在性质和规律。
对于样本集D=\left\{\boldsymbol{x}_{1}, \boldsymbol{x}_{2}, \ldots, \boldsymbol{x}_{m}\right\},聚类算法需要将样本划分为k个互不相交的簇\mathcal{C}=\left\{C_{1},C_{2}, \ldots, C_{k} \right\}. k-means算法针对聚类所得簇最小化平方误差:E=\sum_{i=1}^{k} \sum_{\boldsymbol{x} \in C_{i}}\left\|\boldsymbol{x}-\boldsymbol{\mu}_{i}\right\|_{2}^{2} 其中\boldsymbol{\mu}_{i}=\frac{1}{\left|C_{i}\right|} \sum_{\boldsymbol{x} \in C_{i}} \boldsymbol{x}为簇均值向量。E在一定程度上刻画了簇内样本围绕簇均值向量的紧密程度,E越小相似度越高。
简单来说,k-means算法主要分为两个步骤:
第一步:簇分配,随机选k个点作为中心,计算到这k个点的距离,分为k个簇。
第二步:移动聚类中心:重新计算每个簇的中心,移动中心,重复以上步骤。

k-means算法

二、算法实现

k-means算法过程比较简单明晰,以下为其实现过程:

  1. 所需要的库
import numpy as np
import scipy.io as spio
import imageio
import matplotlib.pyplot as plt
  1. 主体过程,返回聚类中心的位置和各点的归属
def KMeans(X,init_centroids,max_iters,plot_process):
    m,n = X.shape
    K = init_centroids.shape[0]
    centriods = init_centroids
    pre_centroids = centriods
    
    for i in range(max_iters):
        if plot_process:
            ax = plotProcess(X,centriods,pre_centroids)
            pre_centroids = centriods
        idx = calcDistance(X,centriods)
        centriods = calcCentroids(X,idx,K)
    if plot_process:
        ax.show()
    return centriods,idx
  1. 计算各点到聚类中心的位置,并据此将其分属不同类
def calcDistance(X,init_centroids):
    m = X.shape[0]
    K = init_centroids.shape[0]
    dis = np.zeros((m,K))
    idx = np.zeros((m,1))
    
    for i in range(m):
        for j in range(K):
            dis[i,j] = np.dot((X[i,:]-init_centroids[j,:]).reshape(1,-1),(X[i,:]-init_centroids[j,:]).reshape(-1,1))
    
    dummy, idx = np.where(dis==np.min(dis,axis=1).reshape(-1,1))
    return idx[0:m]
  1. 计算聚类中心,即均值向量
def calcCentroids(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)
        
    return centroids
  1. 辅助函数,绘图及初始化聚类中心位置
def plotProcess(X,centriods,pre_centroids):
    plt.scatter(X[:,0],X[:,1])
    plt.plot(pre_centroids[:,0],pre_centroids[:,1],'r*',markersize=10,linewidth=5)
    plt.plot(centriods[:,0],centriods[:,1],'r*',markersize=10,linewidth=5)
    for j in range(centriods.shape[0]):
        p1 = centriods[j,:]
        p2 = pre_centroids[j,:]
        plt.plot([p1[0],p2[0]],[p1[1],p2[1]],'->',linewidth=2)
    return plt

def initCentroids(X,K):
    m = X.shape[0]
    m_arr = np.arange(0,m)
    centroids = np.zeros((K,X.shape[1]))
    np.random.shuffle(m_arr)
    rand_indices = m_arr[:K]
    centroids = X[rand_indices,:]
    return centroids
  1. 主函数
def main():
    data = spio.loadmat('data.mat')
    X = data['X']
    K = 3 
   # init_centroids = np.array([[3,3],[0,2],[7,5]])
    init_centroids = initCentroids(X,K)
    max_iters = 10
    KMeans(X,init_centroids,max_iters,True)
if __name__=='__main__':
    main()

下图为聚类的结果,形象展示了聚类中心及其移动过程。

聚类中心及其移动过程

聚类算法可用于图片的压缩,将图片的像素分为若干类,然后用这个类代替原来的像素值,以下为其实现过程及结果:

def imageCompression():
    img_data = imageio.imread('bird.png')
    img_data = img_data/255.0
    img_size =img_data.shape
    X = img_data.reshape(img_size[0]*img_size[1],3)
    
    K = 10
    max_iters = 10
    init_centroids = initCentroids(X,K)
    centroids,idx = KMeans(X,init_centroids,max_iters,False)
    idx = calcDistance(X,centroids)
    X_recovered = centroids[idx,:]
    X_recovered = X_recovered.reshape(img_size[0],img_size[1],3)
    
    plt.subplot(1,2,1)
    plt.imshow(img_data)
    plt.subplot(1,2,2)
    plt.imshow(X_recovered)
    plt.show()
    
if __name__=='__main__':
    imageCompression()    
原图及压缩后的结果

另外可以通过mglearn库展示聚类过程和分类边界。

import mglearn

mglearn.plots.plot_kmeans_algorithm()
mglearn.plots.plot_kmeans_boundaries()
聚类过程及分类边界

三、问题探讨

3.1、性能度量

聚类性能度量大致有两类:一类是外部指标,就是将聚类结果与某个“参考模型”比较;另一类是内部指标,即直接考察聚类结果而不利用任何参考模型。
外部指标

  • Jaccard系数(Jaccard Coefficient, JC)
    J C=\frac{a}{a+b+c}
  • FM指数(Fowlkes and Mallows Index, FMI)
    \mathrm{FMI}=\sqrt{\frac{a}{a+b} \cdot \frac{a}{a+c}}
  • Rand指数(Rand Index, RI)
    \mathrm{RI}=\frac{2(a+d)}{m(m-1)}
    上述指标的结果值均在[0,1]之间,值越大越好。
    其中
    a=|S S|, \quad S S=\left\{\left(x_{i}, x_{j}\right) | \lambda_{i}=\lambda_{j}, \lambda_{i}^{*}=\lambda_{j}^{*}, i<j\right) \}
    b=|S D|, \quad S D=\left\{\left(x_{i}, x_{j}\right) | \lambda_{i}=\lambda_{j}, \lambda_{i}^{*} \neq \lambda_{j}^{*}, i<j\right) \}
    c=|D S|, \quad D S=\left\{\left(x_{i}, x_{j}\right) | \lambda_{i} \neq \lambda_{j}, \lambda_{i}^{*}=\lambda_{j}^{*}, i<j\right) \}
    d=|D D|, \quad D D=\left\{\left(x_{i}, x_{j}\right) | \lambda_{i} \neq \lambda_{j}, \lambda_{i}^{*} \neq \lambda_{j}^{*}, i<j\right) \}
    \mathcal{C}^{*}=\left\{C_{1}^{*}, C_{2}^{*}, \ldots, C_{s}^{*}\right\}表示参考模型。

内部指标

  • DB指数(Davies-Bouldin Index, DBI)
    \mathrm{DBI}=\frac{1}{k} \sum_{i=1}^{k} \max _{j \neq i}\left(\frac{\operatorname{avg}\left(C_{i}\right)+\operatorname{avg}\left(C_{j}\right)}{d_{\operatorname{cen}}\left(\boldsymbol{\mu}_{i}, \boldsymbol{\mu}_{j}\right)}\right)
  • Dunn指数(Dunn Index, DI)
    \mathrm{DI}=\min _{1 \leqslant i \leqslant k}\left\{\min _{j \neq i}\left(\frac{d_{\min }\left(C_{i}, C_{j}\right)}{\max _{1 \leqslant l \leqslant k} \operatorname{diam}\left(C_{l}\right)}\right)\right\}
    DBI的值越小越好,DI值越大越好。
    其中
    \operatorname{avg}(C)=\frac{2}{|C|(|C|-1)} \sum_{1 \leqslant i<j \leqslant|C|} \operatorname{dist}\left(x_{i}, x_{j}\right)
    \operatorname{diam}(C)=\max _{1 \leqslant i<j \leq|C|} \operatorname{dist}\left(\boldsymbol{x}_{i}, \boldsymbol{x}_{j}\right)
    d_{\min }\left(C_{i}, C_{j}\right)=\min _{\boldsymbol{x}_{i} \in C_{i, \boldsymbol{x}} \in C_{j}} \operatorname{dist}\left(\boldsymbol{x}_{i}, \boldsymbol{x}_{j}\right)
    d_{\mathrm{cen}}\left(C_{i}, C_{j}\right)=\operatorname{dist}\left(\boldsymbol{\mu}_{i}, \boldsymbol{\mu}_{j}\right)

3.2、距离度量

距离度量\operatorname{dist}(\cdot, \cdot)是机器学习中一个非常常用的概念,反映了两点之间的相似程度,具有非负性、同一性、对称性和三角不等式性质。最常用的表示方法是闵可夫斯基距离(Minkowski distance)
\operatorname{dist}_{\mathrm{mk}}\left(\boldsymbol{x}_{i}, \boldsymbol{x}_{j}\right)=\left(\sum_{u=1}^{n}\left|x_{i u}-x_{j u}\right|^{p}\right)^{\frac{1}{p}}

p=2时,即欧氏距离(Euclidean distance)
\operatorname{dist}_{\mathrm{ed}}\left(\boldsymbol{x}_{i}, \boldsymbol{x}_{j}\right)=\left\|\boldsymbol{x}_{i}-\boldsymbol{x}_{j}\right\|_{2}=\sqrt{\sum_{u=1}^{n}\left|x_{i u}-x_{j u}\right|^{2}}

p=1时,即曼哈顿距离(Manhattan distance)
\operatorname{dist}_{\operatorname{man}}\left(\boldsymbol{x}_{i}, \boldsymbol{x}_{j}\right)=\left\|\boldsymbol{x}_{i}-\boldsymbol{x}_{j}\right\|_{1}=\sum_{u=1}^{n}\left|x_{i u}-x_{j u}\right|

另外,聚类算法还包括密度聚类(如DBSCAN)、层次聚类(如AGNES)等,在此不予详述。

参考资料

[1] https://github.com/lawlite19/MachineLearning_Python
[2] 周志华 著. 机器学习. 北京:清华大学出版社,2016
[3] 李航 著. 统计学习方法. 北京:清华大学出版社,2012
[4] 史春奇等 著. 机器学习算法背后的理论与优化. 北京:清华大学出版社,2019
[5] Peter Harrington 著. 李锐等 译. 机器学习实战. 北京:人民邮电出版社,2013

人生如逆旅,我亦是行人 ——苏轼《临江仙·送钱穆父》

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容