D2 · TOPSIS + 模糊综合评价¶
D1 解决的是"每个指标多重要",D2 解决"综合起来哪个方案最好"。这两天的内容合起来就是国赛评价类题目的完整解法链条——出现频率极高,务必吃透。
1. TOPSIS 的核心思想¶
全称"逼近理想解排序法"。思想极其朴素:构造一个虚拟的最优方案(正理想解,每个指标都取所有方案里的最好值)和一个虚拟的最差方案(负理想解),然后看每个真实方案离这两者的距离。离最优近、同时离最差远的,就是好方案。
为什么比"加权求和"强
加权求和只看总分,可能出现"某方案在关键指标上极差、但靠其他指标堆分反超"的情况。TOPSIS 用欧氏距离衡量,短板会被平方放大,更能反映"综合均衡性"。写论文时这句话就是你选 TOPSIS 而不用简单加权的理由。
2. 六步流程¶
- 正向化:把所有指标统一成"越大越好"(D1 的教训,四种类型的公式见第 4 节)
- 标准化:消除量纲。TOPSIS 用向量归一化(每列除以该列平方和的开方),不是 min-max
- 加权:乘上 D1 算出的权重(AHP / 熵权法 / 组合权重)
- 定理想解:Z⁺ = 每列最大值组成的向量;Z⁻ = 每列最小值组成的向量
- 算距离:每个方案到 Z⁺ 的欧氏距离 d⁺,到 Z⁻ 的距离 d⁻
- 算贴近度:C = d⁻ / (d⁺ + d⁻),取值 0~1,越大越优,按 C 排序即得结论
易错
贴近度公式分子是 d⁻ 不是 d⁺。记忆方法:分子放"离最差的距离",离最差越远越好,所以越大越优——和直觉方向一致。写反了排名会完全颠倒。
3. 例题精算(4 方案 × 3 指标,全程不跳步)¶
选购电动车,指标:价格(万元,成本型)、续航(km,效益型)、评分(效益型)。权重沿用 D1 组合赋权的结果 w = (0.4, 0.35, 0.25)。
例子
价格 续航 评分
方案A 20 500 8
方案B 25 600 7
方案C 30 550 9
方案D 22 450 6
- 正向化价格列(max−x,max=30):(10, 5, 0, 8)。其余两列本就是效益型,不动。
- 向量标准化,每列除以平方和开方:
价格列 √(10²+5²+0²+8²)=√189=13.748 → (0.7274, 0.3637, 0, 0.5819) 续航列 √1115000=1055.93 → (0.4735, 0.5682, 0.5209, 0.4262) 评分列 √230=15.166 → (0.5275, 0.4616, 0.5934, 0.3956)
- 加权(分别乘 0.4 / 0.35 / 0.25):
价格 续航 评分 方案A 0.2910 0.1657 0.1319 方案B 0.1455 0.1989 0.1154 方案C 0 0.1823 0.1484 方案D 0.2328 0.1492 0.0989
- 理想解:Z⁺ = (0.2910, 0.1989, 0.1484)(每列最大);Z⁻ = (0, 0.1492, 0.0989)(每列最小)
- 距离(以方案A为例演示): d⁺ = √[(0.2910−0.2910)² + (0.1657−0.1989)² + (0.1319−0.1484)²] = √0.001374 = 0.0371 d⁻ = √[(0.2910−0)² + (0.1657−0.1492)² + (0.1319−0.0989)²] = √0.08604 = 0.2933
- 贴近度:CA = 0.2933 / (0.0371 + 0.2933) = 0.888
四个方案全算完:
| 方案 | d⁺ | d⁻ | 贴近度 C | 排名 |
|---|---|---|---|---|
| A | 0.0371 | 0.2933 | 0.888 | ① |
| D | 0.0911 | 0.2328 | 0.719 | ② |
| B | 0.1492 | 0.1546 | 0.509 | ③ |
| C | 0.2914 | 0.0595 | 0.170 | ④ |
结果解读:C 方案评分最高(9分)却排末位——因为价格权重 0.4 最大,而它 30 万的价格正向化后归零,短板被欧氏距离放大。这个例子正好演示了 TOPSIS "惩罚短板"的特性,写论文时可以拿来做结果分析。
4. 四种指标类型的正向化公式(必背)¶
D1 只讲了成本型,实际赛题里另外两种也常见,漏掉会直接算错:
| 类型 | 含义 | 正向化公式 |
|---|---|---|
| 极大型 | 越大越好(评分、产量) | 不用处理 |
| 极小型 | 越小越好(成本、污染) | x' = max − x 或 x' = 1/x(x>0) |
| 中间型 | 越接近某值越好(pH 值接近 7) | M = max|x − x_best|,x' = 1 − |x − x_best| / M |
| 区间型 | 落在 [a,b] 内最好(体温 36~37℃) | M = max(a − min(x), max(x) − b); x<a 时 x' = 1 − (a−x)/M;a≤x≤b 时 x' = 1;x>b 时 x' = 1 − (x−b)/M |
5. 代码:完整可复用的 TOPSIS¶
topsis.py
import numpy as np
def positivize(X, kinds, best=None, interval=None):
"""kinds 每列一个: 'max' / 'min' / 'mid' / 'interval'
best: {列索引: 最优值} 用于 mid
interval: {列索引: (a, b)} 用于 interval"""
X = np.asarray(X, dtype=float).copy()
best = best or {}
interval = interval or {}
for j, kind in enumerate(kinds):
col = X[:, j]
if kind == 'min':
X[:, j] = col.max() - col
elif kind == 'mid':
M = np.abs(col - best[j]).max()
X[:, j] = 1 - np.abs(col - best[j]) / M
elif kind == 'interval':
a, b = interval[j]
M = max(a - col.min(), col.max() - b)
X[:, j] = np.where(col < a, 1 - (a - col) / M,
np.where(col > b, 1 - (col - b) / M, 1.0))
return X
def topsis(X, kinds, w, **kw):
X = positivize(X, kinds, **kw)
Z = X / np.sqrt((X**2).sum(axis=0)) # 向量标准化
Zw = Z * w # 加权
best, worst = Zw.max(axis=0), Zw.min(axis=0)
d_plus = np.sqrt(((Zw - best )**2).sum(axis=1))
d_minus = np.sqrt(((Zw - worst)**2).sum(axis=1))
return d_minus / (d_plus + d_minus) # 贴近度,越大越优
# 验证本文例题
data = np.array([[20,500,8],[25,600,7],[30,550,9],[22,450,6]])
C = topsis(data, kinds=['min','max','max'], w=np.array([0.4,0.35,0.25]))
print(C.round(3)) # 期望 [0.888 0.509 0.170 0.719]
print(np.argsort(-C) + 1) # 期望 [1 4 2 3] 即 A > D > B > C
注意:kinds 依然是必填参数,延续 D1 勘误里定下的"易错步骤强制显式声明"原则。
6. 模糊综合评价:处理"说不清的边界"¶
TOPSIS 要求每个方案在每个指标上有确切数值。但很多赛题里的评价是模糊的——"服务质量好不好"没法给一个精确数字,只能说"60% 的人认为优,30% 认为良"。模糊综合评价就是处理这类问题的。
三个核心概念:
- 因素集 U:评价指标的集合,如 {服务, 价格, 环境}
- 评语集 V:评价等级的集合,如 {优, 良, 中, 差}
- 隶属度矩阵 R:m×n 矩阵,rij 表示"因素 i 属于评语 j 的程度",每行相加为 1。数据来源通常是问卷统计比例,或用隶属函数计算
最终结果 B = W ∘ R,其中 W 是 D1 算出的权重向量,∘ 是合成算子(常用矩阵乘法)。
7. 例题精算¶
例子
权重 W = (0.5, 0.3, 0.2) 对应 服务/价格/环境
隶属度矩阵 R:
优 良 中 差
服务 0.4 0.4 0.1 0.1
价格 0.2 0.3 0.4 0.1
环境 0.1 0.2 0.5 0.2
- B = W · R,逐列计算: 优:0.5×0.4 + 0.3×0.2 + 0.2×0.1 = 0.28 良:0.5×0.4 + 0.3×0.3 + 0.2×0.2 = 0.33 中:0.5×0.1 + 0.3×0.4 + 0.2×0.5 = 0.27 差:0.5×0.1 + 0.3×0.1 + 0.2×0.2 = 0.12
- 校验:0.28+0.33+0.27+0.12 = 1.00 ✓(B 各分量之和应为 1,不为 1 说明 R 的行没归一化)
- 最大隶属度原则:取最大值 0.33 对应的等级 → 结论"良"
- 加权平均法(给等级赋分 优=4 良=3 中=2 差=1): 0.28×4 + 0.33×3 + 0.27×2 + 0.12×1 = 2.77 → 介于"中"与"良"之间,偏良
易错
最大隶属度原则给出"良",但 0.33 / 0.28 / 0.27 三者非常接近,说明评价结果其实很分散——此时"良"这个结论并不稳健。当最大值不显著占优时,必须改用加权平均法,因为最大隶属度原则丢掉了其余所有信息。论文里两种都算、并说明为什么选其一,是很好的加分点。
8. 合成算子的选择¶
| 算子 | 计算方式 | 特点 | 何时用 |
|---|---|---|---|
| M(·, +) 加权平均型 | 普通矩阵乘法 | 保留全部信息,结果均衡 | 默认选它,国赛绝大多数情况 |
| M(∧, ∨) 主因素决定型 | 先取小再取大 | 只由最突出的因素决定,丢失信息多 | 只关心单一主导因素时 |
写论文时不要只说"采用模糊综合评价",要写明用了哪个合成算子及理由——这是区分"套模板"和"真懂"的细节。
9. 代码¶
fuzzy_eval.py
import numpy as np
def fuzzy_eval(W, R, scores=None):
W = np.asarray(W, dtype=float)
R = np.asarray(R, dtype=float)
assert np.allclose(R.sum(axis=1), 1), "R 每行必须归一化"
B = W @ R # M(·,+) 加权平均型合成
B = B / B.sum() # 保险起见再归一化
result = {'B': B, 'max_idx': int(np.argmax(B))}
if scores is not None: # 加权平均法,scores 如 [4,3,2,1]
result['score'] = float(B @ np.asarray(scores, dtype=float))
return result
W = [0.5, 0.3, 0.2]
R = [[0.4,0.4,0.1,0.1],
[0.2,0.3,0.4,0.1],
[0.1,0.2,0.5,0.2]]
out = fuzzy_eval(W, R, scores=[4,3,2,1])
print(out['B'].round(3), out['max_idx'], round(out['score'],3))
# 期望 [0.28 0.33 0.27 0.12] 1 2.77
10. 写作表达¶
评价类题目的完整叙述链条应该是四段式,每段一句话交代清楚:
论文里可以这么写
① 为什么要综合评价:本问需在 4 种电动车方案中择优,涉及 价格、续航、评分 等多个量纲不同且优劣方向不一致的指标,无法直接比较。
② 权重怎么来的:采用 AHP 与熵权法组合赋权确定指标权重,一致性检验 CR = 0.033 < 0.1,得权重向量 (0.40, 0.35, 0.25)。
③ 评价方法与关键处理:使用 TOPSIS 法排序。考虑到价格为极小型指标,先按 x' = max − x 完成正向化,再作向量标准化,以消除量纲影响。
④ 结果与合理性:各方案贴近度依次为 0.888、0.719、0.509、0.170,方案 A 最优。值得注意的是方案 C 虽评分最高,但因价格显著偏高而排名末位,说明 TOPSIS 对短板指标较为敏感,评价结果符合实际决策逻辑。
第 ④ 段的"值得注意的是…"这种句式很重要——它证明你解释了结果而不只是报了个数,是拿高分论文和普通论文的分水岭。
11. 今日任务清单¶
- [ ]
任务1:复现例题 —
把第 5 节代码跑通,确认输出是 [0.888 0.509 0.170 0.719]。跑不对就逐步打印中间矩阵,对照第 3 节的手算结果定位问题
- [ ]
任务2:处理中间型/区间型指标 —
给例题再加一列"电池温度"(区间型,最佳区间 20~30℃),自己编 4 个数值,用 positivize 的 interval 分支跑通
- [ ]
任务3:串联 D1 + D2 —
用 D1 的 entropy_weight 从任务2 的数据里算出权重,直接喂给 topsis——完整走一遍"数据→权重→排序"的链条,这是评价类赛题的标准解法
- [ ]
任务4:写作 —
套用第 10 节四段式模板,用任务3 的真实数字写一段完整的评价方法叙述
自查
自查:进 D3 之前答一遍¶
- TOPSIS 的贴近度公式分子是 d⁺ 还是 d⁻?为什么?
- 为什么 TOPSIS 用向量归一化而不是 min-max 归一化?(提示:min-max 会让最差方案某列直接归零)
- 模糊综合评价里,B 向量各分量之和应该等于多少?不等于说明哪一步错了?
- 什么情况下不该用最大隶属度原则?改用什么?
- 一道赛题给你 20 个城市 8 个指标的完整数据表,要求排名——你会怎么组合 D1 和 D2 学的方法?完整说出流程。
参考答案
参考答案¶
-
分子是 d⁻,即 C = d⁻ / (d⁺ + d⁻)。因为"离最差方案越远"意味着越好,把 d⁻ 放分子才能让 C 越大越优,与直觉方向一致。写成 d⁺ 会让排名完全颠倒。
-
因为 min-max 归一化会把每列的最小值强行压成 0,该方案在这个指标上的贡献被完全抹掉,且负理想解 Z⁻ 恒为全 0 向量,距离计算失去区分度。向量归一化(除以列平方和的开方)保留了各方案间的相对比例关系,只消除量纲不扭曲结构。
-
应等于 1。B = W·R,其中 W 各分量之和为 1、R 每行之和为 1,因此 B 各分量之和必然为 1。 不等于 1 说明:要么 R 的某一行没有归一化(隶属度之和不为 1),要么 W 没有归一化。代码里用
assert np.allclose(R.sum(axis=1), 1)提前拦住。 -
当最大隶属度不显著占优时不该用——比如 B = (0.28, 0.33, 0.27, 0.12),前三项非常接近,"良"这个结论并不稳健,而且最大隶属度原则丢掉了其余所有信息。 改用加权平均法:给等级赋分(优=4 良=3 中=2 差=1),算 B·scores = 2.77,落在"中"与"良"之间偏良,比单说"良"精确得多。论文里两种都算并说明取舍理由,是加分点。
-
标准流程如下(这就是评价类赛题的通用解法链条):
1. 数据预处理 缺失值/异常值处理 2. 正向化 逐列判断类型(极大/极小/中间/区间),统一成"越大越好" 3. 确定权重 熵权法(客观) + AHP(主观) → 组合权重 w = α·w_AHP + (1−α)·w_entropy 4. TOPSIS 向量标准化 → 加权 → 定 Z⁺/Z⁻ → 算 d⁺/d⁻ → 贴近度 C 5. 排序 按 C 降序输出 20 个城市的排名 6. 敏感性分析 改变 α 取值(如 0.3/0.5/0.7),看排名是否稳定第 6 步很多人会漏,但它是论文里"模型检验"一节的核心内容——如果 α 微调就导致排名大幅变动,说明结论不可靠,必须在论文里讨论。8 个指标接近 AHP 的判断上限(7±2),若 CR 难以通过,可考虑分层构造判断矩阵(先给指标分 2~3 组,组内比较后再组间比较)。