TOPSIS法(优劣解距离法)介绍及 python3 实现

2023-11-04

本文转载自博文: TOPSIS法(优劣解距离法)介绍及 python3 实现

这里也给出一个很好的参考资料:夹逼对抗解释结构模型(SAISM)即TOPSIS-AISM联用模型

文章目录

1. 简述

C.L.Hwang 和 K.Yoon 于1981年首次提出 TOPSIS (Technique for Order Preference by Similarity to an Ideal Solution)。TOPSIS 法是一种常用的组内综合评价方法,能充分利用原始数据的信息,其结果能精确地反映各评价方案之间的差距。基本过程为基于归一化后的原始数据矩阵,采用余弦法找出有限方案中的最优方案和最劣方案,然后分别计算各评价对象与最优方案和最劣方案间的距离,获得各评价对象与最优方案的相对接近程度,以此作为评价优劣的依据。该方法对数据分布及样本含量没有严格限制,数据计算简单易行。

通俗的例子:小明数学考试 134 分,要怎么知道他的成绩是好还是不好呢?

基于分布的评价方法会观察小明的分数位于班级分数的哪个水平(如前 5%、前 10%),但这种评价方法只能给出一个方向的情况。如班上成绩除了最高分外,其余都是 134 分,那么小明的成绩就是并列的倒数第一,但是正向评价给出的结果是前 5%。
而 TOPSIS 就是找出班上最高分(假设是 147 分)、最低分(假设是 69 分),然后计算小明的分数和这两个分数之间的差距,从而得到自己分数好坏的一个客观评价。距离最高分越近,那么评价情况越好,距离最低分越近,那么评价情况越糟。

2. TOPSIS过程

网上大部分资料对此部分均有描述,但不少资料与文献原文存在较大偏差、排版较为混乱,并且没有深入思考原理。此部分内容转述外网文献,并加入了笔者自己的理解。
在这里插入图片描述

2.1 指标属性同向化

TOPSIS 法使用距离尺度来度量样本差距,使用距离尺度就需要对指标属性进行同向化处理(若一个维度的数据越大越好,另一个维度的数据越小越好,会造成尺度混乱)。通常采用成本型指标向效益型指标转化(即数值越大评价越高,事实上几乎所有的评价方法都需要进行转化),此外,如果需要使用雷达图进行展示,建议此处将所有数据都变成正数。

2.1.1 极小型指标

极小型指标:期望指标值越小越好(如患病率、死亡率等)
在这里插入图片描述

M M M 为指标 x x x 可能取值的最大值。

2.1.2 中间型指标

中间型指标:期望指标值既不要太大也不要太小,适当取中间值最好(如水质量评估 PH 值)

[公式]

其中 M M M 为指标 x x x 的可能取值的最大值, m m m 为指标 x x x 的可能取值的最小值

2.1.3 区间型指标

区间型指标:期望指标的取值最好落在某一个确定的区间最好(如体温)

[公式]

其中 [ a , b ] [a, b] [a,b] 为指标 x x x 的最佳稳定区间, [ a ∗ , b ∗ ] [a^*, b^*] [a,b] 为最大容忍区间。

指标属性同向化实现代码:

def dataDirection_1(datas, offset=0):
	def normalization(data):
		return 1 / (data + offset)

	return list(map(normalization, datas))


def dataDirection_2(datas, x_min, x_max):
	def normalization(data):
		if data <= x_min or data >= x_max:
			return 0
		elif data > x_min and data < (x_min + x_max) / 2:
			return 2 * (data - x_min) / (x_max - x_min)
		elif data < x_max and data >= (x_min + x_max) / 2:
			return 2 * (x_max - data) / (x_max - x_min)

	return list(map(normalization, datas))


def dataDirection_3(datas, x_min, x_max, x_minimum, x_maximum):
	def normalization(data):
		if data >= x_min and data <= x_max:
			return 1
		elif data <= x_minimum or data >= x_maximum:
			return 0
		elif data > x_max and data < x_maximum:
			return 1 - (data - x_max) / (x_maximum - x_max)
		elif data < x_min and data > x_minimum:
			return 1 - (x_min - data) / (x_min - x_minimum)

	return list(map(normalization, datas))
2.2 构造归一化初始矩阵

设共有 n n n 个待评价对象,每个对象都有 m m m 个指标(属性),则原始数据矩阵构造为:
在这里插入图片描述
构造加权规范矩阵,属性进行向量规范化,即每一列元素都除以当前列向量的范数(使用余弦距离度量):
在这里插入图片描述
由此得到归一化处理后的标准化矩阵 Z Z Z
在这里插入图片描述

2.3 确定最优方案和最劣方案

最优方案 Z + Z^+ Z+ Z Z Z 中每列元素的最大值构成:
在这里插入图片描述
最劣方案 Z − Z^- Z Z Z Z 中每列元素的最小值构成:
在这里插入图片描述

2.4 计算各评价对象与最优/劣方案的接近程度

在这里插入图片描述
其中 W j W_j Wj 为第 j j j 个属性的权重(重要程度),指标权重建议根据实际确定或使用专家评估方法。基于信息论的 熵值法(AHP)层次分析法 ,在本文第 4 部分也提供了方法的简要介绍。

2.5 计算各评价对象与 最劣方案 的距离 C i C_i Ci

在这里插入图片描述
注:

  • 上式分子为 D i − {D^-_i} Di, 计算的是各评价对象与 最劣方案 的距离 (即与最优方案的贴近程度)。 0 ≤ C i ≤ 1 , C i → 1 0 \le {C_i} \le 1,{\kern 1pt} {\kern 1pt}{C_i} \to 1 0Ci1,Ci1 表明评价对象越优 (距离最劣方案越远, 则方案越优)。
  • 此处也可以将分子设置为 D i + {D^+_i} Di+, 表示与 最优方案 的距离 (即与最劣方案的贴近程度), 此时 0 ≤ C i ≤ 1 , C i → 0 0 \le {C_i} \le 1,{\kern 1pt} {\kern 1pt}{C_i} \to 0 0Ci1,Ci0 表明评价对象越优 (距离最优方案越近, 则方案越优)。
2.6 根据 C i C_i Ci 大小进行排序,给出评价结果
2.7 TOPSIS法算法程序

使用的编程语言:python3.7.1 (Anaconda3)

使用的编辑器:Sublime Text 3

使用的模块:pandas、numpy

import pandas as pd
import numpy as np


def topsis(data, weight=None):
	# 归一化
	data = data / np.sqrt((data ** 2).sum())

	# 最优最劣方案
	Z = pd.DataFrame([data.min(), data.max()], index=['负理想解', '正理想解'])

	# 熵权法计算权值
	weight = get_entropy_weight_1(data) if weight is None else np.array(weight)
	Result = data.copy()
	
	# 计算距离
	Result['正理想解'] = np.sqrt(((data - Z.loc['正理想解']) ** 2 * weight).sum(axis=1))
	Result['负理想解'] = np.sqrt(((data - Z.loc['负理想解']) ** 2 * weight).sum(axis=1))

	# 综合得分指数
	Result['综合得分指数'] = Result['负理想解'] / (Result['负理想解'] + Result['正理想解'])
	Result['排序'] = Result.rank(ascending=False)['综合得分指数']

	return Result, Z, weight

topsis 函数需要输入:

  • data:原始数据,pandas.DataFrame 类型
  • weight:权系数, 默认使用熵权法定权. 也可以传入指定权重列表. (熵权法代码见下文)

3. 案例及程序调用实例

3.1 问题提出

为了客观地评价我国研究生教育的实际状况和各研究生院的教学质量,国务院学位委员会办公室组织过一次研究生院的评估。为了取得经验,先选5所研究生院,收集有关数据资料进行了试评估,下表是所给出的部分数据:
在这里插入图片描述

3.2 指标同向化处理
  • 人均专著、科研经费为效应型指标(越大越好)
  • 逾期毕业率为成本型指标(越小越好)
  • 生师比为区间型指标
    在这里插入图片描述
3.3 构造归一化初始矩阵

以 “人均专著” 属性为例:
在这里插入图片描述

在这里插入图片描述

3.4 确定最优方案和最劣方案

在每一列中分别选取最大值、最小值构成最优最劣方案:
在这里插入图片描述

3.5 计算得分,进行排序

计算各评价对象与最优方案的接近程度及最终得分,并进行排序。

在这里插入图片描述

3.6 雷达图分析

在这里插入图片描述

3.7 实现代码
import pandas as pd

def dataDirection_3(datas, x_min, x_max, x_minimum, x_maximum):
    def normalization(data):
        if data >= x_min and data <= x_max:
            return 1
        elif data <= x_minimum or data >= x_maximum:
            return 0
        elif data > x_max and data < x_maximum:
            return 1 - (data - x_max) / (x_maximum - x_max)
        elif data < x_min and data > x_minimum:
            return 1 - (x_min - data) / (x_min - x_minimum)

    return list(map(normalization, datas))


data = pd.DataFrame(
    {'人均专著': [0.1, 0.2, 0.4, 0.9, 1.2], '生师比': [5, 6, 7, 10, 2], '科研经费': [5000, 6000, 7000, 10000, 400],
     '逾期毕业率': [4.7, 5.6, 6.7, 2.3, 1.8]}, index=['院校' + i for i in list('ABCDE')])

data['生师比'] = dataDirection_3(data['生师比'], 5, 6, 2, 12)   # 师生比数据为区间型指标
data['逾期毕业率'] = 1 / data['逾期毕业率']   # 逾期毕业率为极小型指标

out = topsis(data, weight=[0.2, 0.3, 0.4, 0.1])    # 设置权系数

4. 合理确定指标权重是 TOPSIS 综合评价的关键

权重计算的确定方法在综合评价中重中之重,不同的方法对应的计算原理并不相同。

通常来说采用TOPSIS方法采用的是客观法,因为客观法可以利用当前的数据直接求出权重,计算上非常方便。常见的客观赋权法如下:
在这里插入图片描述
这里重点介绍熵权法(EWM),其他几种方法可以参考:http://www.huaxuejia.cn/ism/CESAISM/topsis_saism.php

4.1 基于信息论的熵值法(数据差异程度)
4.1.1 熵值法过程

基于信息论的熵值法是根据各指标所含信息有序程度的差异性来确定指标权重的客观赋权方法,仅依赖于数据本身的离散程度。

熵用于度量不确定性,指标的离散程度越大(不确定性越大)则熵值越大,表明指标值提供的信息量越多,则该指标的权重也应越大。主要计算步骤如下:

Step1: 对原始数据矩阵 (4) 按列进行归一化处理

注意:

  • 这里不能是同向化后的矩阵,会损失原始信息
  • 归一化方法不唯一,可使用min-max归一化,mean-std归一化或者向量归一化等。

Step2: 计算各指标的熵值:
在这里插入图片描述

在这里插入图片描述

Step3: 计算各指标的权系数:

在这里插入图片描述
熵权系数 h j h_j hj 越大,则该指标代表的信息量越大,表示其对综合评价的作用越大。

4.1.2 结果分析

上面的方法看着很高大上,但是直觉告诉我(们),从数据推出的权重,往往都不具有现实意义。那这个到底是什么意思呢?我们用第 3 部分的数据测试一下:

  • 原始数据比值归一化后的矩阵为:
    在这里插入图片描述

  • 计算各指标方差(衡量数据离散程度)
    [公式]

  • 各指标的熵值和权系数为:
    在这里插入图片描述
    发现了吗?熵值、权系数、方差间的大小次序是相关的,如果对熵的概念较为陌生,那不妨换个角度想想:什么类型的数据会导致方差小?如人体体温变化,体温的变化都是在一个微小的范围内,这样就造成了这一属性的变异程度较小,使用熵权法(主成分分析法同理)进行计算时,获得的权系数较小,变得 “不那么重要”。但事实上即使构造了合理的权系数,在对数据做变换(如成本型指标取倒数),这种权系数的设置是否仍然合理都是个问题(数据分布情况发生了改变)。

一种减轻这种影响的方法是选择更合理的归一化方法去除指标的量纲。如变化范围较大的数据可以使用小数定标规范化、正态分布的数据使用 z 分数变换、均匀分布的数据使用离差标准化。通过这种方法,可以获得较为 “合理” 的指标权。但要注意的是合不合理都是相对的,事实上许多文献没有考虑到这种方法背后的意义,但其计算得到的结论很实用(滑动权值经验模式,未来在介绍其他评价方法时再做详细介绍),即衡量模型的优劣并不是看系数合不合理,而是效果好不好/符不符合实际。

结论:评价结果、评价方法的好坏,本身就具有很强的主观性。马克思主义告诉我们“具体问题具体分析。在矛盾普遍性原理的指导下,具体分析矛盾的特殊性,并找出解决矛盾的正确方法。”。怎么在论文中将你的思想、选取方法的原则、指标选取、权重构造尽可能详尽的展示,才是方法应用成功与否的关键。

4.1.3 熵值法实现代码

先定义基础数据:

data = pd.DataFrame(
        {'人均专著': [0.1, 0.2, 0.4, 0.9, 1.2], '生师比': [5, 6, 7, 10, 2], '科研经费': [5000, 6000, 7000, 10000, 400],
         '逾期毕业率': [4.7, 5.6, 6.7, 2.3, 1.8]}, index=['院校' + i for i in list('ABCDE')])

【实现代码 1】:

import numpy as np

def get_entropy_weight_1(data): # 熵权法需要使用原始数据作为输入
	data = np.array(data)
	# 数据归一化
	# 这里可以根据需要选择mean-std归一化或者min-max归一化
	
    # 计算Pij
	P = data / data.sum(axis=0) # 需要考虑分子为0的情况,可以考虑加一个epsilon=1e-3

	# 计算熵值
	E = np.nansum(-P * np.log(P) / np.log(len(data)), axis=0)

	# 计算权系数
	return (1 - E) / (1 - E).sum()

get_entropy_weight_1(data)

程序输出结果:

array([ 0.41803075,  0.14492264,  0.28588943,  0.15115718])

【实现代码 2】:

def get_entropy_weight_2(data):
    """
    :param data: dataframe类型
    :return: 各指标权重列表
    """
    # 数据归一化
    # 这里可以根据需要选择mean-std归一化或者min-max归一化
    
    m,n=data.shape
    
    #将dataframe格式转化为matrix格式
    data=data.as_matrix(columns=None)
    
    # 第一步:计算k
    k=1/np.log(m)
    
    #第二步:计算pij
    pij=data/data.sum(axis=0)

    # 第三步:计算每种指标的信息熵
    tmp=np.nan_to_num(pij*np.log(pij))
    ej=-k*(tmp.sum(axis=0))
    
    # 第四步:计算每种指标的权重
    wi=(1-ej)/np.sum(1-ej)
    wi_list=list(wi)
    
    return  wi_list

get_entropy_weight_2(data)
[0.41803075156086411,
 0.14492263660659988,
 0.28588943395852595,
 0.15115717787401006]

可以看到,两个代码的输出结果一致,且各个属性的权值加起来和为1。

这里,有几个需要注意的点:

  • 数据归一化:在原始数据量纲不一致时,我们使用熵权法之前可以先对数据做归一化处理。这里可以根据数据的实际情况和业务需要选择mean-std归一化或者min-max归一化。不同的归一化方法,对最后求出来的权值会有影响。
  • 除数为0的情况:上述计算过程涉及除法,会遇到除数为0的情况。可以给除数加一个很小的数值,如epsilon=1e-3,以避免除以0的情况发生。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

TOPSIS法(优劣解距离法)介绍及 python3 实现 的相关文章

  • QT字节数组类QByteArray

    QT字节数组类QByteArray 初始化 访问某个元素 截取字符串 获取字节数组的大小 数据转换与处理 Hex转换 数值转换与输出 字母大小写转换 字符串数值转化为各类数值 QBQyteArray和char 互转 QByteArray 和

随机推荐

  • CentOS 安装 Jenkins

    本文目录 1 安装 JDK 2 获取 Jenkins 安装包 3 将安装包上传到服务器 4 修改 Jenkins 配置 5 启动 Jenkins 6 打开浏览器访问 7 获取并输入 admin 账户密码 8 跳过插件安装 9 添加管理员账户
  • Linux防火墙的配置

    Linux防火墙的配置 防火墙是一种网络安全设备 可用于保护网络中的计算机和其他设备免遭来自互联网或其他网络连接的未授权访问 其主要作用是监控网络流量 根据预先设定的规则对网络流量进行过滤 以防止未经授权的访问 攻击和病毒等威胁 在Linu
  • pip安装pyspark报错

    报错 Traceback most recent call last File
  • UG/NX二次开发Siemens官方NXOPEN实例解析—1.3 BlockStyler/ExtrudewithPreview

    列文章目录 UG NX二次开发Siemens官方NXOPEN实例解析 1 1 BlockStyler ColoredBlock UG NX二次开发Siemens官方NXOPEN实例解析 1 2 BlockStyler EditExpress
  • 一维数组 ——Java

    目录 前言 一 一维数组的声明及初始化 1 一维数组的声明 2 一维数组的初始化 2 1静态初始化 2 2动态初始化 二 访问数组元素 1 添加元素 2 遍历数组 2 1 for循环 2 2 foreach 循环 增强for循环 2 3 f
  • 从深度学习的角度考虑sift关键点匹配

    试一试 看看行不行 得到内点后 再进行下一步
  • 组词典

    组词典将多个图形对象编组存储 存储后的效果 可以通过组来找到所需要的实体 在界面上选中一个就可以找到其他实体 即选中的为一个组 但是与块对比 不同的是将实体分组并不形成新的实体对象 在CAD中的的命令为group 创建组词典 AcDbGro
  • Pytorch创建与安装(无GPU) 无敌教程

    第一步 Pytorch创建与安装 无GPU 独爱相关算法的博客 CSDN博客 pytorch没有gpu 第一步中要看这一步 anaconda下载及安装 保姆级教程 知乎
  • 【编译原理】- 递归下降的语法分析器的实现

    目录 一 实验题目 二 分析与设计 三 源代码 一 实验题目 编写识别由下列文法G E 所定义的表达式的递归下降语法分析器 E E T E T T T T F T F F F E i 输入 含有十进制数或十六进制数的表达式 如 75 1ah
  • 关于vector的emplace_back和push_back的区别

    实验代码 class A public A int x x x cout lt lt construct A lt lt endl A const A a x a x cout lt lt copy construct A lt lt en
  • 正则重难点和个人见解

    正则表达式 RegExp 常用不常写 1 查询 正则大全 2 作用 描述了一种字符串的匹配模式 用在表单验证 搜索替换 模糊查询 一 声明 1 构造函数 new RegExp 规则 模式修正符 2 字面量 let reg 规则 模式修正符
  • https://www.cs.usfca.edu/~galles/visualization/Algorithms.html

    https www cs usfca edu galles visualization Algorithms html
  • 编码(NRZ、NRZI、曼彻斯特、4B/5B)

    将节点和链路变成可用构件的第一步 是清楚它们如何连接 以使比特从一个节点传输到另一个节点 正如在前一节中提到的 信号是在物理链路上传播的 因此 我们的任务是将源节点准备发送的二进制数据编码为链路能够传送的信号 然后在接收节点将信号解码成相应
  • 《Qt MOOC系列教程》第二章第二节:对象通信:信号和槽

    几乎所有的UI工具包都有一种机制来检测用户操作 并对该操作做出响应 其中一些使用回调 另一些使用监听器 但基本上 所有这些都是受观察者模式的启发 观察者模式用于观察对象想要通知其他观察者对象状态变化的情况 下面是一些具体的例子 用户单击了一
  • 【java】【jvm】使用命令行jmap手工触发fullGC

    使用了jmap工具实现 手工触发fullGC 运维常备 jmap histo live
  • 前台js中json转数组,数组转json;后台字符串String转list(类),String 转map

    前台js 数组转json串 var arr 1 2 3 a 1 JSON stringify arr json字符串转数组 var jsonStr 1 2 3 a 1 JSON parse jsonStr 后台String转list Str
  • 远程桌面连接Windows server 2012,提示 “这可能是由于 CredSSP 加密 Oracle 修正”

    出现这个问题看了好多人的博客 到最后发现其实很简单 远程桌面连接之前都是正常使用的 就是链接2012R2的时候出现这样的提示 这个主要原因是微软5月8日更新了补丁 安全性增强了 一开始我总是认为2012R2的原因 因此一直再2012里边调试
  • Java实战05 powerjob 4.3.2 + springboot 任务管理界面化

    目录 1 powerjob 3 4与4 3版本比较 2 官网下载 3 启动后直接登录 http 127 0 0 1 7700 4 新建任务 5 邮件预警 现在大量数据的任务跑批项目越来越多 任务界面化操作也越来越受到重视 于是powerjo
  • 如果笔记软件公司倒闭了,你的笔记还能接着用吗?

    检视你的笔记数据安全和由此引申出来的笔记工具选择问题 疑问 知识星球上 星友刘杰提问 我们记录在相关工具上的笔记及相关内容 会不会因为什么原因 比如 工具背后的公司倒闭了 而无法再查看和调用了呢 如果有 会是哪些原因呢 谢谢 能有数据安全意
  • TOPSIS法(优劣解距离法)介绍及 python3 实现

    本文转载自博文 TOPSIS法 优劣解距离法 介绍及 python3 实现 这里也给出一个很好的参考资料 夹逼对抗解释结构模型 SAISM 即TOPSIS AISM联用模型 文章目录 1 简述 2 TOPSIS过程 2 1 指标属性同向化