3  熵权法

在信息论中,是对不确定性的一种度量。不确定性越大,熵值越高,所包含的信息量也就越大;反之,不确定性越小,熵值越低,信息量也相应减少。

根据熵的这一特性,可以通过计算熵值来评估一个事件的随机性与无序程度。同时,熵值也可用于衡量某个指标的离散程度。指标的离散程度越大,其在综合评价体系中的影响(即权重)也就越大。例如,如果某一指标在所有样本中的取值完全相同,则该指标对综合评价没有任何区分作用,其提供的信息量为零,因此对应的权重也应为零。

熵权法,是一种基于数据本身分布特征的客观赋权方法,其核心思想是依据各指标的信息熵来确定权重,从而避免主观因素的干扰,具有较强的科学性与合理性。

3.1 算法步骤

设有 \(n\) 个评价对象,\(m\) 个评价指标,形成原始指标数据矩阵,其中 \(x_{ij}\) 表示第 \(i\) 个评价对象第 \(j\) 个指标的值。

(1) 数据归一化

由于不同指标通常具有不同的量纲和数量级,为了消除其影响,需要进行归一化处理。

  • 对于正向指标(越大越好): \[ x'_{ij} = \dfrac{x_{ij} - \min\limits_i x_{ij}}{\max\limits_i x_{ij} - \min\limits_i x_{ij}} \]
  • 对于 负向指标(越小越好): \[ x'_{ij} = \dfrac{\max\limits_i x_{ij} - x_{ij} }{\max\limits_i x_{ij} - \min\limits_i x_{ij}} \] 其中,\(\min_ix_{ij}\)\(\max_ix_{ij}\) 分别是第 \(j\) 个指标所有样本值中的最小值和最大值。

注意,熵权法中涉及 \(\ln(\cdot)\) 运算,所以归一化不能出现 \(0\)\(1\),为此,归一化时把 \([0,1]\) 稍微收缩一下,比如到 \([0.002,0.998]\)

为了方便起见,归一化后的数据 \(x_{ij}^{\prime}\) 仍记为 \(x_{ij}\)

注:归一化更适合应用到近似服从均匀分布的数据;也可以使用标准化,标准化更适合应用到近似服从正态分布的数据,负向指标标准化后乘以 \(-1\) 即可正向化。

(2)计算第 \(j\) 个指标下第 \(i\) 个样本值占该指标的比重

将标准化后的值 \(x_{ij}\) 视为某种”概率贡献”,计算其在第 \(j\) 个指标总“贡献”中的比重: \[ p_{ij}=\dfrac{x_{ij}}{\sum_{i=1}^n x_{ij}}, \quad i=1,\, \cdots,\,n,\;j=1,\,\cdots,\,m \]

(3) 计算第 \(j\) 个指标的熵值

利用信息熵公式计算每个指标的信息熵: \[ e_{j}=-k\sum_{i=1}^{n}p_{ij}\ln(p_{ij}),\quad j=1,\cdots,m \] 其中,\(k=1/\ln(n)>0\),满足 \(e_{j} \geq 0\)

熵值 \(e_{j}\) 反映了第 \(j\)个 指标下数据的离散程度,熵值 \(e_{j}\) 越大,表明该指标提供的有用信息量越少。

(4) 计算信息熵冗余度(差异系数)

\[ d_{j}=1-e_{j},\quad j=1,\cdots,m \]

差异系数反映了指标信息量的大小,\(d_{j}\) 越大,表示第 \(j\) 个指标值的离散程度越大(不确定性越小,信息量越大),该指标在综合评价中应赋予较大的权重。

(5) 计算各个指标的权重

将差异系数进行归一化处理,得到各指标的最终权重: \[ w_j=\frac{d_j}{\sum_{j=1}^m d_j},\quad j=1,\,\cdots,\,m \]

(6)(可选)计算各个评价对象的综合得分

\[ s_i=100 × \sum\limits_{j=1}^m w_j x_{ij}, \quad i=1,\,\cdots,\,n \] 其中,\(x_{ij}\) 为标准化后的数据。

3.2 案例:河流水质数据

加载包:

library(tidyverse)
library(mathmodels)

3.2.1 准备数据

使用内置的 water_quality 数据来演示:

water_quality 
# A tibble: 20 × 5
      ID    O2    PH  germ nutrient
   <dbl> <dbl> <dbl> <dbl>    <dbl>
 1     1  4.69  6.59    51    11.9 
 2     2  2.03  7.86    19     6.46
 3     3  9.11  6.31    46     8.91
 4     4  8.61  7.05    46    26.4 
 5     5  7.13  6.5     50    23.6 
 6     6  2.39  6.77    38    24.6 
 7     7  7.69  6.79    38     6.01
 8     8  9.3   6.81    27    31.6 
 9     9  5.45  7.62     5    18.5 
10    10  6.19  7.27    17     7.51
11    11  7.93  7.53     9     6.52
12    12  4.4   7.28    17    25.3 
13    13  7.46  8.24    23    14.4 
14    14  2.01  5.55    47    26.3 
15    15  2.04  6.4     23    17.9 
16    16  7.73  6.14    52    15.7 
17    17  6.35  7.58    25    29.5 
18    18  8.29  8.41    39    12.0 
19    19  3.54  7.27    54     3.16
20    20  7.44  6.26     8    28.4 

这是 \(20\) 条河流的水质数据,含氧量越高越好(正向指标);PH 值越接近 \(7\) 越好(居中型指标);细菌总数越少越好(负向指标);植物性营养物量介于 \(10 \sim 20\) 之间最佳(区间型指标)。

3.2.2 数据预处理

借助 mathmodels 包提供的预处理函数,使用 mutate() 修改列即可。只需要处理居中型和区间型指标,因为指标归一化已内置到熵权法函数。

df = water_quality |>
  mutate(PH = rescale_middle(PH, 7), 
         nutrient = rescale_interval(nutrient, 10, 20))
df
# A tibble: 20 × 5
      ID    O2     PH  germ nutrient
   <dbl> <dbl>  <dbl> <dbl>    <dbl>
 1     1  4.69 0.717     51    1    
 2     2  2.03 0.407     19    0.694
 3     3  9.11 0.524     46    0.906
 4     4  8.61 0.966     46    0.444
 5     5  7.13 0.655     50    0.691
 6     6  2.39 0.841     38    0.601
 7     7  7.69 0.855     38    0.655
 8     8  9.3  0.869     27    0    
 9     9  5.45 0.572      5    1    
10    10  6.19 0.814     17    0.785
11    11  7.93 0.634      9    0.699
12    12  4.4  0.807     17    0.542
13    13  7.46 0.145     23    1    
14    14  2.01 0         47    0.455
15    15  2.04 0.586     23    1    
16    16  7.73 0.407     52    1    
17    17  6.35 0.6       25    0.182
18    18  8.29 0.0276    39    1    
19    19  3.54 0.814     54    0.409
20    20  7.44 0.490      8    0.273

3.2.3 熵权法

entropy_weight() 函数实现用熵权法计算权重,该函数已内置归一化处理,基本语法:

entropy_weight(X, index = NULL, epsilon = 0.002)
  • index 可以指定对哪些列做正向("+")、负向("-")、不做(NA)归一化,默认 index = NULL 表示,所有列都不做归一化。
  • epsilon 是熵权法中避免出现 \(0\)\(1\) 值的微调量,默认为 \(0.002\)

本例已对指标列 PHnutrient 事先做了归一化,故将指标方向设置为 NA,以不再重复做归一化,只是微调 \(0\)\(1\) 值,避免熵权法计算时出现 \(\ln(0)\)

idx = c("+", NA, "-", NA)
res = entropy_weight(df[-1], idx)
  • 查看指标权重:
res$w
       O2        PH      germ  nutrient 
0.3153202 0.1813149 0.3506929 0.1526721 
  • 查看评价对象得分:
res$s
 [1] 42.05869 43.14229 59.75555 58.55797 47.47757 37.60200 61.51622 66.57186
 [9] 75.49739 71.25274 79.89397 59.70830 63.57278 12.10016 48.22587 48.81539
[17] 53.16568 53.61734 27.72132 69.36453
  • 对应到河流,增加排名列:
tibble(ID = df$ID, score = res$s, rank = min_rank(-score)) |> 
  arrange(rank)
# A tibble: 20 × 3
      ID score  rank
   <dbl> <dbl> <int>
 1    11  79.9     1
 2     9  75.5     2
 3    10  71.3     3
 4    20  69.4     4
 5     8  66.6     5
 6    13  63.6     6
 7     7  61.5     7
 8     3  59.8     8
 9    12  59.7     9
10     4  58.6    10
11    18  53.6    11
12    17  53.2    12
13    16  48.8    13
14    15  48.2    14
15     5  47.5    15
16     2  43.1    16
17     1  42.1    17
18     6  37.6    18
19    19  27.7    19
20    14  12.1    20