Python k-均值聚类算法一维实例

时间:2022-12-08 17:29:37

大家好,一直以来在CSDN上学了很多编程方面的知识,很感谢这个平台,感谢大家的无私分享,早就想为中文IT社区贡献一点自己的力量,正巧昨天看了一篇二维聚类的博客,关键算法的地方使用了一个函数,但是后面没有见到这个函数,琢磨了一下,一步步自己写吧,先写个一维的,没什么技术难度,就是一点点技巧。
k-均值聚类,是根据均值间的距离来进行聚类的,在算法实现时,
1、需要首先确定需要分几类,
2、然后给定各类别的均值,
3、再计算两个均值间的平均值,
4、根据该值进行聚类划分。
下面的代码是划分一维数组的聚类算法,因为使用的是随机数,效果不是特别理想,不过各类间的距离放开到30以上就比较理想了。当然,找规律是在有规律的情况下找,如果都是随机数,肯定没什么明显的规律。
Python 3.6.2

import time
import numpy as np
import random

def func00(): #生成随机数列表

#random.seed(1)
kjz1=[random.randint(1,50) for j in range(0,7000)]
kjz1.extend([random.randint(80,150) for j in range(0,8000)])
kjz1.extend([random.randint(200,300) for j in range(0,5000)])
kjz1.extend([random.randint(400,500) for j in range(0,8000)])
return kjz1

def func01(kjz1): #2分类

bj=1;kjz1=np.sort(kjz1)
while(True):
if bj==1:
kj=np.mean([kjz1[0],kjz1[len(kjz1)-1]]) #初始分组均值使用最小值和最大值的平均值
else:
k1=s1;k2=s2;
kj=np.mean([k1,k2]);
kjz2=[[],[]];
for j in kjz1:
if j<=kj:
kjz2[0].append(j)
else:
kjz2[1].append(j)
s1=np.mean(kjz2[0]);
s2=np.mean(kjz2[1]);
if bj==2:
if s1==k1 and s2==k2:
break
bj=2;
return kjz2

def func02(kjz1,k): #k个均值分k份

kjz1=np.sort(kjz1);#正序
wb2=kjz1.copy();
#初始均匀分组wb1
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);#初始分组均值

bj=1;
while(True):
wb2=kjz1.copy().tolist();
if bj!=1:
kj1=kj2.copy();

wb3=[];
for j in range(0,k-1):
wb3.append([])
for j in range(0,k-1):
i=-1;
while(True):
if wb2[i]<=kj1[j]:
wb3[j].append(wb2.pop(i));
else:
i=i+1;
if i>=len(wb2):
break
wb3.append(wb2)

kj2=means(wb3);#过程均值
if bj==2:
if kj1==kj2:
break
bj=2;
return wb3

def means(lb1): #计算均值

mean1=[];mean2=[];std1=[];
for j in lb1:
mean1.append(np.mean(j).tolist())
for j in range(1,len(mean1)):
mean2.append(np.mean([mean1[j-1],mean1[j]])) #分组均值使用各组的均值
print(mean2)
return mean2

if __name__=='__main__':

start=time.time();

kjz1=func00() #生成随机数列表

kjz2=func01(kjz1) #2分类
for j in kjz2:
print(len(j))

k=4;
kjz3=func02(kjz1,k) #k个均值分k份
for j in kjz3:
print(len(j))

print('Time used:',int((time.time()-start)/60*10)/10,'分钟')