K-means算法

25 篇文章 5 订阅

一、概念说明

K-means算法的主要目的是最小化点与它们各自的簇质心之间的距离之和。

现在让我们举个例子来了解K-means实际上是如何工作的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ko1aPoqw-1656136391346)(C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20220607201437055.png)]

我们有这8个点,我们想要应用K-means来为这些点划分簇。下面将演示我们是怎样做到的。

第一步:选择簇的数目k

K-means的第一步是选择簇的数目k。

第二步:从数据中选择k个随机点作为质心

接下来,我们为每个簇随机选择质心。假设我们想要有2个簇,所以k在这里等于2。然后我们随机选择质心:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XVrVMOuH-1656136391347)(C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20220607201515013.png)]

这里,红色和绿色圆圈代表这些簇的质心。

第三步:将所有点分配给到某个质心距离最近的簇

一旦我们初始化了质心,我们就将每个点分配给到某个质心距离最近的簇:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xyJyyfIp-1656136391348)(C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20220607201542588.png)]

在这里,你可以看到更接近红点的点被分配给红色簇,而更接近绿点的点被分配给绿色簇。

第四步:重新计算新形成的簇的质心

现在,一旦我们将所有点分配到任一簇中,下一步就是计算新形成的簇的质心:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zJnaSAid-1656136391349)(C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20220607201615419.png)]

在这里,红色和绿色叉号是新的质心。

第五步:重复第三步和第四步

计算质心并基于它们与质心的距离将所有点分配给簇的步骤是单次迭代。但我们什么时候应该停止这个过程?它不能永远运行下去对吧?

停止K-means聚类的标准

基本上有三种停止标准可用于停止K-means算法:

1、新形成的簇的质心不会改变

2、数据点保留在同一个簇中

3、达到最大迭代次数

如果新形成的簇的质心没有变化,我们就可以停止算法。即使在多次迭代之后,所有簇都还是相同的质心,我们可以说该算法没有学习任何新模式,并且它是停止训练的标志。

另一个明显的迹象表明,在多次迭代训练的之后,如果数据点仍然都在同一簇中,我们应该停止训练过程。

最后,如果达到最大迭代次数,我们可以停止训练。假设我们将迭代次数设置为100。在停止之前,该过程将重复100次迭代。

二、python代码实现
#定义函数:计算二维空间中两点的欧氏距离
def EuclideanDistance(x, y):
    return math.sqrt(math.pow(x[0]-y[0],2)+math.pow(x[1]-y[1],2))

#定义函数:计算一个DataFrame中点集的形心
def Centroid(df):
    Centroid_x = df['属性1'].mean()
    Centroid_y = df['属性2'].sum()/len(df)
    return [Centroid_x,Centroid_y]

#定义函数:以形心点组成的DF——’Centroid_group‘为基准,对于样本点集’df‘中的点进行聚类,并分别得到group_a/b/c三个新的点集,
#此为聚类后的三类
def Clustering(df,Centroid_group):
        group_a = np.zeros(shape = (1,2))
        group_b = np.zeros(shape = (1,2))
        group_c = np.zeros(shape = (1,2))
        for i in range(11):
            a = EuclideanDistance([df.iloc[i,0],df.iloc[i,1]],
                              [Centroid_group.iloc[0,0],Centroid_group.iloc[0,1]])
            b = EuclideanDistance([df.iloc[i,0],df.iloc[i,1]],
                              [Centroid_group.iloc[1,0],Centroid_group.iloc[1,1]])
            c = EuclideanDistance([df.iloc[i,0],df.iloc[i,1]],
                              [Centroid_group.iloc[2,0],Centroid_group.iloc[2,1]])
 
            if a == min(a,b,c):
                group_a = np.append(group_a, [[df.iloc[i,0], df.iloc[i,1]]], axis=0)
            elif b == min(a,b,c):
                group_b = np.append(group_b, [[df.iloc[i,0], df.iloc[i,1]]], axis=0)
            else:
                group_c = np.append(group_c, [[df.iloc[i,0], df.iloc[i,1]]], axis=0)   
        group_a = np.delete(group_a, 0, 0)
        group_b = np.delete(group_b, 0, 0)
        group_c = np.delete(group_c, 0, 0)
 
        a = pd.DataFrame(group_a,columns=['属性1','属性2'],dtype='float64')
        b = pd.DataFrame(group_b,columns=['属性1','属性2'],dtype='float64')
        c = pd.DataFrame(group_c,columns=['属性1','属性2'],dtype='float64')
        print('第一类为:')
        print(a)
        print('第二类为:')
        print(b)
        print('第三类为:')
        print(c)
        return a,b,c

#将初始点存入一个DF中
data = {'属性1':[8,6,1,7,1,4,3,5,7,4,5],
        '属性2':[9,8,5,0,1,7,7,5,2,8,6]}
frame = pd.DataFrame(data,index=['X1','X2','X3','X4','X5','x6','x7','x8','x9','x10','x11'])
print(frame) 

#指定作为第一次分类的初始形心集
Centroid_init = frame.iloc[0:3,:]
type(Centroid_init)
Centroid_init

Centroid_new = Centroid_init
i = 1
while i <= 300:
    print('————————————————————第' + str(i) + '次分类开始——————————————————————————')
    Centroid_new = pd.DataFrame(Centroid_new) #转换格式(由于意外报错)
    l = Clustering(frame,Centroid_new)
    Centroid_new = {'属性1':[Centroid(l[0])[0],Centroid(l[1])[0],Centroid(l[2])[0]],
            '属性2':[Centroid(l[0])[1],Centroid(l[1])[1],Centroid(l[2])[1]]}
    print('————————————————————第' + str(i) + '次分类结束——————————————————————————')
    print('新的形心集为:')
    print(pd.DataFrame(Centroid_new))#输出新的形心集
            #处理计数器
    i += 1
 

参考文献

[1]使用Python实现K-means
[2]你需要的最全面的K-means聚类指南

具体操作的推荐
[1]SPSS——聚类分析之K-均值聚类法
[2]如何在IBM SPSS Statistics中进行K均值聚类分析


学习用,如有侵权,请联系删除。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Q一件事

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值