本文由来

看论文,定量与定性之间评价关系里经常有人用到云模型,看了后觉得,还真是给一个量化指标就能输出分类的确定度,python代码照着MATLAB写的,自从用了python后很少用MATLAB了,留下来省的以后用的时候再找MATLAB脚本了。

2018年写小论文期间,由于计算及绘图需要,写了本文代码,随后放到此博客,避免遗忘,且希望能帮到需要的人。代码并无任何创新,纯粹是云理论的python实现。2018至今,经过多位同学的咨询提问,本文代码得以逐步美化,在此表示感谢。

------------------------------------------------分割线------------------------------------------------------------------

头文件及基础配置

引入:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from time import time,clock

添加字段,以再matplotlib中显示中文字符 

plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.ion() # 关闭阻塞模式

------------------------------------------------分割线------------------------------------------------------------------

一维云模型
def plot_cloud_model(Ex, En, He, n, ax, label='', color = 'r',marker = 'o'):
    """该函数每次画1个云图

    Args:
        Ex (float): 期望
        En (float): 熵
        He (float): 超熵
        n (int): 云滴数量
        ax (Axes): 画布,云图将绘制到指定画布上
        label (str, optional): 云图名称,会显示在图例中,默认为空
        color (str, optional): 云图颜色,默认'r'代表红色
        marker (str, optional): 数据点显示符号,默认显示一个圆圈
    """    
    Y = np.zeros((1, n))
    np.random.seed(int(np.random.random()*100))
    X= np.random.normal(loc=En, scale=He, size=n)
    Y = Y[0]
    for i in range(n):
        np.random.seed(int(np.random.random()*100) + i + 1)
        Enn = X[i]
        X[i] = np.random.normal(loc=Ex, scale=np.abs(Enn), size=1)
        Y[i] = np.exp(-(X[i] - Ex) * (X[i] - Ex) / (2 * Enn * Enn))
    ax.scatter(X, Y, s=10, alpha=0.5, c=color, marker=marker, label=label)

执行:

if __name__ =='__main__': 
    fig = plt.figure(len(plt.get_fignums()))
    ax = fig.add_subplot(111) #创建画布,画布句柄为ax
    title = '设置你的标题'
    ax.set_title(title)#在ax指向的画布上绘图
    ax.set_xlabel('期望')
    ax.set_ylabel('隶属度')
    ax.grid(True)
    plot_cloud_model(1.5, 0.61, 0.1, 500, ax,'云图1','r','o')
    plot_cloud_model(2.0, 0.33, 0.1, 500, ax,'云图2','g','x')
    plot_cloud_model(-1, 0.8, 0.1, 500, ax,'云图3','b','*')
    ax.legend(loc='best')
    plt.show()
    plt.pause(3600)  # 延时关闭,以便开启多个绘图窗口,须在程序最后执行

结果:

python实现建模转化为点云 python云模型_云模型

------------------------------------------------分割线------------------------------------------------------------------ 

二维云模型
def plot_2d_cloud_model(Ex, En, He, n, ax, label='', color = 'r',marker = 'o'):
    """该函数每次画1个云图

    Args:
        Ex ([float,float]): 期望,二维数组
        En ([float,float]): 熵,二维数组
        He ([float,float]): 超熵,二维数组
        n (int): 云滴数量
        ax (Axes): 画布,必须为3d画布,云图将绘制到指定画布上
        label (str, optional): 云图名称,会显示在图例中,默认为空
        color (str, optional): 云图颜色,默认'r'代表红色
        marker (str, optional): 数据点显示符号,默认显示一个圆圈
    """  
    Y = np.zeros((1, n))
    np.random.seed(int(np.random.random()*100))
    X0 = np.random.normal(loc=En[0], scale=He[0], size=n)
    Y = Y[0]
    np.random.seed(int(np.random.random()*100)+1)
    X1 = np.random.normal(loc=En[1], scale=He[1], size=n)
    for i in range(n):
        Enn0 = X0[i]
        np.random.seed(int(np.random.random()*100)+i)
        X0[i] = np.random.normal(loc=Ex[0], scale=np.abs(Enn0), size=1)
        Enn1 = X1[i]
        np.random.seed(int(np.random.random()*100)+i+1)
        X1[i] = np.random.normal(loc=Ex[1], scale=np.abs(Enn1), size=1)
        Y[i] = np.exp(-(X0[i] - Ex[0]) * (X0[i] - Ex[0]) / (2 * Enn0 * Enn0)-(X1[i] - Ex[1]) * (X1[i] - Ex[1]) / (2 * Enn1 * Enn1))
    ax.scatter(X0, X1, Y, s=10, alpha=0.5, c=color, marker=marker,label=label)

执行:

if __name__ =='__main__': 
    fig_3d = plt.figure(len(plt.get_fignums()))
    fig_3d = fig_3d.add_subplot(111, projection='3d') #创建三维画布,画布句柄为ax_3d
    title = '设置你的标题'
    fig_3d.set_title(title)#在ax_3d指向的画布上绘图
    fig_3d.set_xlabel('期望1')
    fig_3d.set_ylabel('期望2')
    fig_3d.set_zlabel('隶属度')
    fig_3d.grid(True)
    plot_2d_cloud_model([1.5,2], [0.61,0.2], [0.1,0.1], 2000, fig_3d,'云图1','r','o')
    plot_2d_cloud_model([2.0,2.5], [0.33,0.5], [0.1,0.1], 2000, fig_3d,'云图2','g','x')
    plot_2d_cloud_model([-1,1], [0.8,0.1], [0.1,0.1], 2000, fig_3d,'云图3','b','*')
    fig_3d.legend(loc='best')
    plt.show()
    plt.pause(3600)  # 延时关闭,以便开启多个绘图窗口,须在程序最后执行

结果:

python实现建模转化为点云 python云模型_python_02


------------------------------------------------分割线------------------------------------------------------------------

二维可分割云模型
def plot_2d_trim_cloud_model(Ex, En, He, n, ax, trim_panel=[[1.5,0.5,0],[0.5,1.5,0],[0.5,1.5,1],1],label='', color = 'r',marker = 'o'):
    """该函数每次画1个云图

    Args:
        Ex ([float,float]): 期望,二维数组
        En ([float,float]): 熵,二维数组
        He ([float,float]): 超熵,二维数组
        n (int): 云滴数量
        ax (Axes): 画布,必须为3d画布,云图将绘制到指定画布上
        trim_panel:分割面,数组的前三个元素为分割面上的三个点,最后一位>0时筛选出分割面以上的点,<0时筛选出分割面以下的点
        label (str, optional): 云图名称,会显示在图例中,默认为空
        color (str, optional): 云图颜色,默认'r'代表红色
        marker (str, optional): 数据点显示符号,默认显示一个圆圈
    """      
    #确定分割panel的四个参数
    a=(trim_panel[1][1]-trim_panel[0][1])*(trim_panel[2][2]-trim_panel[0][2])-(trim_panel[1][2]-trim_panel[0][2])*(trim_panel[2][1]-trim_panel[0][1])
    b=(trim_panel[1][2]-trim_panel[0][2])*(trim_panel[2][0]-trim_panel[0][0])-(trim_panel[1][0]-trim_panel[0][0])*(trim_panel[2][2]-trim_panel[0][2])
    c=(trim_panel[1][0]-trim_panel[0][0])*(trim_panel[2][1]-trim_panel[0][1])-(trim_panel[1][1]-trim_panel[0][1])*(trim_panel[2][0]-trim_panel[0][0])
    d=-(a*trim_panel[0][0]+b*trim_panel[0][1]+c*trim_panel[0][2])

    Y = np.zeros((1, n))
    np.random.seed(int(np.random.random()*100))
    X0 = np.random.normal(loc=En[0], scale=He[0], size=n)
    Y = Y[0]
    np.random.seed(int(np.random.random()*100)+1)
    X1 = np.random.normal(loc=En[1], scale=He[1], size=n)
    for i in range(n):
        Enn0 = X0[i]
        np.random.seed(int(np.random.random()*100)+i)
        X0[i] = np.random.normal(loc=Ex[0], scale=np.abs(Enn0), size=1)
        Enn1 = X1[i]
        np.random.seed(int(np.random.random()*100)+i+1)
        X1[i] = np.random.normal(loc=Ex[1], scale=np.abs(Enn1), size=1)
        Y[i] = np.exp(-(X0[i] - Ex[0]) * (X0[i] - Ex[0]) / (2 * Enn0 * Enn0)-(X1[i] - Ex[1]) * (X1[i] - Ex[1]) / (2 * Enn1 * Enn1))

    #筛选出分割面一侧的点
    Selected_X0 = []
    Selected_X1 = []
    Selected_Y = []
    if(trim_panel[3]>0):
        for i in range(n):
            if((a*X0[i]+b*X1[i]+c*Y[i]+d)>=0):
                Selected_X0.append(X0[i])
                Selected_X1.append(X1[i])
                Selected_Y.append(Y[i])
    else:
        for i in range(n):
            if((a*X0[i]+b*X1[i]+c*Y[i]+d)<0):
                Selected_X0.append(X0[i])
                Selected_X1.append(X1[i])
                Selected_Y.append(Y[i])
    ax.scatter(Selected_X0, Selected_X1, Selected_Y, s=10, alpha=0.5, c=color, marker=marker,label=label)

执行:

if __name__ =='__main__': 
    fig_3d_trim = plt.figure(len(plt.get_fignums()))
    ax_3d_trim = fig_3d_trim.add_subplot(111, projection='3d') #创建三维画布,画布句柄为ax_3d
    title = '设置你的标题'
    ax_3d_trim.set_title(title)#在ax_3d指向的画布上绘图
    ax_3d_trim.set_xlabel('期望1')
    ax_3d_trim.set_ylabel('期望2')
    ax_3d_trim.set_zlabel('隶属度')
    ax_3d_trim.grid(True)
    trim_panel = [[2,2,0],[0.5,1.5,0],[0.5,1.5,1],1]#定义一个分割面
    plot_2d_trim_cloud_model([1.5,2], [0.61,0.2], [0.1,0.1], 2000, ax_3d_trim,trim_panel,'云图1','r','o')
    plot_2d_trim_cloud_model([2.0,2.5], [0.33,0.5], [0.1,0.1], 2000, ax_3d_trim,trim_panel,'云图2','g','x')
    plot_2d_trim_cloud_model([-1,1], [0.8,0.1], [0.1,0.1], 2000, ax_3d_trim,trim_panel,'云图3','b','*')
    ax_3d_trim.legend(loc='best')
    plt.show()
    plt.pause(3600)  # 延时关闭,以便开启多个绘图窗口,须在程序最后执行

结果:

python实现建模转化为点云 python云模型_确定度_03

------------------------------------------------分割线------------------------------------------------------------------

代码汇总
import numpy as np
import matplotlib.pyplot as plt
from time import perf_counter
plt.rcParams['font.sans-serif'] = ['SimHei']    #运行配置参数中的字体(font)为黑体(simHei)
plt.rcParams['axes.unicode_minus'] = False    #运行配置参数总的轴(axes)正常显示正负号(minus)
plt.ion() # 关闭阻塞模式

def plot_cloud_model(Ex, En, He, n, ax, label='', color = 'r',marker = 'o'):
    """该函数每次画1个云图

    Args:
        Ex (float): 期望
        En (float): 熵
        He (float): 超熵
        n (int): 云滴数量
        ax (Axes): 画布,云图将绘制到指定画布上
        label (str, optional): 云图名称,会显示在图例中,默认为空
        color (str, optional): 云图颜色,默认'r'代表红色
        marker (str, optional): 数据点显示符号,默认显示一个圆圈
    """    
    Y = np.zeros((1, n))
    np.random.seed(int(np.random.random()*100))
    X= np.random.normal(loc=En, scale=He, size=n)
    Y = Y[0]
    for i in range(n):
        np.random.seed(int(np.random.random()*100) + i + 1)
        Enn = X[i]
        X[i] = np.random.normal(loc=Ex, scale=np.abs(Enn), size=1)
        Y[i] = np.exp(-(X[i] - Ex) * (X[i] - Ex) / (2 * Enn * Enn))
    ax.scatter(X, Y, s=10, alpha=0.5, c=color, marker=marker, label=label)

def plot_2d_cloud_model(Ex, En, He, n, ax, label='', color = 'r',marker = 'o'):
    """该函数每次画1个云图

    Args:
        Ex ([float,float]): 期望,二维数组
        En ([float,float]): 熵,二维数组
        He ([float,float]): 超熵,二维数组
        n (int): 云滴数量
        ax (Axes): 画布,必须为3d画布,云图将绘制到指定画布上
        label (str, optional): 云图名称,会显示在图例中,默认为空
        color (str, optional): 云图颜色,默认'r'代表红色
        marker (str, optional): 数据点显示符号,默认显示一个圆圈
    """  
    Y = np.zeros((1, n))
    np.random.seed(int(np.random.random()*100))
    X0 = np.random.normal(loc=En[0], scale=He[0], size=n)
    Y = Y[0]
    np.random.seed(int(np.random.random()*100)+1)
    X1 = np.random.normal(loc=En[1], scale=He[1], size=n)
    for i in range(n):
        Enn0 = X0[i]
        np.random.seed(int(np.random.random()*100)+i)
        X0[i] = np.random.normal(loc=Ex[0], scale=np.abs(Enn0), size=1)
        Enn1 = X1[i]
        np.random.seed(int(np.random.random()*100)+i+1)
        X1[i] = np.random.normal(loc=Ex[1], scale=np.abs(Enn1), size=1)
        Y[i] = np.exp(-(X0[i] - Ex[0]) * (X0[i] - Ex[0]) / (2 * Enn0 * Enn0)-(X1[i] - Ex[1]) * (X1[i] - Ex[1]) / (2 * Enn1 * Enn1))
    ax.scatter(X0, X1, Y, s=10, alpha=0.5, c=color, marker=marker,label=label)

def plot_2d_trim_cloud_model(Ex, En, He, n, ax, trim_panel=[[1.5,0.5,0],[0.5,1.5,0],[0.5,1.5,1],1],label='', color = 'r',marker = 'o'):
    """该函数每次画1个云图

    Args:
        Ex ([float,float]): 期望,二维数组
        En ([float,float]): 熵,二维数组
        He ([float,float]): 超熵,二维数组
        n (int): 云滴数量
        ax (Axes): 画布,必须为3d画布,云图将绘制到指定画布上
        trim_panel:分割面,数组的前三个元素为分割面上的三个点,最后一位>0时筛选出分割面以上的点,<0时筛选出分割面以下的点
        label (str, optional): 云图名称,会显示在图例中,默认为空
        color (str, optional): 云图颜色,默认'r'代表红色
        marker (str, optional): 数据点显示符号,默认显示一个圆圈
    """      
    #确定分割panel的四个参数
    a=(trim_panel[1][1]-trim_panel[0][1])*(trim_panel[2][2]-trim_panel[0][2])-(trim_panel[1][2]-trim_panel[0][2])*(trim_panel[2][1]-trim_panel[0][1])
    b=(trim_panel[1][2]-trim_panel[0][2])*(trim_panel[2][0]-trim_panel[0][0])-(trim_panel[1][0]-trim_panel[0][0])*(trim_panel[2][2]-trim_panel[0][2])
    c=(trim_panel[1][0]-trim_panel[0][0])*(trim_panel[2][1]-trim_panel[0][1])-(trim_panel[1][1]-trim_panel[0][1])*(trim_panel[2][0]-trim_panel[0][0])
    d=-(a*trim_panel[0][0]+b*trim_panel[0][1]+c*trim_panel[0][2])

    Y = np.zeros((1, n))
    np.random.seed(int(np.random.random()*100))
    X0 = np.random.normal(loc=En[0], scale=He[0], size=n)
    Y = Y[0]
    np.random.seed(int(np.random.random()*100)+1)
    X1 = np.random.normal(loc=En[1], scale=He[1], size=n)
    for i in range(n):
        Enn0 = X0[i]
        np.random.seed(int(np.random.random()*100)+i)
        X0[i] = np.random.normal(loc=Ex[0], scale=np.abs(Enn0), size=1)
        Enn1 = X1[i]
        np.random.seed(int(np.random.random()*100)+i+1)
        X1[i] = np.random.normal(loc=Ex[1], scale=np.abs(Enn1), size=1)
        Y[i] = np.exp(-(X0[i] - Ex[0]) * (X0[i] - Ex[0]) / (2 * Enn0 * Enn0)-(X1[i] - Ex[1]) * (X1[i] - Ex[1]) / (2 * Enn1 * Enn1))

    #筛选出分割面一侧的点
    Selected_X0 = []
    Selected_X1 = []
    Selected_Y = []
    if(trim_panel[3]>0):
        for i in range(n):
            if((a*X0[i]+b*X1[i]+c*Y[i]+d)>=0):
                Selected_X0.append(X0[i])
                Selected_X1.append(X1[i])
                Selected_Y.append(Y[i])
    else:
        for i in range(n):
            if((a*X0[i]+b*X1[i]+c*Y[i]+d)<0):
                Selected_X0.append(X0[i])
                Selected_X1.append(X1[i])
                Selected_Y.append(Y[i])
    ax.scatter(Selected_X0, Selected_X1, Selected_Y, s=10, alpha=0.5, c=color, marker=marker,label=label)


if __name__ =='__main__': 
    # 画二维图
    fig = plt.figure(len(plt.get_fignums()))
    ax = fig.add_subplot(111) #创建画布,画布句柄为ax
    title = '设置你的标题'
    ax.set_title(title)#在ax指向的画布上绘图
    ax.set_xlabel('期望')
    ax.set_ylabel('隶属度')
    ax.grid(True)
    plot_cloud_model(1.5, 0.61, 0.1, 500, ax,'云图1','r','o')
    plot_cloud_model(2.0, 0.33, 0.1, 500, ax,'云图2','g','x')
    plot_cloud_model(-1, 0.8, 0.1, 500, ax,'云图3','b','*')
    ax.legend(loc='best')

    # 画三维图
    fig_3d = plt.figure(len(plt.get_fignums()))
    ax_3d = fig_3d.add_subplot(111, projection='3d') #创建三维画布,画布句柄为ax_3d
    title = '设置你的标题'
    ax_3d.set_title(title)#在ax_3d指向的画布上绘图
    ax_3d.set_xlabel('期望1')
    ax_3d.set_ylabel('期望2')
    ax_3d.set_zlabel('隶属度')
    ax_3d.grid(True)
    plot_2d_cloud_model([1.5,2], [0.61,0.2], [0.1,0.1], 2000, ax_3d,'云图1','r','o')
    plot_2d_cloud_model([2.0,2.5], [0.33,0.5], [0.1,0.1], 2000, ax_3d,'云图2','g','x')
    plot_2d_cloud_model([-1,1], [0.8,0.1], [0.1,0.1], 2000, ax_3d,'云图3','b','*')
    ax_3d.legend(loc='best')

    # 画带分割面的三维图
    fig_3d_trim = plt.figure(len(plt.get_fignums()))
    ax_3d_trim = fig_3d_trim.add_subplot(111, projection='3d') #创建三维画布,画布句柄为ax_3d
    title = '设置你的标题'
    ax_3d_trim.set_title(title)#在ax_3d指向的画布上绘图
    ax_3d_trim.set_xlabel('期望1')
    ax_3d_trim.set_ylabel('期望2')
    ax_3d_trim.set_zlabel('隶属度')
    ax_3d_trim.grid(True)
    trim_panel = [[2,2,0],[0.5,1.5,0],[0.5,1.5,1],1]#定义一个分割面
    plot_2d_trim_cloud_model([1.5,2], [0.61,0.2], [0.1,0.1], 2000, ax_3d_trim,trim_panel,'云图1','r','o')
    plot_2d_trim_cloud_model([2.0,2.5], [0.33,0.5], [0.1,0.1], 2000, ax_3d_trim,trim_panel,'云图2','g','x')
    plot_2d_trim_cloud_model([-1,1], [0.8,0.1], [0.1,0.1], 2000, ax_3d_trim,trim_panel,'云图3','b','*')
    ax_3d_trim.legend(loc='best')
    plt.show()
    plt.pause(3600)  # 延时关闭,以便开启多个绘图窗口,须在程序最后执行