K-means算法是一种常见的无监督学习算法,用于将一个数据集分成K个类别。K-means算法的基本思想是将数据集中的点分成K个类别,使得每个点到其所属类别的质心(即类别中心点)的距离最小。其中,K是事先设定的需要聚类的类别数目。
K-means算法的具体步骤如下:
1.从数据集中随机选取K个点作为初始聚类中心。
2.对于数据集中的每个点,计算其到K个聚类中心的距离,并将其归为距离最近的聚类中心所在的类别。
3. 对于每个聚类,重新计算其聚类中心点。
4. 重复步骤2-3,直到聚类中心点不再发生变化或达到最大迭代次数。
本次算法代码中的数据集我选用西瓜数据集,其中第一列表示西瓜的密度,第二列表示西瓜的含糖率,接下来我要用k-means聚类算法把这30个西瓜分为3类。
具体的python代码如下:
import operator
from numpy import *
import math
import matplotlib.pyplot as plt
melons = []
times = 0 # 最终迭代次数
maxTimes = 100 # 最大迭代次数
with open("./melons.txt", "r") as f:
for line in f.readlines():
line = line.strip('\n').split(' ') # 去掉列表中每一个元素的换行符
# 把文件中每行数据都转换为float类型,并存储到melons列表中
melons.append(list(map(float, line)))
species = [[], [], []] # 我把数据集中的西瓜分为3个类别
# 最开始分别把第5行、第15行和第25行西瓜数据单独划分为一类
species[0].append(melons[4])
species[1].append(melons[14])
species[2].append(melons[24])
dupli_speceis = [] # dupli_speceis用于存储每次更新前的西瓜分类数据,以判断西瓜种类数据是否不再变化
while operator.eq(species, dupli_speceis) == False and times < maxTimes:
times += 1 # 迭代次数+1
dupli_speceis = species
average = [[], [], []] # average列表用于记录每个类别的平均值
# 计算每个类别的平均值
for i in range(0, 3):
x = 0
y = 0
length = len(species[i])
for item in species[i]:
x += float(item[0])
y += float(item[1])
average[i].append(x / length)
average[i].append(y / length)
species = [[], [], []] # 先清空species中的数据,以方便更新
# 分别计算150个西瓜中每个西瓜与每个类别平均值之间的距离
for item in melons:
distance = []
for ave in average:
distance.append(
math.sqrt((float(item[0]) - ave[0])**2 + (float(item[1]) - ave[1])**2))
# 找出与三个类别平均值距离最小的那个类别
min = 0
if distance[min] > distance[1]:
min = 1
if distance[min] > distance[2]:
min = 2
species[min].append(item)
print('迭代次数为:', end=str(times)) # 输出迭代次数
print()
colors = ['red', 'green', 'blue']
# 绘制散点图
for i, col in zip(range(3), colors):
for melon in species[i]:
plt.scatter(melon[0], melon[1], color=col)
plt.show()
运行结果图如下:
终端显示结果为: