TOPSIS方法以及python代码实现

文章目录

  • TOPSIS方法简介
  • 实现过程
    • 1.将数据正向化
    • 2.将正向化矩阵标准化
    • 3.计算得分并归一化
  • 实例分析
    • 分析
    • 代码实现
  • 拓展

TOPSIS方法简介

TOPSIS法(Technique for Order Preference by Similarity to Ideal Solution),通常也称为优劣解距离法。TOPSIS 法是一种常用的综合评价方法,其能充分利用原始数据的信息,其结果能精确地反映各评价方案之间的差距。它用于解决的问题是:给出n个对象,以及n个对象关于m个指标的各项数据,根据这些数据对n个对象进行综合评价并打分,此分数能反映这n个对象的综合排名

实现过程

1.将数据正向化

我们通常将数据指标分为四种:极大型、极小型、中间型、区间型,具体区别如下表:
极大型 数据值越大越好,比如成绩、利润等 极小型 数据值越小越好,比如损失、挂科率等 中间型 数据值接近某个值时最好,比如某些情况下的ph值 区间型 数据值位于某个区间内最好 \begin{array}{c|c} \text{极大型} & \text{数据值越大越好,比如成绩、利润等}\\ \hline \text{极小型} & \text{数据值越小越好,比如损失、挂科率等}\\ \hline \text{中间型} & \text{数据值接近某个值时最好,比如某些情况下的ph值}\\ \hline \text{区间型} & \text{数据值位于某个区间内最好} \end{array} 极大型极小型中间型区间型数据值越大越好,比如成绩、利润等数据值越小越好,比如损失、挂科率等数据值接近某个值时最好,比如某些情况下的ph数据值位于某个区间内最好
在这一步我们要做的是将m个指标全部转换为极大型指标,以下是对于每种数据类型的处理方法举例(因为转换成极大型的方法不止一种)
对于一组数据: y 1 , y 2 , ⋯   , y m y_1,y_2,\cdots,y_m y1,y2,,ym
若其为极大型,则无需操作;
若其为极小型, y i ∗ = m a x { y 1 , y 2 , ⋯   , y m } − y i y_i^* = max\{y_1,y_2,\cdots,y_m\} -y_i yi=max{y1,y2,,ym}yi,则 y 1 ∗ , y 2 ∗ , ⋯   , y m ∗ y_1^*,y_2^*,\cdots,y_m^* y1,y2,,ym组成一组极大型指标;
若其为中间型,设 y 0 y_0 y0为最优值, M = m a x { ∣ y i − y 0 ∣ } , y i ∗ = 1 − ∣ y i − y 0 ∣ M M = max\{|y_i-y_0|\},y_i^* = 1-\frac{|y_i-y_0|}{M} M=max{yiy0},yi=1Myiy0,则 y 1 ∗ , y 2 ∗ , ⋯   , y m ∗ y_1^*,y_2^*,\cdots,y_m^* y1,y2,,ym组成一组极大型指标;
若其为区间型,设最优区间为(a,b),并且假定大于b、小于a的数据均存在, M = m a x { a − m i n   y i , m a x   y i − b } M = max\{a-min\,y_i,max\,y_i-b\} M=max{aminyi,maxyib}
y i ∗ = { 1 − a − y i M y i ≤ a 1 a < y i < b 1 − y i − b M y i ≥ b y_i^* = \begin{cases} 1-\frac{a-y_i}{M} & y_i \leq a \\ 1 & a < y_i < b \\ 1-\frac{y_i-b}{M} & y_i \geq b \end{cases} yi=1Mayi11Myibyiaa<yi<byib y 1 ∗ , y 2 ∗ , ⋯   , y m ∗ y_1^*,y_2^*,\cdots,y_m^* y1,y2,,ym组成一组极大型指标

2.将正向化矩阵标准化

设待评价的n个对象的m个指标的数据矩阵(经过正向化之后)如下:
[ x 11 x 12 ⋯ x 1 m x 21 x 22 ⋯ x 2 m ⋮ ⋮ ⋱ ⋮ x n 1 x n 2 ⋯ x n m ] \begin{bmatrix} x_{11} & x_{12} & \cdots & x_{1m} \\ x_{21} & x_{22} & \cdots & x_{2m} \\ \vdots & \vdots & \ddots & \vdots \\ x_{n1} & x_{n2} & \cdots & x_{nm} \\ \end{bmatrix} x11x21xn1x12x22xn2x1mx2mxnm
标准化是在此基础上构造新矩阵,使得每一列的元素平方和为1,不难验证以下操作得到的矩阵 Z Z Z即满足要求
z i j = x i j ∑ i = 1 n x i j 2 z_{ij} = \frac{x_{ij}}{\sqrt{\sum_{i=1}^{n}x_{ij}^2}} zij=i=1nxij2 xij
之所以进行标准化,是因为各个指标的量纲不同,进行标准化是为了消除量纲差异

3.计算得分并归一化

标准化矩阵为
[ z 11 z 12 ⋯ z 1 m z 21 z 22 ⋯ z 2 m ⋮ ⋮ ⋱ ⋮ z n 1 z n 2 ⋯ z n m ] \begin{bmatrix} z_{11} & z_{12} & \cdots & z_{1m} \\ z_{21} & z_{22} & \cdots & z_{2m} \\ \vdots & \vdots & \ddots & \vdots \\ z_{n1} & z_{n2} & \cdots & z_{nm} \\ \end{bmatrix} z11z21zn1z12z22zn2z1mz2mznm
将每列的最大值取出组成最大值向量: Z + = ( m a x   { z i 1 } , m a x   { z i 2 } , ⋯   , m a x   { z i m } ) Z^+=(max\,\{z_{i1}\},max\,\{z_{i2}\},\cdots,max\,\{z_{im}\}) Z+=(max{zi1},max{zi2},,max{zim}),同理得到最小值向量 Z − Z^- Z
第i个对象的m个数据与最大值之间的距离为 D i + = ∑ j = 1 m ( z i j − Z j + ) 2 D_i^+=\sqrt{\sum_{j=1}^m{(z_{ij}-Z_j^+)^2}} Di+=j=1m(zijZj+)2 ,与最小值之间的距离为 D i − = ∑ j = 1 m ( z i j − Z j − ) 2 D_i^-=\sqrt{\sum_{j=1}^m{(z_{ij}-Z_j^-)^2}} Di=j=1m(zijZj)2 那么我们将第i个对象的未归一化得分定义为 S i = D i − D i + + D i − S_i=\frac{D_i^-}{D_i^++D_i^-} Si=Di++DiDi,归一化之后,第i个对象的最终得分为 S i ∑ r = 1 n S r \frac{S_i}{\sum_{r=1}^nS_r} r=1nSrSi,至此便完成了全部的打分工作,接下来根据分数便可看出n个对象的综合排名

实例分析

下面通过一个实际问题来进一步理解该打分方法
例:下图为七个国家2020年在高等教育领域的七个指标的汇总,请根据其为七个国家在高等教育领域排名TOPSIS方法以及python代码实现_第1张图片

分析

在这七个指标中,通过查阅资料得出:第1、3、5、6项指标为极大型指标;招生人数为中间型,最优值2500;毕业率为中间型,最优值0.74;师生比为中间型,最优值0.105

代码实现

import numpy as np

#定义转换函数:
def f_1(A):#极小型->极大型
    x = np.max(A)
    for i in range(0,A.shape[0]):
        A[i] = x-A[i]
    return A

def f_2(A,a):#中间型->极大型
    x = np.max(np.abs(A-a))
    for i in range(0,A.shape[0]):
        A[i] = 1-np.abs(A[i]-a)/x
    return A

def f_3(A,a,b):#区间型->极大型
    u = a-np.min(A)
    v = np.max(A)-b
    M = v
    if u>=v:
        M=u
    for i in range(0,A.shape[0]):
        if A[i]<=a:
            A[i] = 1-(a-A[i])/M
        elif A[i]>=b:
            A[i] = 1-(A[i]-b)/M
        else:
            A[i] = 1
    return A

#定义标准化函数:
def standardize(A):
    for j in range(0,A.shape[1]):
        sum = 0
        for i in range(0,A.shape[0]):
            sum = sum+A[i][j]**2
        for i in range(0,A.shape[0]):
            A[i][j] = A[i][j]/np.sqrt(sum)
    return A

#定义打分函数:
def score(Z):
    Z = np.transpose(Z)
    Z_max = []
    Z_min = []
    for j in range(0,Z.shape[0]):
        Z_max.append(np.max(Z[j]))
        Z_min.append(np.min(Z[j]))
    S = []
    for i in range(0,Z.shape[1]):
        sum1 = 0
        for j in range(0,Z.shape[0]):
            sum1 = sum1+(Z[j][i]-Z_max[j])**2
        D1 = np.sqrt(sum1)
        sum2 = 0
        for j in range(0,Z.shape[0]):
            sum2 = sum2+(Z[j][i]-Z_min[j])**2
        D2 = np.sqrt(sum2)
        S.append(D2/(D1+D2))
    return S

#归一化函数:
def g(S):
    S = np.array(S)
    sum = 0
    for i in range(0,S.shape[0]):
        sum = sum+S[i]
    for i in range(0,S.shape[0]):
        S[i] = S[i]/sum
    return S

def main():
    A = np.array([[28,19,3,5,3,3,8],
                  [1806,3180,3080,2560,3551,3309,3139],
                  [11.2,7.98,8.12,5.29,4.3,5.68,6.58],
                  [0.67,0.71,0.75,0.76,0.874,0.92,0.708],
                  [17413,11770,9081,11566,8295,9143,9556],
                  [0.823,0.741,0.804,0.7947,0.851,0.754,0.8676],
                  [0.112,0.111,0.1,0.091,0.071,0.058,0.067]])
    A[1] = f_2(A[1],2500)
    A[3] = f_2(A[3],0.74)
    A[6] = f_2(A[6],0.105)
    B = np.transpose(A)
    Z = standardize(B)
    S = score(Z)
    S1 = g(S)
    print(S1)

main()

结果为[0.22337069 0.19818175 0.1626775 0.18908219 0.04941305 0.0465146 0.13076021]由此得到各国的分数,可以看出每个国家在高等教育领域的发展程度,分数较低的国家需要寻找差距。

拓展

本道题目中默认了各项指标的权重相同,但在实际的评价中指标都是有各自的权重,因此应该用权重对公式进行修正,修正后的公式如下, ω \omega ω 代表权重。
D i + = ∑ j = 1 m ω j ( Z j + − z i j ) 2 , D i − = ∑ j = 1 m ω j ( Z j − − z i j ) 2 D_i^+=\sqrt{\sum_{j=1}^m\omega_j(Z_j^+-z_{ij})^2},D_i^-=\sqrt{\sum_{j=1}^m\omega_j(Z_j^--z_{ij})^2} Di+=j=1mωj(Zj+zij)2 ,Di=j=1mωj(Zjzij)2

你可能感兴趣的:(python,算法,数学建模)