机器学习:K-means和K-medoid聚类算法

一、两个算法的区别

两者的区别主要在质心的选择,K-means是样本点均值,K-medoid是从当前分类样本点中选取距离和最小的点。

二、算法步骤

1、K-means

1、随机选取K个质心
2、计算各个点到质心的距离
3、将点的类划分到离他最近的质心,形成K个cluster
4、根据分类好的cluster,在每个cluster内重新计算质心
每个cluster中各个点的平均值
5、重复迭代2-4次,知道前后两次分类误差小于指定值

2、K-medoids

1、随机选取K个质心
质心必须是某些样本点的值
2、计算各个点到质心的距离
3、将点的类划分到离他最近的质心,形成K个cluster
4、根据分类好的cluster,在每个cluster内重新计算质心
计算cluster中所有样本到其中一个点的距离和
选出距离和最小的样本为新的质心
5、重复迭代2-4次,知道前后两次分类误差小于指定值

三、优缺点分析

1、K-medoid的运行速度慢,因为计算质心的时间复杂度是O(n^2),因为它必须计算任意两点的距离,而K-means只计算平均距离,时间复杂度是O(1)
2、K-medoid对噪声的鲁棒性较好,可以将异常样本单独成类。
3、K-medoid只适用于小样本,K-means常用于大量样本。

四、K值选取

1、手肘法
手肘法的核心指标是误差平方和(SSE)。核心思想:随着聚类数K的增加,样本划分会更加精细,每个簇的聚合程度会逐渐提高,那么误差平方和SSE会逐渐变小。并且,当K小于真实聚类数时,由于K的增大会大幅增加每个簇的聚合程度,故SSE的下降幅度会很大,而当K到达真实聚类数时,再增加K所得到的聚合程度回报会迅速变小,所以SSE的下降幅度会骤减,然后随着K值的继续增大而趋于平缓,也就是说SSE和K的关系图是一个手肘的形状,而这个肘部对应的K值就是数据的真实聚类数。SSE-K折线图
2、轮廓系数法
该方法的核心指标是轮廓系数,某个样本点Xi的轮廓系数定义如下:
S = (b-a)/max(a,b)
其中,a是Xi与同簇的其他样本的平均距离,称为凝聚度,b是Xi与最近簇中所有样本的平均距离,称为分离度。而最近簇的定义是:
在这里插入图片描述
其中p是某个簇Ck中的样本。就是用Xi到某个簇所有样本的平均距离作为衡量改点到该簇的距离后,选择离Xi最近的一个簇的作为最近簇
求出所有样本的轮廓系数后再求平均值就得到了平均轮廓系数。平均轮廓系数的取值范围是[-1,1],且簇内样本的距离越近,簇间样本距离越远,平均轮廓系数越大,聚类效果越好。那么,选择平均轮廓系数最大的K值就是最佳簇类数。

五、初试聚类中心

1、随机选择K个点作为初始簇类中心。
2、首先随机选择一个点作为第一个初始类簇中心点,然后选择距离该点最远的那个点作为第二个初始类簇中心点,然后再选择距离前两个点的最近距离最大的点作为第三个初始类簇的中心点,以此类推,直至选出K个初始类簇中心点。
3、选用层次聚类或者Canopy算法进行初始聚类,然后利用这些类簇的中心点作为KMeans算法初始类簇中心点。
常用的层次聚类算法有BIRCH和ROCK,在此不作介绍,下面简单介绍一下Canopy算法,主要摘自Mahout的Wiki:
首先定义两个距离T1和T2,T1>T2.从初始的点的集合S中随机移除一个点P,然后对于还在S中的每个点I,计算该点I与点P的距离,如果距离小于T1,则将点I加入到点P所代表的Canopy中,如果距离小于T2,则将点I从集合S中移除,并将点I加入到点P所代表的Canopy中。迭代完一次之后,重新从集合S中随机选择一个点作为新的点P,然后重复执行以上步骤。
Canopy算法执行完毕后会得到很多Canopy,可以认为每个Canopy都是一个Cluster,与KMeans等硬划分算法不同,Canopy的聚类结果中每个点有可能属于多个Canopy。我们可以选择距离每个Canopy的中心点最近的那个数据点,或者直接选择每个Canopy的中心点作为KMeans的初始K个类簇中心点。

六、代码

1、K-means

import numpy as np 
import pandas as pd 
import matplotlib.pyplot as plt

class KMeans():

    def __init__(self, train_data, k_num_center):
    '''
    train_data 训练数据,格式为(m,n)
    k_num_center K值
    '''
        self.train_data = train_data
        self.K = k_num_center

    #定义函数计算欧氏距离,point为点的坐标,其维度为(p,)
    def get_euclidean_distance(self,point1, point2):
        return (np.sum(point1 - point2) ** 2) ** 0.5

    #定义函数返回所有样本点到聚类中心的欧氏距离
    def get_distances(self, train_data, crowds):
        all_distances = [] #保存所有样本点到所有聚类中心的欧式距离,其维度为(k,n)
        for i in range(len(crowds)):
            disances = [] #保存所有样本到一个聚类的欧式距离,其维度为(n,)
            for j in range(len(train_data)):
                distance = self.get_euclidean_distance(train_data[j], crowds[i])
                disances.append(distance)
            all_distances.append(disances)
        return all_distances

    def get_distances_sse(self, crowds, clsys):
        sse = 0.0 #保存所有样本点到所有聚类中心的欧式距离,其维度为(k,n)
        for i in range(len(self.train_data)):
            # sse += get_euclidean_distance(train_data[i], crowds[clsys[i]])        
            sse += float(self.get_euclidean_distance(self.train_data[i]
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值