机器学习-聚类算法

聚类算法,字面意思可以理解为对数据进行汇聚以及分类的过程。
在高维度的数据集中 ,每一个数据都包含了大量的信息,不同于二维三维时候我们可以轻易分辨,所以我们可能需要聚类算法帮我们将数据分类。

那么分类的依据是什么呢?应该就是数学上所说的欧氏距离。
通过距离的不同我们可以将数据进行分类。
例如对于k-means算法我们可以:
1.通过我们设置的中心(第一次可以较为随意的设置这个中心)到每个数据的欧氏距离将分类算法运行。
2.迭代后我们得到了分出类别的数据们,然后,再在每类数据中进行计算,根据欧式距离最小的原则,得出新的中心点。
3.重复过程2直到所有数据所属类别不再变化,我们就得到了收敛后的模型。

而每个数据集所分的种类数量是我们可以自己控制的,我们希望将数据分成几类就分成几类(但是不合理的类别数量有可能会让模型的鲁棒性下降)。

———————————————————————————————
下面是引用了一篇自己喜欢的文章:

所谓人以类聚,物以群分。人都喜欢跟自己像的人聚在一起,这些人或者样子长得比较像,或者身高比较像,或者性格比较像,或者有共同的爱好,也就是身上有某些特征是相似的。

而跟自己像的人聚在一起的过程,其实就是寻找朋友的过程,比如A认识B,因为跟B兴趣相近于是成为了朋友,通过B又认识了C,发现兴趣较一致于是也成为了朋友,那么ABC三个人就是一个朋友群,这个朋友群的形成,是自下而上的迭代的过程。在100个人当中,可能有5个朋友群,这5个朋友群的形成可能要2个月。
在这里插入图片描述
而聚类算法,跟以上的过程很像。
聚类算法,是把距离作为特征,通过自下而上的迭代方式(距离对比),快速地把一群样本分成几个类别的过程。
有人可能会说,干嘛要聚类啊,肉眼看猪是猪牛是牛这不一下就分开了么,那如果是一万头猪跟牛,你能一下分开么?
又有人说猪跟牛长的那么不一样,一下就看出来了,还用机器?其实猪跟牛看的出分别是因为他们的外形太不一样。实际上样本可能有几个甚至几十个维度,光对比其中1,2个维度基本分不出差别。
所以聚类算法,一般是面向大量的,同时维度在2个或2个以上的样本群。

前面讲到,聚类算法是根据样本之间的距离来将他们归为一类的,这个距离不是普通的距离,理论上叫做欧氏距离。
为什么不用普通的距离就好,用这么拗口的欧式距离?那是为了衡量高于三维空间的样本之间的距离。在二维和三维空间里,欧式距离就是我们理解的普通的距离。
在多维空间里,假设两个样本为a(x1,x2,x3,x4…xn),b(y1,y2,y3,y4…yn)。那么他们之间的欧式距离的计算公式是在这里插入图片描述
那么聚类算法,是怎么通过迭代的方式,将样本聚成几个类别的呢?
有一种最经典的K-Means聚类方法,他是这样运作的:
1、在样本中随机选择K个点,作为每个类别的初始中心点,这K是自己定的,假如你想将样本分成3个类K就等于3,4个类K就等于4;
2、计算所有样本离这K个初始中心点的距离并分别进行比较,选出其中最近的距离并把这个样本归到这个初始中心点的类别里,即总共划分成K个类别;
3、舍弃原来的初始中心点,在划分好的K个类别里分别计算出新的中心点,使得这些中心点距离他类别里的所有样本的距离之和最小;
4、判断新获得的中心点是否与旧中心点一样,如不一样则回到第2步,重新计算所有样本离这K个新的中心点的距离并进行比较,选出其中最近的距离并归到这个新的中心点的类别里,继续下面的步奏;如一样则完成,即收敛。

可以用下面的图很好地说明
在这里插入图片描述
有ABCDE5个样本,一开始选定右边的2个初始中心点,K=2,大家颜色都不一样,谁都不服谁;在这里插入图片描述
5个样本分别对比跟2个初始中心点的距离,选距离近的傍依,这时5个样本分成红黑2群;在这里插入图片描述
然后开始换老大啦,2个初始中心点消失,重新在2个类分别中心的位置出现2个新的中心点,这2个新的中心点离类别里样本的距离之和必须是最小的;在这里插入图片描述
新的老大出现,类别的划分也不一样啦,C开始叛变,皈依新老大,因为他离新老大更近一点;在这里插入图片描述
新的老大消失,新新老大出现,发现划分的类别没有变化,帮派稳定,于是收敛。

用Python写了一个简单的聚类算法:

import matplotlib.pyplot as plt
import random
import math
from copy import copy

#寻找新的中心点的函数
def new(group):
    minimum=10000
    o=[]
    for x1 in range(min(group['x']),max(group['x'])):
        for y1 in range(min(group['y']),max(group['y'])):
            j=0
            red_sum=0
            while j<=len(group['x'])-1:
                red_sum+=math.sqrt((group['x'][j]-x1)**2+(group['y'][j]-y1)**2)
                j+=1
            o.append(red_sum)
            if(red_sum<minimum):
                minimum=copy(red_sum)
                x2=copy(x1)
                y2=copy(y1)
    return x2,y2

#根据中心点聚类并且着色的函数
def color(a,b,x,y):
    i=0
    red={'x':[],'y':[]}
    blue={'x':[],'y':[]}
    black={'x':[],'y':[]}
    while i<=90:
        distance0=math.sqrt((int(a[i])-x[0])**2+(int(b[i])-y[0])**2)
        distance1=math.sqrt((int(a[i])-x[1])**2+(int(b[i])-y[1])**2)
        distance2=math.sqrt((int(a[i])-x[2])**2+(int(b[i])-y[2])**2)
        if (min(distance0,distance1,distance2)==distance0):
            plt.plot(a[i],b[i],'ro',color='red')
            red['x'].append(int(a[i]))
            red['y'].append(int(b[i]))
        elif (min(distance0,distance1,distance2)==distance1):
            plt.plot(a[i],b[i],'ro',color='blue')
            blue['x'].append(int(a[i]))
            blue['y'].append(int(b[i]))
        else:
            plt.plot(a[i],b[i],'ro',color='black')
            black['x'].append(int(a[i]))
            black['y'].append(int(b[i]))
        i+=1
    return red,blue,black

def main():
    #读取数据
    file=open('d:/kmeans/data.txt')
    a=[]
    b=[]
    for line in file.readlines():
        data=line.strip().split(',')
        a.append(data[0])
        b.append(data[1])
    #随机选取3个初始中心点
    x=[random.randint(1,20),random.randint(1,20),random.randint(1,20)]
    y=[random.randint(1,20),random.randint(1,20),random.randint(1,20)] 
    red,blue,black=color(a,b,x,y)
    plt.plot(x[0],y[0],'x',color='red',markersize=15)
    plt.plot(x[1],y[1],'x',color='blue',markersize=15)
    plt.plot(x[2],y[2],'x',color='black',markersize=15)
    plt.axis([0,25,0,25])
    plt.show()
    #循环执行函数,直到收敛
    while (x[0],y[0]!=new(red)) or (x[1],y[1]!=new(blue)) or (x[2],y[2]!=new(black)):
        x[0],y[0]=new(red)
        x[1],y[1]=new(blue)
        x[2],y[2]=new(black)
        red,blue,black=color(a,b,x,y) 
        plt.plot(x[0],y[0],'x',color='red',markersize=15)
        plt.plot(x[1],y[1],'x',color='blue',markersize=15)
        plt.plot(x[2],y[2],'x',color='black',markersize=15)
        plt.axis([0,25,0,25])
        plt.show()
    file.close()  
    
if __name__=='__main__':
    main()

第一次聚类时,分布是这样的在这里插入图片描述
第二次聚类时,分布是这样的在这里插入图片描述
收敛时,分布是这样的在这里插入图片描述
文章转载自挖数
版权归作者所有
———————————————————————————————
常见的聚类算法有下列五种:
一、上面提到的k-means算法
二、均值偏移(Mean shift)聚类算法
三、DBSCAN聚类算法
四、使用高斯混合模型(GMM)的期望最大化(EM)聚类
五、层次聚类算法
层次聚类算法在selective research中有应用到,这里具体讲解一下。
算法其实可以分为两类:自上而下或自下而上。
自下而上的算法:将每一个数据视为一个分类,然后将这些单一的分类进行合并,直到所有类合并成一个包含所有数据点的单一聚类。因此,自下而上的层次聚类称为合成聚类(合成为一类)或HAC。
聚类的层次结构用一棵倒立的树来表示。树的根是收集所有样本的唯一聚类,而叶子是只有一个样本的聚类。在这里插入图片描述
算法步骤如下:
1.我们首先将每个数据点作为一个单独的聚类进行处理。如果我们的数据集有X个数据点,那么我们就有了X个聚类。然后我们选择一个度量两个聚类之间距离的距离度量。作为一个示例,我们将使用平均连接(average linkage)聚类,它定义了两个聚类之间的距离,即第一个聚类中的数据点和第二个聚类中的数据点之间的平均距离。
2.在每次迭代中,我们将两个聚类合并为一个。将两个聚类合并为具有最小平均连接的组。比如说根据我们选择的距离度量,这两个聚类之间的距离最小,因此是最相似的,应该组合在一起。(意思是找出平均距离最小的两个组进行合并)
3.重复步骤2直到我们到达树的根。我们只有一个包含所有数据点的聚类。通过这种方式,我们可以选择最终需要多少个聚类,只需选择何时停止合并聚类,也就是我们停止建造这棵树的时候!

层次聚类算法不要求我们指定聚类的数量,我们甚至可以选择哪个聚类看起来最好。此外,该算法对距离度量的选择不敏感;它们的工作方式都很好,而对于其他聚类算法,距离度量的选择是至关重要的。层次聚类方法的一个特别好的用例是,当底层数据具有层次结构时,你可以恢复层次结构;而其他的聚类算法无法做到这一点。层次聚类的优点是以低效率为代价的,因为它具有O(n³)的时间复杂度,与K-Means和高斯混合模型的线性复杂度不同。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值