import numpy as np
import matplotlib.pyplot as plt
def build_data():
"""
准备数据
:return:准备好的数据
"""
data_list = []
# 加载数据
with open("./test.txt") as f:
# 将所有的元素读成一个列表
lines = f.readlines()
# 循环对每一行元素进行单独处理
for line in lines:
# print(line)
# 去除line 前后的空白字符
line_obj = line.strip().split('\t')
# print(line_obj)
# print(type(line_obj))
# print("*"*20)
# 把 line_obj 里面的每一个元素 转化为float,追加到一列表中
data_list.append([float(line_obj[0]), float(line_obj[1])])
# 列表嵌套列表的数据 ,每一个列表元素是原来的每一行元素
# print(data_list)
# 将列表嵌套列表转化为二维数组
data_array = np.array(data_list)
# print(data_array)
# 将二维数组 转化为矩阵
data = np.mat(data_array)
# print(data)
# print(type(data))
return data
def center_init(data, k):
"""
初始化聚类中心
:param data: 所有的样本数据
:param k: 聚类的类别数目
:return: 聚类中心
"""
# 随机在 data中挑选4行 作为初始化的聚类中心
# 获取data 的列数
columns_num = data.shape[1]
# 获取data 的行数
index_num = data.shape[0]
# 先初始化一个全为0 的中心,然后,后续替换里面的值
center = np.zeros(shape=(k, columns_num))
# 每次初始化一个聚类中心,需要循环初始化k次
for i in range(k):
# 随机在80行里面选一个下标
# np.random.uniform() --->默认生成【0,1) 小数,可以更改最小值与最大值
r = int(np.random.uniform(0, index_num))
center[i, :] = data[r, :]
return center
def distance(v1, v2):
"""
计算点1 跟点2 的距离
:param v1: 点1
:param v2: 点2
:return: 距离
"""
dist = np.sqrt(np.sum(np.power((v1 - v2), 2)))
return dist
def k_means_owns(data, k):
"""
自实现聚类算法
:param data: 所有的样本数据
:param k: 聚类的类别数目
:return: 聚类中心 、每一个样本属于哪一类别
"""
# 获取data 的 行数
index_num = data.shape[0]
columns_num = data.shape[1]
# 1、初始化聚类中心
center = center_init(data, k)
# print(center)
# 需要将这个样本属于哪一类,而且距离也要保存起来吧
new_data = np.zeros(shape=(index_num,columns_num))
# 2、计算距离
# 每一个样本 都与每一个聚类中心进行计算距离
# 设置开关
flag = True
while flag:
flag = False # 关闭开关
for i in range(index_num):
min_dist = 10000000000
min_index = -1
# i 代表每一行的样本的下标
for j in range(k):
# 每一个样本需要 与每一个聚类中心进行计算距离
# 样本点data[i,:] 聚类中心center[j,:]
dist = distance(data[i,:],center[j,:])
if dist < min_dist :
min_dist = dist
min_index = j
if new_data[i,1] != min_index:
flag = True # 打开
new_data[i,:] = min_dist,min_index
# 调整聚类中心
for p in range(k):
# p 0 1 2 3
# 找出属于同一类别
p_clustor = data[new_data[:,1] == p,:]
# 计算这一类别的中心
# 先找出 这一类的簇第0 列的均值,与第1列的均值分别作为center 的行、列
center[p,:] = p_clustor[:,0].mean(),p_clustor[:,1].mean()
return new_data,center
def show_res(data,new_data,center):
"""
结果展示
:param data: 原始数据
:param new_data: 主要包含了聚类距离与最终类别的数据
:param center: 最终的聚类中心
:return: None
"""
# 1、创建画布
plt.figure()
# 2、绘图
# 获取原始数据的行数
index_num = data.shape[0]
#
colors = ['r','g','pink','y']
# 绘制散点图
# 一个点的绘制,需要给该点进行添加颜色
for i in range(index_num):
plt.scatter(data[i,0],data[i,1],c=colors[int(new_data[i,1])])
# 绘制聚类中心
#
plt.plot(center[:,0],center[:,1],'bx',markersize=12)
# print(center[:,0])
# print(center[:,1])
# 3、展示
plt.show()
def main():
"""
主函数
:return:
"""
# 1、构建数据
data = build_data()
# 2、进行自实现k-means
# 确定聚类的类别数目
k = 4
new_data, center = k_means_owns(data, k)
print(new_data)
print("*" * 80)
print(center)
# 3、结果展示
# 进行绘制结果图形展示
show_res(data,new_data,center)
if __name__ == '__main__':
main()