Pyhton实现K-Means算法(numpy+pandas+matplotlib)

5 篇文章 0 订阅

摘要:使用Python实现K-Means算法

一、K-Means算法基本流程

1)随机选取K个聚类中心

2)计算每个样本到聚类中心的距离

3)更新样本聚类中心

4)迭代,直到样本聚类中心不再发生变化

二、详细步骤

1.导入训练集数据,并做些许处理,方便之后的使用,因为原始数据是两列,列名分别为AB,所以使用data['A'].values和data['B'].values来获取文件中的具体数值。

# 导入数据集,文件名为testSet.csv
data = pd.read_csv('testSet.csv')

# 将文件中数据转换为数组
f1 = data['A'].values
f2 = data['B'].values
X = np.array(list(zip(f1, f2)))

2.由簇数确定初始质心的个数,然后把随机生成的质心画到图上,数据集的数据用黑色点表示,质心用蓝色“×”表示,如图1所示。

#设置簇数,根据簇数确定生成初始质心的个数
k = 4
#随机获取初始质心并画到示例数据上
C_x = np.random.randint(0, np.max(X)-2, size=k)
C_y = np.random.randint(0, np.max(X)-2, size=k)
C = np.array(list(zip(C_x, C_y)), dtype=np.float32)
plt.scatter(f1, f2, c='black', s=7)
plt.scatter(C_x, C_y, marker='x', s=100, c='b')

 图1 生成初始质心的效果

3. 通过计算欧几里得距离,不断对质心进行迭代,直到质心间距离不再发生变化,那么就进行迭代的终止,此时的质心间距离指的是:上次迭代完的质心与本次迭代完的质心之间的距离。倘若迭代结果一直在改变,那么我们就通过设置最大迭代次数来终止迭代,次数根据具体要求可进行改变。下面仅列出前两次循环的结果,作为参考示例。

while tmp <= 15 and newDist.any() != 0:

注:此处判断迭代结果是否一样,主要是比较迭代前后的两次质心位置有没有改变,辅助以计算质心距离和(簇内各点到该簇质心的距离的和) ,但实际上应该是使用质心距离和差异来判断,即判断迭代前后两次的质心距离和是否改变,如果读者有精力,可以自己再琢磨琢磨。

三、详细代码

import numpy as np
import pandas as pd
from copy import deepcopy
from matplotlib import pyplot as plt

# 导入数据集
data = pd.read_csv('testSet.csv')

# 将文件中数据转换为数组
f1 = data['A'].values
f2 = data['B'].values
X = np.array(list(zip(f1, f2)))

# 计算两个坐标点之间的距离,采用欧几里得法
def dist(a, b,ax=1):
    c=a-b
    dist=np.sum(np.power(c,2),axis=ax)
    return np.sqrt(dist)

#设置簇数
k = 4

# 随机获得中心点的X轴坐标
C_x = np.random.randint(0, np.max(X)-2, size=k)
# 随机获得中心点的Y轴坐标
C_y = np.random.randint(0, np.max(X)-2, size=k)
C = np.array(list(zip(C_x, C_y)), dtype=np.float32)

# 将初始化中心点画到输入的样例数据上
plt.scatter(f1, f2, c='black', s=7)
plt.scatter(C_x, C_y, marker='x', s=100, c='b')

# 用于保存中心点更新前的坐标
C_old = np.zeros(C.shape)
print('C:',C)
# 用于保存数据所属中心点
clusters = np.zeros(len(X))
#设置迭代标识位
newDist = dist(C, C_old, 1)
tmp = 1
while tmp <= 15 and newDist.any() != 0:
    
    # 循环计算出每个点对应的最近中心点
    for i in range(len(X)):
        # 计算出每个点与中心点的距离
        distances = dist(X[i], C, 1)
        # 记录0 - k-1个点中距离近的点
        cluster = np.argmin(distances) 
        # 记录每个样例点与哪个中心点距离最近
        clusters[i] = cluster 
        
    # 采用深拷贝将当前的中心点保存下来
    C_old = deepcopy(C)
    
    # 从属于中心点放到一个数组中,然后按照列的方向取平均值
    for i in range(k):
        points = [X[j] for j in range(len(X)) if clusters[j] == i]
        C[i] = np.mean(points, axis=0)
        
    colors = ['b', 'g', 'r', 'y', 'c', 'm']
    #建立一个fig和axis对象
    fig, ax = plt.subplots()
    # 不同的子集使用不同的颜色
    for i in range(k):
        points = np.array([X[j] for j in range(len(X)) if clusters[j] == i])
        ax.scatter(points[:, 0], points[:, 1], s=15, c=colors[i])
    ax.scatter(C[:, 0], C[:, 1], marker='x', s=100, c='black')
    plt.show()
    print ('第%d次循环' % tmp)
    tmp = tmp + 1
    # 迭代标识位,计算新旧质心的的距离
    newDist = dist(C, C_old, 1)
    print("新旧质心间的距离:",newDist)
    print("质心距离和:")
    for i in range(k): 
        p = C[i]
        poin = [X[j] for j in range(len(X)) if clusters[j] == i]
        e=0
        for x in poin:
            d = dist(x, p, 0)
            e += d
        print(e)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值