Python实现简单k-means聚类

目录

1.导入原始数据集

 2.首次计算中心点

3.进行迭代循环,不断优化样本中心点和聚类结果

4.聚类可视化

通过手动书写k-means聚类算法的逻辑实现聚类(而非使用python内置的sklearn)

不了解k-means聚类算法的话可以先去了解以下这种算法的原理,下面就直接进入正题啦~


1.导入原始数据集

首先我们导入原始样本点,这里我们通过execl表记录原始数据,原始数据为假设为某班学术的平时成绩 和 期末成绩。原始数据如下图所示

import pandas as pd
import random
import math
import matplotlib.pyplot as plt

documentObject = pd.read_excel(r"C:\Users\DELL\Desktop\proData.xlsx")
documentLst = documentObject.values.tolist()
print(documentLst)

plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
for i in range(len(documentLst)):
    x = documentLst[i][0]
    y = documentLst[i][1]
    plt.scatter(x, y, s = 50)
    plt.xlabel('平时成绩')
    plt.ylabel('期末成绩')
plt.show()

除了导入原始样本数据以外,原始数据在坐标系中的散点图如下

 2.首次计算中心点

我们设置k值,以及最大迭代次数等初始变量

首次的样本中心点通过randint函数在所有样本点中随机选取,由于最后通过迭代聚类算法总能找到合适的样本中心点,所以首次的样本中心点选取可以随机选取

dataLength = len(documentLst)
#k为聚类中心点个数
k = 3
#iteraions为起始的迭代量
iterations = 0
#maxIteraions表示最大迭代次数
maxIteraions = 400
#centre用来保存中心点的坐标,随机出k个样本数据作为中心点
centre = []
for i in range(k):
    centre.append([0]*2)
for i in range(k):
    tempIndex = random.randint(0, dataLength - 1)
    centre[i][0] = documentLst[tempIndex][0]
    centre[i][1] = documentLst[tempIndex][1]
print(centre)
#disRecord用于记录每一个样本点里中心点的距离
disRecord = []
for i in range(dataLength):
    disRecord.append([0]*3)
#定义distance函数计算两点间距离
def distance(samples, centres):
    return math.sqrt((samples[0] - centres[0])**2 + (samples[1] - centres[1])**2)

finalClusters = []
for i in range(k):
    finalClusters.append([])

3.进行迭代循环,不断优化样本中心点和聚类结果

每一次迭代后新的样本中心点的坐标值取自于某一个类的所有样本点的坐标平均值

这里简单地将迭代终止条件为——最大迭代次数(这里只是为了简单所以才选择了400次迭代作为终止条件,并不是一定要以此为标准!),最后的聚类结果随着迭代次数增加而更加准确,也可以设置其他阈值为迭代停止条件!

#进行k-means主体
while iterations < maxIteraions:
    #用于记录新的k个样本中心点的坐标
    new_centres = []
    for i in range(k):
        new_centres.append([0]*2)
    # cluster用于记录聚类结果[[], [], []]
    clusters = []
    for i in range(k):
        clusters.append([])

    for i in range(dataLength):
        for j in range(k):
            disRecord[i][j] = distance(documentLst[i], centre[j])
    #将某一个样本点的坐标添加至cluster列表中
    for i in range(dataLength):
        index = disRecord[i].index(min(disRecord[i]))
        clusters[index].append(i)
        new_centres[index][0] += documentLst[i][0]
        new_centres[index][1] += documentLst[i][1]
    #创建用于迭代的中心点数组
    temp_centre = []
    for i in range(k):
        temp_centre.append([0]*2)
    for i in range(k):
        temp_centre[i][0] = (new_centres[i][0])/len(clusters[i])
        temp_centre[i][1] = (new_centres[i][1])/len(clusters[i])

    if(temp_centre == centre):
        break;
    else:
        centre = temp_centre
        iterations += 1
        finalClusters = clusters
print("聚类中心为:", centre)
print("分类情况为:", finalClusters)

4.聚类可视化

通过为不同聚类的样本点添加不同的颜色,从而能直观地在散点图中看到聚类结果

colors = ['red', 'yellow', 'aqua']
for i, j in zip(range(k), colors):
    for index in finalClusters[i]:
        plt.scatter(x = documentLst[index][0], y = documentLst[index][1], c=j)
plt.xlabel('平时成绩')
plt.ylabel('期末成绩')
plt.show()

 

物联沃分享整理
物联沃-IOTWORD物联网 » Python实现简单k-means聚类

发表评论