模糊动态聚类之python实现

模糊动态聚类

聚类过程:
 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)

你可能感兴趣的:(love_python,python,数据)