所有文章 > AI驱动 > 基于熵权法的TOPSIS模型

基于熵权法的TOPSIS模型

前言

TOPSIS(Technique for Order Preference by Similarity to Ideal Solution)是一种多准则决策分析方法,用于在多个方案之间进行排序。而熵权法是一种用于确定指标权重的方法,它考虑了指标之间的相关性。将这两种方法结合起来,就形成了基于熵权法的TOPSIS模型

实施基于熵权法的TOPSIS模型的一般步骤:

  1. 确定决策矩阵: 收集相关的决策信息,形成一个决策矩阵。该矩阵的行代表各个决策方案,列代表不同的决策指标。
  2. 数据正向化对于极小型指标、中间性指标、区间型指标,正向化处理的目的是将其转换为越大越好的形式,数据正向化处理在TOPSIS模型前的应用旨在提高决策分析的准确性和可解释性,确保不同类型的指标能够在相同的度量尺度上进行比较,为最终的综合排序提供更有意义的结果。
  3. 数据标准化: 对决策矩阵进行标准化,确保所有指标具有相同的度量单位。这可以通过将每个元素除以其列的总和来实现,以确保每个指标在[0, 1]的范围内。
  4. 确定指标权重: 使用熵权法确定每个指标的权重。熵权法考虑了指标的信息熵,指标熵越大,权重越小。计算每个指标的熵,然后计算相对熵,最后得到指标的权重。
  5. 构造加权决策矩阵: 将每个标准化后的元素乘以其对应的权重,得到加权决策矩阵。
  6. 确定正理想解和负理想解: 对于每个指标,确定最大值和最小值,分别构成正理想解和负理想解。
  7. 计算方案与正理想解的相似度和负理想解的相似度: 使用某种距离度量(通常是欧氏距离)计算每个决策方案与正理想解和负理想解的距离。
  8. 计算综合得分: 对于每个决策方案,计算其相对于正理想解和负理想解的综合得分。通常,综合得分越高,排名越靠前。
  9. 排序: 根据计算的综合得分对决策方案进行排序,得出最终的排序结果。

TOPSIS模型的基本数学公式:

  1. 正理想解(PIS):对于每个决策指标  ,正理想解的值 () 是所有方案中该指标的最大值  
  2. 负理想解(NIS)计算每个方案与正理想解和负理想解的距离。通常使用欧氏距离(Euclidean Distance)或其他距离度量    其中  是方案  与正理想解的距离,  是方案  与负理想的距离
  3. 相似度得分:根据方案与正理想解和负理想解的距离,计算相似度得分  其中  是方案  的相似度得分,该得分越接近1表示方案越优
  4. 综合得分:根据相似度得分对方案进行排名。综合得分越高,排名越靠前

熵权法基本数学公式:

  1. 信息熵(Entropy):对于决策指标  ,计算其信息熵的公式如下:  其中,  是第  个方案在第  个指标上的取值,  是决策方案数量
  2. 信息熵向量:将各个指标的信息熵组成一个向量,即熵向量  其中,  是决策指标的数量
  3. 信息熵权重:计算每个指标的信息熵权重,即各个指标在整体信息熵中的贡献比例。  其中  表示第  个指标的信息熵权重,  是决策指标的数量
  4. 最终权重调整:最终,可以对信息熵权重进行归一化处理,确保它们的和为1  这里  是最终的指标权重

通过计算各个指标的信息熵,然后将信息熵转化为指标权重。

代码实现

import pandas as pd
data = pd.read_excel('水质数据.xlsx')
print(data.shape) # 数据维度
print(data.isnull().sum()) # 返回缺失值数量
data.head()

数据集为某四个水池(各15周)水质指标数据,其中总磷、COD(mg/l)、总氮、氨氮为极小型数据,PH为区间型数据(范围为[6,9])。

# 原始数据正向化
def func_1(x):
return(x.max()-x) # 极小型
def func_2(x,x_best):
M = (abs(x-x_best)).max()
return(1-abs(x-x_best)/M) # 中间性
def func_3(x,a,b):
M = max(a-min(x), max(x)-b)
y = []
for i in x:
if i < a:
y.append(1-(a-i)/M)
elif i > b:
y.append(1-(i-b)/M)
else:
y.append(1)
return(y) # 区间型

定义三个函数,函数用于进行原始数据的正向化处理。

func_1(x):

  • 类型: 极小型
  • 功能: 该函数对输入的数据向量  进行极小型的正向化处理。
  • 实现: 对每个元素,计算它与该列的最大值的差,从而将较大的原始值转换为较小的正向化值。
  • 公式:  

func_2(x, x_best):

  • 类型: 中间性
  • 功能: 该函数对输入的数据向量  进行中间性的正向化处理,考虑了相对于某个“最佳”解的相对距离。
  • 实现: 计算每个元素与对应元素在  中的差的绝对值,并对这些差异进行归一化,以保留相对距离信息。
  • 公式:  

func_3(x, a, b):

  • 类型: 区间型
  • 功能: 该函数对输入的数据向量x进行区间型的正向化处理,将元素分别考虑在给定范围内和范围之外的情况。
  • 实现: 对于每个元素,根据它与给定范围  的关系,进行不同的正向化处理,使得在范围内的元素被正向化为1,而在范围之外的元素根据其离开范围的距离进行正向化。
  • 公式:  

              如果  则正向化为                如果  则正向化为  

              如果  则正向化为  

data['总磷'] = func_1(data['总磷']) # 极小型
data['总氮'] = func_1(data['总氮']) # 极小型
data['COD(mg/l)'] = func_1(data['COD(mg/l)']) # 极小型
data['氨氮'] = func_1(data['氨氮']) # 极小型
data['PH'] = func_3(data['PH'], 6, 9) # 区间型

通过调用特定的正向化函数,对DataFrame中的几列数据进行了不同类型的正向化处理,以便用于后续的数据分析或模型建设。

import numpy as np
# 标准化
def func(data):
tep_x1 = (data.iloc[:,0::]*data.iloc[:,0::]).sum() # 每个元素平方后按列相加
tep_x2 = np.tile(tep_x1,(data.shape[0], 1)) # 将tep_x1平铺a行
Z = data.iloc[:,::]/((tep_x2)**0.5) # 标准化
return(Z)

data_bzh = func(data)
data_bzh.head()

  标准化,即将数据缩放到指定范围(通常是   ),公式为:

其中,  是标准化后的原始,  是原始数据框中的元素,  是第  列的最小值,  是第  列的最大值。

# 熵权法求每个指标权值
P = data_bzh/np.tile(data_bzh.sum(),(data_bzh.shape[0],1)) # 概率矩阵P
E = -1/np.log(data_bzh.shape[0]) * (P*np.log(P)).sum()
D = 1-E
W = D/D.sum() # 熵权
print(W)

代码使用熵权法,通过对标准化数据,计算每个指标的概率矩阵和信息熵,然后通过离散度计算得到每个指标的权值,最终输出一个权值向量   ,用于评估每个指标在多准则决策中的相对重要性。

tep_max = data_bzh.max()
tep_min = data_bzh.min()
D_P = ((((np.tile(tep_max, (data_bzh.shape[0],1))-data_bzh)**2)*np.tile(W, (data_bzh.shape[0],1))).sum(axis = 1))**0.5
D_N = ((((np.tile(tep_min, (data_bzh.shape[0],1))-data_bzh)**2)*np.tile(W, (data_bzh.shape[0],1))).sum(axis = 1))**0.5
S = D_N/(D_P+D_N) # 未归一化得分

代码计算了数据框 data_bzh 中每行的未归一化得分 S,该得分反映了每个方案相对于理想解和负理想解的距离。具体而言,使用熵权法中的极大型指标,计算每行数据相对于最大值(理想解)和最小值(负理想解)的距离,最终得到未归一化得分。

import matplotlib.pylab as plt
plt.rcParams['font.sans-serif'] = 'SimHei' # 设置中文显示
plt.rcParams['axes.unicode_minus'] = False

df = pd.DataFrame(S)
plt.figure(figsize=(8, 3), dpi = 300)
y1 = df.iloc[0:15, :]
y2 = df.iloc[15:30,:]
y3 = df.iloc[30:45,:]
y4 = df.iloc[45:60,:]
X = range(1, 16)
plt.scatter(X, y1, color= 'k', label='水池#1')
plt.scatter(X, y2, color= 'b', label='水池#2')
plt.scatter(X, y3, color= 'y', label='水池#3')
plt.scatter(X, y4, color= 'r', label='水池#4')
plt.legend(loc='upper left', numpoints=1, ncol=1, fontsize=8, bbox_to_anchor=(1, 1))
plt.title('各水池评价')
plt.xlabel('周数')
plt.ylabel('评价值')
plt.show()

绘制四个水池在不同周数的评价值散点图,展示四个水池每周的评价值分布情况,帮助比较它们的性能。

# 输出每个水池均值评分
print(df.iloc[0:15, :].mean())
print(df.iloc[15:30,:].mean())
print(df.iloc[30:45,:].mean())
print(df.iloc[45:60,:].mean())

本文章转载微信公众号@Python机器学习AI