Python手撸机器学习系列(七):聚类(Kmeans)

聚类

聚类算法,一般情况下将给定的数据集划分为若干个不相交的子集,每个子集称为一个簇,即将数据集划分为几类。在这种情况下,可能会对一些潜在的概念进行划分,用周志华《机器学习》中的话来讲,聚类算法可能会将原本的西瓜数据集潜在地划分为浅色瓜、深色瓜、有籽瓜、无籽瓜等,虽然你原本将其分为好瓜和坏瓜。值得注意的是,这些概念对于聚类算法而言是事先未知的,即聚类算法会自动地把数据集划分为簇结构,每个簇的名称和含义需要使用者来命名和把握。

一、Kmeans聚类

1.1 原理

属于原型聚类的一种,较为简单给。定样本集 D = { x 1 , x 2 , . . . , x m } D=\{x_1,x_2,...,x_m\} D={x1,x2,...,xm},对于聚类,可以划分为簇 C = { C 1 , C 2 , . . , C k } C = \{C_1,C_2,..,C_k\} C={C1,C2,..,Ck},即将原数据划分为 k k k类,然后最小化平方误差:
E = ∑ i = 1 k ∑ x ∈ C i ∣ ∣ x − μ i ∣ ∣ 2 2 \large E =\displaystyle\sum_{i=1}^k\displaystyle\sum_{x\in C_i}||x-\mu_i||^2_2 E=i=1kxCixμi22
其中 μ i = 1 ∣ C i ∣ ∑ x ∈ C i x \large \mu_i=\frac{1}{|C_i|}\sum_{x\in C_i}x μi=Ci1xCix是簇 C i C_i Ci的均值向量

上述公式不好求解,一般我们通过迭代的方式近视化求解,大致过程如下:

  1. 从数据集 D D D中随机选取 k k k个样本作为 k k k个簇的初始均值(簇中心)
  2. 计算每个样本跟每个簇均值的距离,将样本放入距离最近的簇中
  3. 根据每个簇中的样本,重新计算每个簇的均值
  4. 判断,如果新的均值等于之前的均值,则停止迭代,否者以新均值继续循环2-3
  5. 查看最后结果绘图

即根据每个簇的均值不断构建新的簇来迭代,直到每个簇的均值不变为止。

1.2 代码实现

使用了周志华《机器学习》p202表9.1西瓜数据集4.0,已经处理成CSV格式,请自取:

https://pan.baidu.com/s/1ecLAbe_ZP75u1h7Ig9KVRw
提取码:c2sh

数据集预览(共计30条,此处略去):

请添加图片描述

代码实现:

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

data = pd.read_csv('xigua3.0.csv')
feature = ['密度','含糖率']
data = data[feature]

K = 3
#随机选取簇初始化
C_list = data.sample(K).values
data = data.values
while True:
    cur_cluster = [[] for _ in range(K)] #用于存储每个簇的元素
    for i in range(len(data)):
        choose = {} #字典形式存放每个元素对于每个簇的距离,以此来判断该放入哪个簇
        for j in range(K):
            diff = np.mean((data[i]-C_list[j])**2)
            choose[j] = diff
        choose = sorted(choose.items(),key=lambda kv:(kv[1],kv[0]))
        cur_cluster[choose[0][0]].append(data[i]) #将元素放入对应簇
    flag = True#用于判断是否结束循环

    #计算每个簇的均值并置为新的中心点,若均值与之前相等则结束循环
    for i in range(K):
        c = np.mean(cur_cluster[i],axis=0)
        for j in range(c.shape[0]):
            if c[j] != C_list[i][j]:
                flag = False
                C_list[i] = c
                break
    if flag:
        break

color = np.random.random((3,K)) #随机颜色

#得到最终的分类结果并绘图
for i in range(K):
    C = cur_cluster[i] #每一簇的元素
    x = [i[1] for i in C]
    y = [i[0] for i in C]
    plt.scatter(x,y,c = color[i],label = 'C'+str(i)) #随机颜色
plt.legend()
plt.xlabel('midu')
plt.ylabel('hantang')
plt.show()

最终结果:
注意,由于每次抽取的初始样本不同,所以每次运行的结果也不相同

请添加图片描述

注意,由于每次抽取的初始样本不同,所以每次运行的结果也不相同

如果有兴趣,可以自行存储每一个迭代过程的聚类情况绘图,这里不再赘述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

锌a

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

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

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

打赏作者

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

抵扣说明:

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

余额充值