import numpy as np
import matplotlib.pyplot as plt
# 要进行聚类, 得有样本
# 加载样本数据
data = []
with open('test.txt', 'r') as f:
lines = f.readlines()
# print(lines)
for line in lines:
line_obj = line.strip().split('\t')
# 进行去除空格和\t,返回line_obj列表
# print(line_obj)
# str类型 ---》float类型,在以类表的形式存储到data里面
data.append([float(line_obj[0]), float(line_obj[1])])
# 列表嵌套列表形式
# print(data)
# 将二维数组转化成矩阵
data = np.mat(data) # data为矩阵数据
# print(data)
# print(type(data))
# 确定聚为几类
k = 4 # 聚为4类
def distance(v1, v2):
"""
计算点与点之间的距离
:param v1: 点1
:param v2: 点2
:return: 点与点之间的距离
"""
# np.power(v1-v2,2)
# 对于两个点进行距离的计算,可以使用power()
# np.power(np.array([1,2]-np.array([2,3],2)))
# np.sqrt() 开平方
dist = np.sqrt(np.sum(np.power(v1-v2, 2)))
return dist
def center_init(data, K):
"""
初始化聚类中心
:param data: 原始矩阵数据
:param K: 聚类数量
:return: 聚类中心
"""
# 获取data列数
col_num = data.shape[1]
index_num = data.shape[0]
# 先初始化一个center,然后全部元素为0, 后面替换元素就可以了
# 形状为(4,2)的二维数组
center = np.zeros((k, col_num))
# print(center)
# 循环初始化聚类中心
for i in range(k):
# pass
# np.random.uniform() -->随机初始化一个小数
r = int(np.random.uniform(0, index_num))
center[i, :] = data[r, :]
# print(center)
return center
def k_means(data, k):
"""
自实现k-means聚类
:param data: 原始矩阵数据
:param k: 聚类数量
:return:
"""
# 初始化聚类中心, 调用center_init初始化
center = center_init(data, k)
# 计算点与各个聚类中心的相似度 --》距离的计算
# 循环计算
# 获取data行数、列数
index_num = data.shape[0] # 80
col_num = data.shape[1] # 2
# 进行初始化一个数组, 保存80个点距离聚类中心的距离,和是哪个中心的距离
# [min_dist,min_index]
new_data = np.zeros([index_num, col_num])
flag = True
while flag:
flag = False
for i in range(index_num): # 循环80次 每次进行距离聚类中心计算
min_index = -1
# 每一个点要与聚类中心进行距离计算,计算4次
min_dist = 10000
for j in range(k):
dist = distance(data[i, :], center[j, :])
# 拿到距离之后 --》进行点到距离中心的比对
# 设置一个最小距离, 拿到点与每一个聚类中心的距离之后,
# 与最小距离进行比对,如果小于最小距离,赋值给最小距离,
# 经过四次,那么点与这四个聚类中心的最小距离就是min_dist
# 最小距离获取到了
if dist < min_dist:
min_dist = dist
min_index = j #0,1,2,3
# --> 属于哪一个聚类中心的点
# 需要把每一个点的min_dist,min_index保存起来
if new_data[i, 1] != min_index:
flag = True
new_data[i, :] = min_dist, min_index # 循环80次,那里面存的就是
# 聚类中心调整
for p in range(k):
# 确定同一类别的所有数据
point_clu = data[np.where(new_data[:, 1] == p)[0]]
# print(point_clu,type(point_clu))
# print("----------------------------------")
# 对这群里的点进行求取均值
center[p, :] = np.mean(point_clu, axis=0)
return new_data, center
def show_res(data, new_data, k , center):
"""
图形绘制
:param data: 原矩阵
:param new_data: 保存着属于哪一类的数据
:param k: 聚类中心个数
:param center: 聚类中心
:return: none
"""
# 创建画布
plt.figure()
# 获取data的行数
index_num = data.shape[0]
# print(index_num)
color = ['r', 'g', 'b', 'y']
colors = []
for i in range(index_num):
# print(new_data[i, 1])
colors.append(color[int(new_data[i, 1])])
# print(colors)
# 准备循环 --》散点图
for i in range(index_num):
# x,y --->对应的点进行绘制
# print("index",data[i,0])
# print("value",data[i,1])
plt.scatter(data[i, 0], data[i, 1], c=colors[i])
# 绘制聚类中心
plt.plot(center[:, 0], center[:, 1], 'bx', markersize=12)
plt.show()
new_data, center = k_means(data, k)
show_res(data, new_data, k, center)
k-means算法
最新推荐文章于 2024-06-25 13:31:56 发布