Kmeans的原理及简单实现

# 原理:

假设数据集合为(x1, x2, …, xn),并且每个样本xi为d维的向量,K-means聚类目标,在给定分类组数k(k ≤ n)值的条件下,将原始数据分成k类:
S = {S1, S2, …, Sk}
在数值模型上,即对以下表达式求最小值
在这里插入图片描述

#数学表达式:

数学表达式:

在这里插入图片描述

n:样本数。
k:样本分为k类。
rnk:第n个样本点是否属于第k类,属于则rnk=1, 不属于则rnk=0。
μK:第k个中心点。

# 算法的实现:

(1)随机选取K个对象作为初始聚类中心;
(2)将数据样本集合中的样本按照最小距离原则分配到最邻近聚类;
(3)根据聚类的结果,重新计算K个聚类的中心,并作为新的聚类中心;
(4)重复步骤2.3直到聚类中心不再变化。

# 代码的实现`

import pandas as pd
import numpy as np
import random
import matplotlib.pyplot  as plt
class Kmeans_clustering:
    def __init__(self,data,k):
        self.data=data
        self.k = k
    def distance(self,A,B):
        '''用欧式距离公式计算两个向量之间的距离'''
        return np.sqrt(sum(np.power(A-B,2)))
    def chioce_center(self):
        '''从数据集中随机选取k 个点作为聚类的中心'''
        centroids=random.sample(self.data,self.k)
        return centroids
    
    def k_means(self):
        '''将样本点,样本点距离聚点的最近距离,样本点的类型存放在DataFrame中
           然后进行迭代的过程,计算样本点到聚点的最近距离,判断属于哪一类
           重新计算每个类的质心
           直到所有的样本点的类型不发生变化
        
        '''
        df=pd.DataFrame(self.data)
        m=df.shape[1]
        df["min_distance"]=[0]*len(self.data)
        df["k类"]=[0]*len(self.data)
       
        centroids=self.chioce_center()
      
        K_changed=True
        while K_changed:
            K_changed = False
            list_k    = []#存放样本点的类型
            min_distance =[]#存放样本点到各个聚点的最小距离
            for j in range(len(self.data)):
                dis_list=[]#存放一个样本点到各个聚点的距离
                for i in range(self.k):
                    distance=self.distance(np.array(self.data[j]),np.array(centroids[i]))
                    dis_list.append(distance)
                min_distance.append(min(dis_list))
                list_k.append(dis_list.index(min(dis_list)))
                
            if list(df["k类"])!=list_k:
                K_changed=True
                df["min_distance"] = min_distance
                df["k类"] = list_k
            
            for i in range(self.k):#重新计算每个类的质心
                df1=df.groupby(df.columns[-1]).get_group(i)
                centroids[i]=[np.mean(df1.iloc[:,0]),np.mean(df1.iloc[:,1])]
        return df,centroids
                                   
data=[]
with open("text.txt","r",encoding="utf-8") as f:
    for line in f.readlines():
        line1 = line.strip().split()
        line2 = list(map(float,line1))
        data.append(line2)

a=Kmeans_clustering(data,4)
df,centroids=a.k_means()
print(df)
print(centroids)
for i in range(4):#将每个类的点显示出来
    df2=df.groupby(df.columns[-1]).get_group(i)
    plt.scatter(x=list(df2.iloc[:,0]),y=list(df2.iloc[:,1]))
    

结果:
0 1 min_distance k类
0 1.658985 4.285136 2.758587 1
1 -3.453687 3.424321 0.993410 2
2 4.838138 -1.151539 3.634463 1
3 -5.379713 -3.362104 1.251393 0
4 0.972564 2.924086 2.015117 1
5 -3.567919 1.531611 1.654707 2
6 0.450614 -3.302219 0.330917 3
7 -3.487105 -1.724432 1.251393 0
8 2.668759 1.594842 0.140032 1
9 -3.156485 3.191137 0.618302 2
10 3.165506 -3.999838 2.530735 3
11 -2.786837 -3.099354 1.737939 0
12 4.208187 2.984927 2.108910 1
13 -2.123337 2.943366 0.498210 2
14 0.704199 -0.479481 2.840816 1
15 -0.392370 -3.963704 1.147769 3
16 2.831667 1.574018 0.295199 1
17 -0.790153 3.343144 1.884279 2
18 2.943496 -3.357075 2.275142 3
[[-3.884551666666667, -2.7286300000000003], [2.554642714285714, 1.6759984285714287], [-2.6183161999999998, 2.8867158], [1.5418115000000001, -3.655709]]
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值