机器学习实验
采用K均值算法对样本进行聚类
一、选取([3, 3], [6, 2], [8, 5])三个点作为初始聚类中心
1、源代码
import pandas as pd
import numpy as np
import scipy.io as scio
import matplotlib.pyplot as plt
if __name__ == '__main__':
data = scio.loadmat('ex7data2.mat')
D = data['X']
k=3
avg_vec=[[3, 3], [6, 2], [8, 5]] #均值向量
center=[[[3,3]],[[6,2]],[[8,5]]] #聚类中心点
for times in range(0,10):
C = []
for i in range(0, k):
C.append([])
for j in range(0,len(D)): #计算样本与均值向量的距离,加入距离最小的簇
min_d=0 #最短距离
min_sign=0 #簇标记
for i in range(0,k):
d= ((D[j][0] - avg_vec[i][0]) ** 2 + (D[j][1] - avg_vec[i][1]) ** 2) ** 0.5
if i==0:
min_d=d
min_sign=i
else:
if d<min_d:
min_d=d
min_sign=i
C[min_sign].append(D[j])
for i in range(0,k): #计算新均值向量
new_vec=[]
for j in range(0,2):
new_vec_value=0
for m in range(0,len(C[i])):
new_vec_value+=C[i][m][j]
new_vec_value/=len(C[i])
new_vec.append(new_vec_value)
for pos in range(0,2):
if new_vec[pos]!=avg_vec[i][pos]: #更新均值向量
avg_vec[i]=new_vec
center[i].append(new_vec) #记录每次迭代的聚类中心点
#画图
plt.title('EXP5', fontsize=20)
plt.xlabel('x', fontsize=10)
plt.ylabel('y', fontsize=10)
for i in range(0,k):
X=[]
Y=[]
for j in range(0,len(C[i])):
X.append(C[i][j][0])
Y.append(C[i][j][1])
if i==0:
plt.plot(X, Y, 'o', c='red', markersize=6)
elif i==1:
plt.plot(X, Y, 'o', c='green', markersize=6)
else:
plt.plot(X, Y, 'o', c='blue', markersize=6)
#画聚类中心点折线图
plt.plot([item[0] for item in center[i]],[item[1] for item in center[i]],c='black',marker='x')
plt.show()
2、实验结果
二、随机取初始聚类中心点
1、源代码
import pandas as pd
import numpy as np
import scipy.io as scio
import matplotlib.pyplot as plt
if __name__ == '__main__':
data = scio.loadmat('ex7data2.mat')
D = data['X']
k=3
avg_vec=[] #均值向量
for i in np.random.randint(0,len(D),k): #从D中随机选择k个样本作为初始均值向量
avg_vec.append(D[i])
while True:
C=[]
for i in range(0,k):
C.append([])
for j in range(0,len(D)): #计算样本与均值向量的距离,加入距离最小的簇
min_d=0 #最短距离
min_sign=0 #簇标记
for i in range(0,k):
d= ((D[j][0] - avg_vec[i][0]) ** 2 + (D[j][1] - avg_vec[i][1]) ** 2) ** 0.5
if i==0:
min_d=d
min_sign=i
else:
if d<min_d:
min_d=d
min_sign=i
C[min_sign].append(D[j])
change=False #判断均值向量是否更新
for i in range(0,k): #计算新均值向量
new_vec=[]
for j in range(0,2):
new_vec_value=0
for m in range(0,len(C[i])):
new_vec_value+=C[i][m][j]
new_vec_value/=len(C[i])
new_vec.append(new_vec_value)
for pos in range(0,2):
if new_vec[pos]!=avg_vec[i][pos]: #更新均值向量
avg_vec[i]=new_vec
change=True
if not change: #收敛,退出循环
break
#画图
plt.title('EXP5', fontsize=20)
plt.xlabel('x', fontsize=10)
plt.ylabel('y', fontsize=10)
for i in range(0,k):
X=[]
Y=[]
for j in range(0,len(C[i])):
X.append(C[i][j][0])
Y.append(C[i][j][1])
if i==0:
plt.plot(X, Y, 'o', c='blue', markersize=6)
elif i==1:
plt.plot(X, Y, 'o', c='red', markersize=6)
else:
plt.plot(X, Y, 'o', c='green', markersize=6)
for i in range(0, k): #画聚类中心点
plt.plot([avg_vec[i][0]],[avg_vec[i][1]],'x',c='black',markersize=15)
plt.show()