数模学习(模糊数学篇)——模糊聚类(python实现)

目录

一、关于我想说的

二、第一篇——模糊聚类

例题1

        ① 数据阅读

        ② 聚类选择

        ③ python代码编写

        ④ 矩阵输入方法

三、动态聚类图



一、关于我想说的


        “此时笔者是某不知名211大学经管专业大二小辣鸡,在学习数学建模的过程中发现课本中大多数都使用的是matlab。首先得肯定matlab的功能之强大,但是作为一个小白真的实在是弄不懂matlab咋写,但结合学过(也可以说没学过)的python来完成一些数模分析是非常简单的。简单了解之后,笔者认为matlab的优势在于可以简单方便的实现函数的调用,但是python并不能在一个file中实现调用其他file中自己编写的函数(忽略有很多开源的库可以下载调用)但是这不意味着python在解决数模时会很复杂。笔者在学习数学建模时,根据一些例题编写了一些简单改动之后便可以实现运行的python程序,在此分享给大家,希望对大家的数模学习有一定的帮助。当然我才是大二小辣鸡,如果有什么错误也请大家予以斧正。

        大家一起学数模!我就是个小白还没摸清楚门道,和大家一起进步!”


二、第一篇——模糊聚类

例题1

数模学习(模糊数学篇)——模糊聚类(python实现)_第1张图片

        ① 数据阅读

        首先得明确这是一个面板数据,个体是国家与地区,时间是1996年、2000年和2006年。有两个变量:婴儿死亡率和出生时平均预期寿命。

        ② 聚类选择

        面板数据有两种聚类方式(自己的理解),第一个是对时间聚类,比如哪几年具有相似性因此予以聚类;第二个就是对地区进行聚类,比如哪几个地区的发展结果具有相似性便予以聚类。此处由于时序较少,仅有三年数据,个人认为没有必要去对时间进行聚类。而且有两个变量(这里不太清楚,是不是要分开聚类?) 所以选择对42个地区进行聚类。

        ③ python代码编写

        此处的python代码是转载然后修改之后并补上对各个λ截进行运算计算并输出的代码。由于找不到是转载的谁的(账号注销了),在CSDN中能够搜到的(侵删~)

第一步:下载numpy库:

        A.mac os 系统

         笔者运行环境是mac系统,只需要点电脑右上角的(搜索?放大器?)符号输入:终端,打开之后输入 pip3  install numpy(好像是这样的,可以在其他博客里面看看)即可

        B.Windows 系统

        打开菜单,cmd,重复上述操作就好啦(我也记不清了)        

第二步:python代码编写:

import numpy as np
np.set_printoptions(precision=2) # 设置矩阵输出精度,保留两位小数
def jmax(a):
    """
    数据标准化
    最大值规格化法
    """
    a=np.array(a)
    c=np.zeros_like(a,dtype=float)
    for j in range(c.shape[1]): # 遍历c的列
        for i in range(c.shape[0]): # 遍历c的列
            c[i,j]=a[i,j]/np.max(a[:,j])
    return c

def alike(a):
    """
    模糊相似矩阵
    最大最小法
    """
    a=jmax(a) # 用标准化后的数据
    c=np.zeros((a.shape[0],a.shape[0]),dtype=float)
    mmax=[]
    mmin=[]
    for i in range(c.shape[0]): # 遍历c的行
        for j in range(c.shape[0]): # 遍历c的行
            mmax.extend([np.fmax(a[i,:],a[j,:])]) # 取i和和j行的最大值,即求i行和j行的并
            mmin.extend([np.fmin(a[i,:],a[j,:])]) # 取i和和j行的最大值,即求i行和j行的交
    for i in range(len(mmax)):
        mmax[i]=np.sum(mmax[i]) # 求并的和
        mmin[i]=np.sum(mmin[i]) # 求交的和
    mmax=np.array(mmax).reshape(c.shape[0],c.shape[1]) # 变换为与c同型的矩阵
    mmin=np.array(mmin).reshape(c.shape[0],c.shape[1]) # 变换为与c同型的矩阵
    for i in range(c.shape[0]): # 遍历c的行
        for j in range(c.shape[1]): # 遍历c的列
                c[i,j]=mmin[i,j]/mmax[i,j] # 赋值相似度
    return c


def hecheng(a,b):
    """
    求模糊是矩阵a和模糊矩阵b的合成
    """
    a,b = np.array(a),np.array(b)
    c=np.zeros_like(a.dot(b))
    for i in range(a.shape[0]): # 遍历a的行元素
        for j in range(b.shape[1]): # 遍历b的列元素
            empty=[]
            for k in range(a.shape[1]):
                empty.append(min(a[i,k],b[k,j])) # 行列元素比小
            c[i,j]=max(empty) # 比小结果取大
    return c

def bibao(a):
    """
    求模糊矩阵a的闭包
    """
    a = alike(a) # 用模糊相似矩阵
    c=a
    while True:
        m=c
        c=hecheng(hecheng(a,c),hecheng(a,c))
        if (c==m).all(): # 闭包条件
            return np.around(c,decimals=2) # 返回传递闭包,四舍五入,保留两位小数
            break
        else:
            continue

def julei(a,g):
    a=bibao(a) # 用传递闭包
    c=np.zeros_like(a,dtype=int)
    for i in range(c.shape[0]):
        for j in range(c.shape[1]):
            if a[i,j]>=g:
                c[i,j]=1
            else:
                c[i,j]=0
    return c

def result(a,g):
    """
    模糊聚类分析结果展示
    """
    a = julei(a,g)
    c=[] # 同类聚合
    for i in range(len(a)):
        x=[]
        for j in range(i,len(a)):
            if a[i][j]==1:
                x.append(j)
            else:
                continue
        c.append(x)
    d=[] # 删除重复1
    for i in range(len(c)):
        for j in range(i+1,len(c)):
            for k in range(len(c[j])):
                if c[j][k] in c[i]:
                    d.append(c[j])
                    break
                else:
                    continue
    dd=[] # 删除重复2
    for i in range(len(d)):
        for j in range(i+1,len(d)):
            if d[i]==d[j]:
                dd.append(d[j])
    for i in range(len(dd)): # 删除重复3
        try:
            d.pop(d.index(dd[i]))
        except ValueError:
            continue
    for i in range(len(d)): # 删除重复4
        try:
            c.pop(c.index(d[i]))
        except ValueError:
            continue
    for i in range(len(dd)): # 删除重复5
        try:
            c.pop(c.index(dd[i]))
        except ValueError:
            continue
    for i in range(len(c)):
        for j in range(len(c[i])):
            c[i][j]+=1
    return c

def main():
    """
    测试代码
    """
    x=[[36.3,29.9,20.1,68.9,70.3,72],
        [95,66,51.6,54.8,61,63.7],
        [10,8,8,74.2,76.2,77.1],
        [84.5,78,64.8,54.9,56.5,58.9],
        [80,68,57.4,59.1,62.9,64.5],
        [60,36,26.4,61.7,65.8,68.2],
        [54,36,30,64.8,68.9,70.7],
        [10,5.6,4.2,76.6,79,80],
        [4.6,3.2,2.6,78.8,81.1,82.3],
        [50.5,37.1,25.8,68.3,65.5,66.2],
        [42,42,42,69.9,66.8,67],
        [8,5,4.5,71.3,75.9,78.5],
        [98,77,59,54.6,60.9,63.9],
        [16,11,9.8,70.3,72.6,74],
        [78.5,47.6,34.2,62.7,65.1,67.2],
        [91,78,74.4,59,60.1,61.6],
        [95,85,77.8,59.1,63,65.2],
        [41,30,24,65.6,69.6,71.4],
        [6.7,2.9,2.3,74.3,78.1,79.9],
        [25.6,16.1,11.2,71.2,73.6,75],
        [25.7,11.4,7.2,67,68.3,70.2],
        [38,23,14.6,64.8,69.1,70.8],
        [66.7,40,28.9,62.2,68.8,71],
        [45,50,56,61.9,48.5,50.7],
        [41.5,31.6,29.1,70.9,74,74.5],
        [9.4,6.9,6.5,75.2,77,77.8],
        [24.7,16.8,14.1,71.7,73.8,75],
        [48.1,26.9,18.6,66.6,70.4,72.1],
        [26.9,20.7,17.7,71.2,73.3,74.4],
        [10.9,4.1,3.2,71.4,75,76.5],
        [7.4,4.4,3.6,76.7,78.9,80.6],
        [7,4.4,3.7,75.2,77.9,79.1],
        [8.2,4.6,3.5,76.9,79.5,81.1],
        [7.2,4.6,4.2,76.9,78,79.7],
        [19.3,8.1,6,70.9,73.7,75.1],
        [22.7,20.2,13.7,68.9,65.3,65.6],
        [7.6,4.5,3.6,76.8,79,80.8],
        [67,37.5,23.7,66,70.4,71.5],
        [21.5,19.2,19.8,70.1,67.9,68],
        [8,5.6,4.9,75.9,77.7,79.1],
        [8,4.9,4.7,77,79.2,81],
        [8.3,5.9,5.2,75.4,78.6,79.9]]
    lambdas = np.sort(np.unique(bibao(x)).reshape(-1))[::-1]
    print(lambdas)
    lam_str = ''
    for (i,lam) in zip(range(len(lambdas)),lambdas):
        if i !=len(lambdas)-1:
            lam_str += str(lam)+' > '
        else:
            lam_str += str(lam)
    print('截集水平:'+lam_str)
    print("原始数据\n",np.array(x))
    print("\n数据标准化(最大值规格化法)\n",jmax(x))
    print("\n模糊相似矩阵(最大最小法)\n",alike(x))
    print("\n传递闭包\n",bibao(x))
    for i in range(0,len(lambdas)):
        g=lambdas[i]
        print("\n模糊聚类分析矩阵(lambda=%0.2f)\n"%g,julei(x,g))
        print("\n模糊聚类结果(lambda=%0.2f)\n"%g,result(x,g))
    
if __name__ == "__main__":
    main()
        

由于运行结果太长了,因此不在此处展示了。

 ④ 矩阵输入方法

        要注意输入矩阵的时候可以参考其他大佬博主打开file文件自动导入,但是笔者能力有限使用的是Excel,在数据较少的时候用这个也不难。只需要复制粘贴数据进入EXCEl(如果在一列中全部粘贴出来了可以:→数据→分列)

        然后可以利用:=“[”&A1&","..........","&D1&"]" 然后选中下拉、右拉啥的就可以在一列中生成所有行向量矩阵啦!

        然后一定要注意行列的选择,因为python似乎是不能对列进行索引的,一般都是需要行列转置,通过索引行来实现索引原先的列。这题是不需要的。

三、动态聚类图

        动态聚类图的画法笔者尚还没有学会,找代码也没有找到,如果大家知道怎么写的话可以分享一下!!!感谢大佬!!!

你可能感兴趣的:(python,矩阵,抽象代数,经验分享)