熵权法

本文最后更新于 2025年7月28日 上午

25年暑假学习数模算法时做的一些笔记。

熵权法

一种比较客观的,得到权重的方法

依据的原理:指标的变异程度越小,所反映的信息量也越少,其对应的权值也应该越低。

步骤

1.数据标准化

矩阵标准化之后为$Z$,满足 $$ z_{ij} = \frac{x_{ij}}{\sqrt{\sum_{i=1}^{n} x_{ij}}} $$ 若存在负数,则 $$ \tilde{Z} = \frac{x - \min{x_{1j}, x_{2j}, ..., x_{nj}}}{\max{x_{1j}, x_{2j}, ..., x_{nj}} - \min{x_{1j}, x_{2j}, ..., x_{nj}}} \ \tilde{Z} \in (0,1) $$

2.计算概率矩阵$P$

$$ p_{ij} = \frac{z_{ij}}{\sum_{i=1}^{n} z_{ij}} $$

3.计算熵权

$$ 信息熵e_j = -\frac{1}{\ln n} \sum_{i=1}^{n} p_{ij} \ln(p_{ij}) \quad (j=1,2,...,m) \ 信息效用值d_j=1-e_j \ 归一化得到w_j=\frac{d_j}{\sum_{j=1}^{m}d_j} \ 其中 W_j 为第 j 个指标的熵权。 $$

Python代码

代码PYTHON · 89 行
import numpy as np

def entropy_weight(X):
    """
    根据给定的数据矩阵计算熵权。

    参数:
    X (np.array): 数据矩阵,n行(样本)x m列(指标)。

    返回:
    np.array: 每个指标的权重 w。
    """
    # 将输入转换为numpy数组
    X = np.array(X)
    
    # --- 步骤 1: 数据标准化 ---
    # 为了普适性和避免负数带来的问题,我们使用您提供的第二种标准化方法 (Min-Max Normalization)
    # Z = (x - min) / (max - min)
    # PS: 如果您的数据保证全为正数,也可以使用第一种方法。
    
    # 检查数据中是否存在负数
    if np.any(X < 0):
        print("数据中存在负数,将使用 Min-Max 标准化方法。")
        # 对每一列(指标)进行标准化
        min_vals = X.min(axis=0)
        max_vals = X.max(axis=0)
        # 防止分母为0
        ranges = max_vals - min_vals
        ranges[ranges == 0] = 1 
        Z = (X - min_vals) / ranges
    else:
        print("数据中无负数,将使用向量归一化方法。")
        # z_ij = x_ij / sqrt(sum(x_ij^2 for i in 1 to n))
        # 注意:您给出的公式是 x_ij / sqrt(sum(x_ij)),这在数学上不常见。
        # 通常使用的是向量范数,即除以平方和的平方根。这里我们按照常规的向量标准化来处理。
        norm_base = np.sqrt((X**2).sum(axis=0))
        # 防止分母为0
        norm_base[norm_base == 0] = 1
        Z = X / norm_base

    # 处理标准化后可能出现的0值,为其加上一个极小值,以防止log(0)错误
    Z[Z == 0] = 1e-9

    # --- 步骤 2: 计算概率矩阵 P ---
    # p_ij = z_ij / sum(z_ij for i in 1 to n)
    P = Z / Z.sum(axis=0)
    
    # --- 步骤 3: 计算熵权 ---
    n, m = X.shape  # n 个样本, m 个指标
    
    # 计算信息熵 e_j
    # e_j = - (1/ln(n)) * sum(p_ij * ln(p_ij) for i in 1 to n)
    k = -1 / np.log(n)
    # 计算每个指标的信息熵
    e = (P * np.log(P)).sum(axis=0) * k
    
    # 计算信息效用值 (信息冗余度) d_j
    # d_j = 1 - e_j
    d = 1 - e
    
    # 归一化得到最终权重 w_j
    # w_j = d_j / sum(d_j for j in 1 to m)
    w = d / d.sum()
    
    return w

if __name__ == '__main__':
    # ================================================================
    # 请在这里修改您的矩阵数据
    # n行样本, m列指标
    # 例如,一个4个样本、3个指标的矩阵
    X = [
        [8, 9, 7],
        [6, 7, 8],
        [9, 6, 6],
        [7, 8, 9]
    ]
    # ================================================================
    
    # 将列表转换为numpy数组以便计算
    X_matrix = np.array(X)
    
    # 调用函数计算权重
    weights = entropy_weight(X_matrix)
    
    # 打印结果
    print("\n计算得到的各指标权重为:")
    for i, w in enumerate(weights):
        print(f"指标 {i+1}: {w:.4f}")