您的位置:首页 > 编程语言 > Python开发

模糊Kmeans

2015-12-04 17:36 731 查看

模糊Kmeans

基本思想:首先设定一些类及每个样本对各类的隶属度; 然后通过迭代,不断调整聚类中心和隶属度至收敛。收敛条件是隶属度的变化量小于规定的阈值。

 

算法实现步骤:

 

1.给定样本个数X(个数N),类数K,迭代收敛常数e。

2.给定或随机生成隶属度U,U[i][j]表示第j个元素对第i类的隶属度。

3.计算各类的聚类中心Zj

 

  

i=1,2........K;j=1,2......N;m>=2

 

 

4.计算新的隶属度矩阵U

 

   

  i=1,2........K;j=1,2......N;m>=2
    

 

 

5.判断是否满足收敛条件

 

  收敛条件:


当算法收敛时聚类结束,否则返回第三步

 

6根据最终迭代的隶属度结果进行分类。

 

  

 j=1,2......N  

 

 

时间复杂度:O(tK2mn)

空间复杂度:O((m+K)n+Km)

 

 

 

程序运行结果图:



Python实现

注:此程序需要引入一些外部开源库,详细内容请参照网上教程,此处省略;sample.txt和membership.txt中的数据由MATLAB随机生成一定格式数据。

import math #导入math模块
import matplotlib.pyplot as plt #导入画图库

W=2; #样本坐标维度(本程序只考虑二维坐标中的数据点)
N=180; #样本数量
K=3; #类数
M=2; #控制模糊程度的参数
E=0.0001 #达到收敛时最小误差

#从sample.txt中读入样本坐标
X = []
for i in open("sample.txt"):
row = [float(x) for x in i.split()]
if len(row):
X.append(row)

#聚类中心
Z=[ [0 for i in range(W) ] for j in range(K) ]

#计算乘方
def pow(a,b):
return a**b

#计算距离
def dis(x1,y1,x2,y2):
return math.sqrt((x1-x2)**2+(y1-y2)**2)

#更新聚类中心和隶属度
def membership(U):
#生成二维列表,K行N列
UL=[ [ 0.0 for i in range(N)] for j in range(K)]
#求聚类中心Z
for i in range(0,K,1):
s1=s2=s3=0.0
for j in range(0,N,1):
s1+=pow(U[i][j],M)*X[j][0]
s2+=pow(U[i][j],M)*X[j][1]
s3+=pow(U[i][j],M)
Z[i][0]=s1/s3
Z[i][1]=s2/s3

#求新的隶属度
for i in range(0,K,1):
for j in range(0,N,1):
s=0.0
d=dis(Z[i][0],Z[i][1],X[j][0],X[j][1])
if d==0:
UL[i][j]=1
else:
for k in range(0,K,1):
d1=dis(Z[k][0],Z[k][1],X[j][0],X[j][1])
s+=pow(d/d1,2/(M-1))
UL[i][j]=1/s
return UL

#计算新旧隶属度最大差值
def MAX_error(U,UL):
max=0.0
for i in range(0,K,1):
for j in range(0,N,1):
t=abs(UL[i][j]-U[i][j])
if max<t:
max=t
return max

#画图函数,显示结果
def showMap(UL):
#定义点的颜色,这里只定义四种,即最大为四类
mark1 = ['or', 'ob', 'og', 'ok']
mark2 = ['Dr', 'Db', 'Dg', 'Dk']
#定义横纵坐标的范围
for i in range(0,N,1):
max=0.0
index=0
#找出每个点对K个类的隶属度中最高的那个,并归为那一类
for j in range(0,K,1):
if UL[j][i]>max:
max=UL[j][i]
index=j
plt.plot(X[i][0],X[i][1],mark1[index])
#显示聚类中心
for i in range(0,K,1):
plt.plot(Z[i][0],Z[i][1],mark2[i])
plt.xlim(-5.0,20.0)
plt.ylim(-6.0,14.0)
plt.show()

#主函数
def main():
#从membership.txt文件中导入初始化的隶属度
U = []
for i in open("membership.txt"):
row = [float(x) for x in i.split()]
if len(row):
U.append(row)

#归一化
s=[0.0 for i in range(N)] #初始化每列的和
for i in range(0,K,1):
for j in range(0,N,1):
s[j]+=U[i][j]
for i in range(0,K,1):
for j in range(0,N,1):
U[i][j]=U[i][j]/s[j]

UL=membership(U)
err=MAX_error(U,UL)

#进行迭代,直到隶属度的最大差值小于常数E
whil
4000
e(err>E):
U=UL
UL=membership(U)
err=MAX_error(U,UL)

#绘图
showMap(UL)

#__name__作为模块的内置属性,就是.py文件的调用方式。.py文件有两种使用方式:作为模块被调用和
#直接使用。如果它等于"__main__"就表示是直接执行。 在if __name__ == "__main__":之后的
#语句作为模块被调用的时候,语句之后的代码不执行;直接使用的时候,语句之后的代码执行。
if __name__ == '__main__':
main()
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Python