模糊动态聚类
聚类过程:
1.数据标准化(建立模糊矩阵),最大值标准化法,平移——极差变换
2.建立模糊相似矩阵
3.聚类(求动态聚类图)
模糊动态聚类主要用于非监督学习的聚类分析,假设样本数据为n*m维(共有n个样本,m个属性),可以使用模糊动态聚类的方法得出聚类结果。根据上述过程会得到不同lambd值对应的划分,对于不同的类别根据F—统计的大小得到最优的聚类结果。
python代码如下:
# -*- coding: utf-8 -*-
"""
Created on Tue Dec 5 10:55:07 2017
@author: mynumber
"""
import numpy as np
import pandas as pd
class CLUST(object):
"""模糊动态聚类
聚类过程:
1.数据标准化(建立模糊矩阵),最大值标准化法,平移——极差变换
2.建立模糊相似矩阵
3.聚类(求动态聚类图)
"""
def __init__(self,standard_choice='Max_standard',Maxlike_choice='MinMax'):
self.standard_choice=standard_choice
self.Maxlike_choice=Maxlike_choice
self.lambd=0
self.cluster=[] #对应的lambd值,及其对应的数据
self.best_lambd=[] #最优的lambd
self.F=[] #除去全部分为一类和全部分为两类的数据
def standard(self,data):
"""数据标准化"""
data_min,data_max=np.min(data,axis=0),np.max(data,axis=0)
numSamples,numShapes=np.shape(data)
delta_data=data_max-data_min
if self.standard_choice=='Max_standard':
for i in range(numSamples):
data[i,:]= (data[i,:] )/data_max
#将四舍五入保留两位数字
for i in range(numSamples):
for j in range(numShapes):
data[i,j]=round(float(data[i,j]),2)
return data
if self.standard_choice == 'std_standard':
for i in range(numSamples):
data[i,:]= (data[i,:]-data_min)/delta_data
#将四舍五入保留两位数字
for i in range(numSamples):
for j in range(numShapes):
data[i,j]=round(float(data[i,j]),2)
return data
def MatrixLike(self,data):
"""构造模糊相似矩阵"""
numSamples,numShapes=np.shape(data)
r=np.zeros((numSamples,numSamples))
for i in range(numSamples):
for j in range(numSamples):
r[i,j]=np.sum(self.Min(data[i,:],data[j,:]))/np.sum(self.Max(data[i,:],data[j,:]))
r[i,j]=round(r[i,j],2)
return r
def Max(self,a,b):
"""取最大值"""
a_or_b=[]
for (i,j) in zip(a,b):
if i>j:
a_or_b.append(i)
else:
a_or_b.append(j)
return a_or_b
def Min(self,a,b):
"""取最小值"""
a_and_b=[]
for (i,j) in zip(a,b):
if ielse:
a_and_b.append(j)
return a_and_b
def t_R(self,R):
"""计算传递闭包"""
numSamples,numShapes=np.shape(R)
T_R=np.zeros(np.shape(R))
for i in range(numSamples):
for j in range(numShapes):
T_R[i,j]=max(self.Min(R[i,:],R[j,:]))
return T_R
def judge(self,T1,T2):
"""判断T1,T2是否相同
相同返回1,不同返回0"""
flag=1
for i,j in zip(T1.flat,T2.flat):
if i!=j :
flag=0
break
return flag
def main(self,data):
"""程序调用"""
i=1
data=self.standard(data)
R=self.MatrixLike(data)
temp=self.t_R(R) #计算第一个传递闭包
flag=self.judge(temp,R)
while(flag!=1):
i+=1
temp_1=self.t_R(temp)
flag=self.judge(temp_1,temp)
temp=temp_1
T=temp
lambd=np.unique(T)
lambd_length=len(lambd)
for i in range(lambd_length):
temp={}
temp['lambd']=round(lambd[lambd_length-i-1],2)
temp['answer']=self.clust_T(T,lambd[lambd_length-i-1])
self.cluster.append(temp)
self.choise_lambd(data)
print("模糊聚类结果为:",self.cluster)
ind=self.F.index(max(self.F))
print("根据F统计,最佳聚类结果为:",self.cluster[ind+1]['answer'])
def clust_T(self,T,lam):
"""
根据给定的lambda,对数据进行划分
"""
answer= T>=lam
numI,numJ=answer.shape
xindex,yindex=[],[]
for i in range(numI):
for j in range(numJ):
if answer[i,j]==True:
xindex.append(i+1)
yindex.append(j+1)
num=list(np.unique(xindex))
total_clust=[]
for i in num:
temp=[]
for j,k in zip(xindex,yindex):
if i==j:
temp.append(k)
total_clust.append(temp)
if len(total_clust)==len(xindex):
return total_clust
else :
return np.unique((total_clust))#xindex,yindex
def data_mean(self,data,index):
"""计算每类的中心,flag=1表示data只有一组,否则含有多组"""
flag=len(index)
if flag==1:
return data
else :
return np.mean(data,axis=0)
def choise_lambd(self,data):
#根据F统计,选择最优的lambd值
n=np.shape(data)[0]
self.x_k=np.mean(data,axis=0)
length=len(self.cluster)
for choice in range(1,length-1): #针对每个选择
total_sum1=0 #计算F统计的分子值
total_sum2=0 #计算F统计的分母值
r=len(self.cluster[choice]['answer'])
for i in self.cluster[choice]['answer']: #针对每个选择的每个类别
i=[j-1 for j in i]
num1=np.sum(np.square(self.data_mean(data[i,:],i)-self.x_k))
total_sum1+=len(i)*num1
num2=0
for k in i:
num2+=np.sum(np.square(self.data_mean(data[i,:],i)-data[k,:]))
total_sum2+=num2
F1=total_sum1/(r-1)
F2=total_sum2/(n-r)
F=F1/F2
self.F.append(F)
xdata=np.array([[60.,10.,6.,2.],
[50.,1.,6.,4.],
[90.,6.,4.,6.],
[40.,5.,7.,3.],
[10.,1.,2.,4.]])
clu=CLUST()
clu.main(xdata)