k-均值聚类算法二维实例,不多解释,解释就是掩饰,复制粘贴即可运行。
import time
import numpy as np
import random
import matplotlib.pyplot as plt
import operator
def func01(): #生成二维随机点
#random.seed(1)
kjz1=[[random.randint(50,100),random.randint(50,100)] for j in range(0,200)]
kjz1.extend([[random.randint(150,200),random.randint(150,200)] for j in range(0,200)])
kjz1.extend([[random.randint(60,110),random.randint(150,200)] for j in range(0,200)])
kjz1.extend([[random.randint(130,180),random.randint(50,100)] for j in range(0,200)])
kjz1.extend([[random.randint(150,200),random.randint(250,300)] for j in range(0,200)])
kjz1.extend([[random.randint(60,110),random.randint(250,300)] for j in range(0,200)])
return kjz1
def func02(kjz2w): #绘图
if kjz2w!=[]:
colors=['b','g','r','c','m','y','k'];s=0;
for j in kjz2w:
for i in j:
plt.plot(i[0], i[1], color=colors[s%len(colors)], marker='.')
s=s+1;
plt.ion();plt.show();plt.pause(5);plt.close();
def func03(kjz1,k): #计算初始均值,并返回初始分组
minxy=np.min(kjz1,axis=0).tolist();maxxy=np.max(kjz1,axis=0).tolist();
xjg=(maxxy[0]-minxy[0])/k;yjg=(maxxy[1]-minxy[1])/k;
meanxy=[];meanxy.append([minxy[0],minxy[1]]);meanxy.append([maxxy[0],maxxy[1]]);
for j in range(1,k-1):
meanxy.append([minxy[0]+xjg*j,minxy[1]+yjg*j])
kjz2wxy2=[[] for j in range(0,len(meanxy))];
for j in kjz1:
s=0;lslb=[];
for k in meanxy:
lslb.append([s,(j[0]-k[0])**2+(j[1]-k[1])**2]);s=s+1; #一个坐标一组
lslb.sort(reverse=False,key=operator.itemgetter(1)) #正序
kjz2wxy2[lslb[0][0]].append(j)
return kjz2wxy2
def func05(lb2): #剔除空列表
j=0;
while(True):
if len(lb2[j])<=0:
lb2.pop(j)
else:
j=j+1;
if j>=len(lb2):
break
return lb2
def func06(kjz2wxy): #求组合中心(均值)
meanxy=[];
for j in kjz2wxy:
meanxy.append(np.mean(j,axis=0).tolist())
kjz2wxy2=[[] for j in range(0,len(meanxy))];
for j in kjz2wxy:
for i in j: #点
s=0;lslb=[];
for k in meanxy:
lslb.append([s,(i[0]-k[0])**2+(i[1]-k[1])**2]);s=s+1;
lslb.sort(reverse=False,key=operator.itemgetter(1)) #正序
kjz2wxy2[lslb[0][0]].append(i)
kjz2wxy2=func05(kjz2wxy2)
return kjz2wxy2,meanxy
def func07(kjz2w,fz):
kjz2wxy=func03(kjz2w,fz) #坐标列表,分组,0-按照x轴均分
j=0;
while(True):
kjz2wxy,meanxy=func06(kjz2wxy)
if j>0 and meanxy==meanxy2:
break
meanxy2=meanxy.copy();
j=j+1;
print('迭代%d次' % (j))
func02(kjz2wxy) #绘图
if __name__=='__main__':
start=time.time();
for j in range(0,10):
kjz2w=func01()
func07(kjz2w,6) #分6组
print('Time used:',int((time.time()-start)/60*10)/10,'分钟')
上图是初始均值选取比较好的时候的情况,还有些情况是下面这样的。
今天还写了一种画蛇添足的算法,从一维算法过度来的,就像下面这样的。
import time
import numpy as np
import random
import matplotlib.pyplot as plt
import operator
def func01(): #生成二维随机点
random.seed(1)
kjz1=[[random.randint(50,100),random.randint(50,100)] for j in range(0,200)]
kjz1.extend([[random.randint(150,200),random.randint(150,200)] for j in range(0,200)])
kjz1.extend([[random.randint(60,110),random.randint(150,200)] for j in range(0,200)])
kjz1.extend([[random.randint(130,180),random.randint(50,100)] for j in range(0,200)])
kjz1.extend([[random.randint(150,200),random.randint(250,300)] for j in range(0,200)])
kjz1.extend([[random.randint(60,110),random.randint(250,300)] for j in range(0,200)])
#绘图
plt.xlabel('x-axis')
plt.ylabel('y-axis')
for j in kjz1:
plt.plot(j[0], j[1], color='b', marker='.', label='y1 data')
plt.ion();plt.show();plt.pause(1);plt.close();
return kjz1
def func02(kjz1,k,axis): #k个均值分k份
kjz1.sort(reverse=False,key=operator.itemgetter(1-axis)) #正序
kjz1.sort(reverse=False,key=operator.itemgetter(axis)) #正序
wb2=kjz1.copy();
#初始均匀分组
xlb=[];a=round(len(wb2)/k);b=len(wb2)%k;
for j in range(1,k+1):
xlb.append(j*a)
if j==k:
xlb[j-1]=xlb[j-1]+b;
j=0;wb1=[];
for j in range(0,k):
wb1.append([])
i=0;j=0;
while(i<=len(wb2)-1):
wb1[j].append(wb2[i]);
if i>=xlb[j]-1:
j=j+1;
i=i+1;
kj1=means(wb1,axis);#初始分组均值
bj=1;
while(True):
wb2=kjz1.copy();
if bj!=1:
kj1=kj2.copy();
wb3=[];
for j in range(0,k-1):
wb3.append([])
for j in range(0,k-1):
i=0;
while(True):
if wb2[i][axis]<=kj1[j]:
wb3[j].append(wb2.pop(i));
else:
i=i+1;
if i>=len(wb2):
break
wb3.append(wb2)
for j in wb3:
if len(j)<=0:
print('分组出现空组,返回[]');return []
kj2=means(wb3,axis);#过程均值
if bj==2:
if kj1==kj2:
break
bj=2;
return wb3
def means(lb1,axis): #计算均值
mean1=[];mean2=[];std1=[];
for j in lb1:
mean1.append(np.mean(j,axis=0).tolist())
for j in range(1,len(mean1)):
mean2.append(np.mean([mean1[j-1][axis],mean1[j][axis]])) #分组均值使用各组的均值
return mean2
def func03(kjz2w): #绘图
if kjz2w!=[]:
colors=['b','g','r','c','m','y','k'];s=0;
for j in kjz2w:
for i in j:
plt.plot(i[0], i[1], color=colors[s%len(colors)], marker='.', label='y1 data')
s=s+1;
plt.ion();plt.show();plt.pause(3);plt.close();
def func04(kjz2wx,kjz2wy): #x,y 组整合
kjz2wxy=[[] for j in range(0,len(kjz2wx)*len(kjz2wy))];k=0;
for j in kjz2wx:
for i in kjz2wy:
for a in j:
if a in i:
kjz2wxy[k].append(a);
k=k+1;
kjz2wxy=func05(kjz2wxy)
return kjz2wxy
def func05(lb2): #组合迭代
j=0;
while(True):
if len(lb2[j])<=0:
lb2.pop(j)
else:
j=j+1;
if j>=len(lb2):
break
return lb2
def func06(kjz2wxy): #组合迭代
#求组合中心(均值)
meanxy=[];
for j in kjz2wxy:
meanxy.append(np.mean(j,axis=0).tolist())
kjz2wxy2=[[] for j in range(0,len(meanxy))];
for j in kjz2wxy:
for i in j: #点
s=0;lslb=[];
for k in meanxy:
lslb.append([s,(i[0]-k[0])**2+(i[1]-k[1])**2]);s=s+1;
lslb.sort(reverse=False,key=operator.itemgetter(1)) #正序
kjz2wxy2[lslb[0][0]].append(i)
kjz2wxy2=func05(kjz2wxy2)
return kjz2wxy2,meanxy
def func07(kjz2w):
kjz2wx=func02(kjz2w,2,0) #列表,分组数,x轴0,y轴1
func03(kjz2wx) #绘图
kjz2wy=func02(kjz2w,3,1)
func03(kjz2wy) #绘图
kjz2wxy=func04(kjz2wx,kjz2wy)
func03(kjz2wxy) #绘图
#kjz2wxy=func06(kjz2wxy)
j=0;
while(True):
kjz2wxy,meanxy=func06(kjz2wxy)
if j>0 and meanxy==meanxy2:
break
meanxy2=meanxy.copy();
j=j+1;
print('迭代%d次' % (j))
func03(kjz2wxy) #绘图
if __name__=='__main__':
start=time.time();
kjz2w=func01()
func07(kjz2w)
print('Time used:',int((time.time()-start)/60*10)/10,'分钟')