编程语言
首页 > 编程语言> > python不确定性计算之模糊动态聚类实验

python不确定性计算之模糊动态聚类实验

作者:互联网

模糊动态聚类实验

本实验所采用的模糊聚类分析方法是基于模糊关系上的模糊聚类法,也称为系统聚类分析法,可分为三步:
第一步:数据标准化,建立模糊矩阵
第二步:建立模糊相似矩阵
第三步:聚类

本程序读取Excel文件,再由程序读入,在数据标准化中采用了最大值规格法,然后通过夹角余弦法或最大最小法构造模糊相似矩阵,然后按lambda截集进行动态聚类,聚类完成后,采用Xie-Beni指标和F统计指标两种方式进行评判,选出最优聚类和lambda的最优取值。
代码如下:

# -*- coding: utf-8 -*-
import numpy as np
import pprint
import xlrd #读取Excel的扩展工具
from copy import deepcopy
import warnings
#矩阵不用科学计数法的显示方式
np.set_printoptions(suppress=True)

def main():
    path = 'data.xlsx'
    # 0.读取数据
    matrix = read_excel(path)
    # 1.数据标准化
    #k = 2
        
    while( k != 1 and k != 2 and k !=3 ):
        print('请输入标准化方法:\n1.平移-标准差变换\n2.平移-极差变换\n3.最大值规格法')
        k = eval(input())    
    
    x_matrix = std_matrix(matrix,k)
    print(x_matrix)
    # 2.构造模糊相似矩阵
    k = -1
    while( k != 1 and k != 2 ):
        print('请输入构造模糊相似矩阵方法:\n1.夹角余弦法\n2.最大最小法')
        k = eval(input())    
    if( k == 1 ):
        r_matrix = get_rmatrix1(x_matrix)
    else:
        r_matrix = get_rmatrix2(x_matrix)
    #print('===============标准化特征指标矩阵=============',x_matrix)
    #print('==================模糊相似矩阵R================',r_matrix)
    # 3.求传递闭包t(R)
    i = 0
    while True:
        t_r_matrix = get_tR(r_matrix)
        if (t_r_matrix == r_matrix).all():#每个元素都相等
            break
        else:
            r_matrix = t_r_matrix
            i = i + 1
    # 4.按lambda截集进行动态聚类
    result = lambda_clustering(t_r_matrix)
    warnings.filterwarnings("ignore")#因为存在除0情况,需忽略警告

    # 5.利用Xie_beni指数或F统计寻找最优分类
    k = -1
    while( k != 1 and k != 2 ):
        print('请输入评判Lambda取值的标准:\n1.Xie-Beni指标\n2.F统计指标')
        k = eval(input())    
    if( k == 1 ):
        Xie_Beni(result,x_matrix)
    else:
        F_Statistics(result,x_matrix)

# 1.标准化:
def std_matrix(x_matrix,k):
    x = deepcopy(x_matrix)
    #获得特征指标矩阵x的行列数
    x_rows = x.shape[0]#读取矩阵第一维度的长度,即行数
    x_cols = x.shape[1]#读取矩阵第二维度的长度,即列数
    x_mean = np.mean(x,axis = 0)#均值
    x_std = np.std(x,axis = 0)#标准差
    #numerical python
    for i in range(x_rows):
        for j in range(x_cols):
            if(k == 1):
                x[i][j] = (x[i][j] - x_mean[j])/x_std[j]#平移-标准差变换(消除量纲)            
            elif(k == 2):
                x[i][j] = ( x[i][j] - min(x[i]) ) / ( max(x[i]) - min(x[i]) )#平移-极差变换
            else:    
                x[i][j] = round(x[i][j] / max(x_matrix.T[j]),2)#标准化:最大值规格法
    return x


# 2.构造模糊相似矩阵:采用夹角余弦法
def get_rmatrix1(x_matrix):
    x_rows = x_matrix.shape[0]#读取矩阵第一维度的长度,即行数
    x_cols = x_matrix.shape[1]#读取矩阵第二维度的长度,即列数
    # norm_matrix :每一行的2-范式值
    norm_matrix = np.linalg.norm(x_matrix,axis = 1)
    # r_matrix : 模糊相似矩阵
    r_matrix = np.zeros((x_rows,x_rows),dtype = 'float')#初值为零矩阵
    # 获得模糊相似接矩阵行列数
    r_rows = r_matrix.shape[0]
    r_cols = r_matrix.shape[1]
    for i in range(r_rows):
        for j in range(r_cols):
            #multi_matrix = x_matrix[i] * x_matrix[j]
            r_matrix[i][j] = abs(np.dot(x_matrix[i],x_matrix[j])) / (norm_matrix[i] * norm_matrix[j])#矩阵相乘,再除以2范式之积
    return r_matrix

# 2.构造模糊相似矩阵:采用最大最小法
def get_rmatrix2(x_matrix):
    # r_matrix : 模糊相似矩阵
    r_matrix = np.zeros((x_matrix.shape[0],x_matrix.shape[0]),dtype = 'float')
    for i in range(0,x_matrix.shape[0]):
        for j in range(0,x_matrix.shape[0]):
            max_sum = 0
            min_sum = 0
            for k in range(x_matrix.shape[1]):
                max_sum = max_sum + max(x_matrix[i][k], x_matrix[j][k])
                min_sum = min_sum + min(x_matrix[i][k], x_matrix[j][k])
            r_matrix[i][j] = round(min_sum / max_sum , 2)#最小值之和除以最大值之和
    return r_matrix


# 3.平方法求传递闭包t(R)
def get_tR(r_matrix):
    rows = r_matrix.shape[0]#读取矩阵第一维度的长度,即行数
    cols = r_matrix.shape[1]#读取矩阵第二维度的长度,即列数
    min_list = []
    new_mat = np.zeros((rows,cols),dtype = 'float')
    for m in range(rows):
        for n in range(cols):
            min_list = []
            now_row = r_matrix[m]
            for k in range(len(now_row)):
                #先取小,再取大
                min_cell = min(r_matrix[m][k],r_matrix[:,n][k])#先取小
                min_list.append(min_cell)
            new_mat[m][n] = max(min_list)#再取大
    return new_mat


def lambda_clustering(final_matrix):
    rows = final_matrix.shape[0]#读取矩阵第一维度的长度,即行数
    cols = final_matrix.shape[1]#读取矩阵第二维度的长度,即列数
    result = [] #返回的结果
    global lambda_list
    lambda_list = []  #所有的lambda值
    temp_matrix = np.zeros((rows,cols),dtype = 'float')
    global temp_class_all
    temp_class_all = []

    for i in range(0,rows):
        for j in range(0,cols):
            lambda_list.append(final_matrix[i][j])#提取各个特征值到lambda_list

    #print(final_matrix)
    lambda_list = list(set(lambda_list))#去重
    lambda_list.sort()

    #通过循环,逐个计算lambda值的分类情况
    for i in range(len(lambda_list)):
        temp_matrix = np.zeros((rows,cols),dtype = 'float')
        class_list = []  #分类情况
        mark_list = [] #存储当前lambda值已经被分组的样本
        for m in range(rows):
            for n in range(cols):
                if final_matrix[m][n] >= lambda_list[i]:
                    temp_matrix[m][n] = 1 #大于lambda则赋值为1
        #对某个lambda值进行分类
        for m in range(rows):
            if (m+1) in mark_list:
                continue
            now_class = [] #当前分类情况
            now_class.append(m+1)
            mark_list.append(m+1)
            for n in range(m+1,rows):
                if (temp_matrix[m] == temp_matrix[n]).all() :
                    #进行分类
                    now_class.append(n+1)#每个小的分类表
                    #print(now_class)
                    mark_list.append(n+1) #存储当前lambda值,已经被分组的样本
            class_list.append(now_class) #分类完成           
        global temp_class 
        temp_class = class_list
        result.append(['matrix:',temp_matrix,'lambda:',lambda_list[i],'class',temp_class])  
        temp_class_all.append(temp_class)
    return result

# 5.利用Xie_beni指标寻找最优分类
def Xie_Beni(final_matrix,x_matrix):
    class_num = 0    #当前总类数
    class_list = []  #当前分类情况
    rate = float('inf') #Xie_Beni指数
    flag = 0 #标记Xie_Beni指数最大的分类情况
    i = 0
    for temp in final_matrix:
        this_in_measure = 0    #当前分类的类内紧密度,类中各点与类中心的距离平方和
        this_out_measure = float('inf')   #当前分类的类间分离度,最小的类与类中心的平方
        class_list = temp_class_all[i]
        class_num = len(class_list)
        means_list = [np.zeros((1,x_matrix.shape[1]),dtype = 'float')]*class_num #该分类下,每一类的均值
        #遍历每一类
        for i in range(class_num):
            #求每一类的类中心
            this_class_num = len(class_list[i])
            this_sum = np.zeros((1,x_matrix.shape[1]),dtype = 'float')
            this_means = np.zeros((1,x_matrix.shape[1]),dtype = 'float')
            for j in range(this_class_num):
                this_sum += x_matrix[class_list[i][j]-1]
            this_means = this_sum / this_class_num
            means_list[i] = this_means

        #计算当前分类类间分离度
        for m in range(len(means_list)):
            if len(means_list) == 1:
                this_out_measure = 0 #当所有样本分为一类的时候,类间分离度为无穷大,但这样的分类没有任何意义,所以置0,不予以比较。
                break
            for n in range(m+1,len(means_list)):
                temp = np.linalg.norm(means_list[m] - means_list[n])#计算向量欧氏距离
                if temp < this_out_measure:
                    this_out_measure = temp

        #计算当前分类类内紧密度
        for m in range(class_num):
            this_class_num = len(class_list[i])
            for n in range(this_class_num):
                add = np.linalg.norm(means_list[m] - np.array([x_matrix[n-1]]))#计算向量欧氏距离
                this_in_measure = this_in_measure + add

        this_rate = this_in_measure /  this_out_measure# 类内距离 ÷ 类间距离

        print('lambda =',round(lambda_list[i],2))
        print("Xie_Beni指数为%.2f"%this_rate)
        print('当前分类为',class_list)
        print("================================================")
        if (this_rate < rate):
            rate = this_rate
            flag = class_list
            best_lambda = lambda_list[i]
            min_num = this_rate
        i = i + 1
    
    print("****************最优分类结果如下****************")
    print('lambda的最优取值为 %.2f'%best_lambda)
    print('Xie_Beni指数最小值为%.2f'%min_num)
    print('最优分类为',flag)
    
# 5.利用 F统计指标
def F_Statistics(results, standard_matrix):
    #定义变量F 为F统计量数值    #定义class_class变量为类与类之间的距离  F的分子#    定义class_sample变量为类内样品间的距离  F的分母
    temp_F = []
    k = 0
    #print('temp_class_all:',temp_class_all)
    for result in results:
        mean_all = np.mean(standard_matrix, axis=0)#计算矩阵所有样品属性的平均值
        sorts = temp_class_all
        class_class = 0
        class_sample = 0

        #对于每个分类
        for sort in sorts:
            sort = sort[0]
            sort = [i-1 for i in sort]#将分类转化 [4, 9, 10]-->[3, 8, 9]因为矩阵下标从零开始
            # print(standard_matrix[sort])
            mean_j = np.mean(standard_matrix[sort], axis=0)#计算矩阵第j类样品的平均值

            #类间距离
            xj_av_reduce_xall_av = (np.sum((np.square(mean_j - mean_all)), axis=0))**(1/2) #第j类样品的平均值 - 所有样品属性的平均值
            class_class = class_class + (len(sort) * xj_av_reduce_xall_av**2)
            
            #计算类class_sample 为类内样品间的距离
            sum_xij_reduce_xj_av = 0#用来储存这个类中所有样品的xij_reduce_xj_av值
            for s in sort:#求每一个样品的xij_reduce_xj_av,对所有属性
                xij_reduce_xj_av = (np.sum(np.square((standard_matrix[s] - mean_j)), axis=0))**(1/2) #计算x(i,j) - 第j类样品的平均值 
                sum_xij_reduce_xj_av = sum_xij_reduce_xj_av + (xij_reduce_xj_av**2)
            class_sample = class_sample + sum_xij_reduce_xj_av #类内样品间的距离

        F = (class_class / (len(sorts[k])-1)) / (class_sample / (standard_matrix.shape[0] - len(sorts[k]))) #类间距离 ÷ 类内距离

        if(F == float('inf')):
            #当所有样本分为一类的时候,类间分离度为无穷大,但这样的分类没有任何意义,所以置0,不予以比较。
            F = 0
        F = round(F,2)
        temp_F.append(F)

        print('lambda =',round(lambda_list[k],2))
        print('F统计量为',F)
        print('当前分类结果',temp_class_all[k])    
        print("================================================")
        k = k + 1

    print("****************最优分类结果如下****************")
    print('lambda的最优取值为 %.2f'%lambda_list[np.argmax(temp_F)])
    print('F统计量最大值为%.2f'%max(temp_F))
    print('最优分类为',temp_class_all[np.argmax(temp_F)])#取F最大时候的下标

# 7.读取excel目录
def read_excel(path):
    #打开exel
    workbook = xlrd.open_workbook(path,'r') 
    #获得sheet1名字
    sheet1 = workbook.sheets()[0] 
    rows = sheet1.nrows
    cols = sheet1.ncols
    #建立特征指标矩阵
    x_matrix = np.zeros((rows-1,cols-1),dtype = 'float')
    #第一行是列名,从第二行开始
    for i in range(0,rows-1):
        #第一列是序号,从第二列开始
        for j in range(0,cols-1):
            x_matrix[i][j]= sheet1.cell(i+1,j+1).value
    return x_matrix

if __name__ == '__main__':
    main()

测试表格如下:
在这里插入图片描述

标签:matrix,temp,python,模糊,list,聚类,print,class,lambda
来源: https://www.cnblogs.com/chengjunkai/p/16362136.html