ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

TOPSIS优劣距离法:多属性决策中的量化排序与实战应用

TOPSIS优劣距离法:多属性决策中的量化排序与实战应用 1. 从“拍脑袋”到“算距离”为什么我们需要Topsis优劣距离法在数学建模竞赛或者任何需要做决策的场景里我们常常会遇到一个经典难题面对一堆各有千秋的选项到底哪个才是“最好”的比如评选优秀学生有人成绩好但实践少有人实践强但成绩一般再比如选择投资项目A项目回报高但风险大B项目风险低但周期长。这时候如果还靠“拍脑袋”或者简单加权平均往往说服力不足也容易失之偏颇。Topsis法全称“逼近理想解排序法”就是为了解决这个“多属性决策”问题而生的。它的核心思想非常直观且符合人类直觉最好的方案应该离“理想中最好的那个点”最近同时离“理想中最差的那个点”最远。想象一下在一个多维空间里每个方案都是一个点坐标由它的各项指标如成绩、实践、风险、回报决定。我们先虚构出两个“极端”点一个是所有指标都取最优值的“理想解”乌托邦另一个是所有指标都取最劣值的“负理想解”反乌托邦。然后我们计算每个真实方案与这两个“极端”点的距离。最后通过一个相对贴近度公式就能给所有方案排出一个清晰、量化的优劣顺序。我第一次在国赛中用Topsis法是处理一个城市宜居性评价的题目。当时手头有十几个城市的几十项经济、环境、社会数据评委老师直接问“你的排名依据是什么凭什么说A城市比B城市好0.5分”如果没有Topsis这种有严格数学推导的距离计算仅靠主观赋权加总在答辩环节会非常被动。而Topsis法提供的“距离”概念让评价结果变得可解释、可追溯——每个城市的得分都能清楚地告诉别人“它离理想状态有多近离最差状态有多远。”这种客观性和说服力是很多评价方法不具备的。2. Topsis法的“三步走”核心流程拆解Topsis法听起来高级但实现起来有清晰的标准化步骤。我们可以把它理解为一个“数据清洗、空间构建、距离测量”的三步流程。下面我结合一个具体的例子来拆解假设我们要评价4款手机A, B, C, D主要看3个指标性能得分越高越好、价格越低越好、续航越长越好。原始数据如下表方案性能分价格元续航小时手机A90500010手机B80400012手机C7030008手机D603500152.1 第一步数据规范化——把“苹果和橘子”放在一起比第一步也是最关键的一步叫做数据规范化。我们的指标单位不同分、元、小时量纲也不同性能90分和价格5000元数值上差了两个数量级。如果直接计算距离价格指标会完全主导结果因为它的绝对数值太大。这就像用“米”和“毫米”去量同一个东西却不做单位换算比较毫无意义。规范化的目的就是消除量纲和数量级的影响把所有指标压缩到同一个尺度上通常是在[0,1]区间内。最常用的是向量规范化法。它的公式是对于原始矩阵中的每一个元素 \( x_{ij} \)第i个方案的第j个指标其规范化值 \( z_{ij} \) 为 \[ z_{ij} \frac{x_{ij}}{\sqrt{\sum_{i1}^{m} x_{ij}^2}} \]简单说就是把该指标下所有方案的数值看成是一个向量。每个数值除以这个向量的模长所有数值平方和再开根号。这样处理之后每个指标下所有方案规范化值的平方和等于1。我们来计算“性能”这个指标首先计算分母模长\( \sqrt{90^2 80^2 70^2 60^2} \sqrt{8100640049003600} \sqrt{23000} \approx 151.66 \)然后计算每个方案的规范化值手机A: \( 90 / 151.66 \approx 0.593 \)手机B: \( 80 / 151.66 \approx 0.527 \)手机C: \( 70 / 151.66 \approx 0.462 \)手机D: \( 60 / 151.66 \approx 0.396 \)对“价格”和“续航”指标重复此过程得到规范化矩阵Z。这里有一个极易踩坑的点价格是成本型指标越小越好而性能和续航是效益型指标越大越好。在规范化之前我们通常需要将成本型指标“正向化”。最常用的方法是取倒数或用最大值减去该值。但注意如果原始数据中有0或负值取倒数会出错。更稳健的方法是使用“倒数法”或“最小最大值法”进行正向化但必须在规范化之前完成。例如对价格用倒数法新价格 1 / 原价格。这样价格越低倒数后的值越大就变成了效益型指标。为了示例连贯我们假设已对价格进行正向化处理例如用“性价比”概念转换并完成规范化得到如下矩阵数值为假设便于演示方案性能规范后价格规范后已正向化续航规范后手机A0.5930.4810.535手机B0.5270.6020.642手机C0.4620.7220.428手机D0.3960.6310.802注意在实际建模论文中必须明确写出你对成本型指标的处理方法。我见过很多队伍在这一步出错导致整个模型结果扭曲。一个检查方法是正向化后所有指标都应该满足“数值越大代表该方面表现越好”。2.2 第二步确定理想解与负理想解——找到“天花板”和“地板”有了规范化矩阵我们就可以定义那个多维空间里的“理想点”和“负理想点”了。这一步非常直观理想解\( Z^ \)由每个指标在规范化矩阵中的最大值构成。因为经过规范化和正向化所有指标都是越大越好。负理想解\( Z^- \)由每个指标在规范化矩阵中的最小值构成。根据上表理想解 \( Z^ (0.593, \ 0.722, \ 0.802) \) 性能最大0.593价格正向化值最大0.722续航最大0.802负理想解 \( Z^- (0.396, \ 0.481, \ 0.428) \) 性能最小0.396价格正向化值最小0.481续航最小0.428这两个点在实际中可能并不存在没有一款手机能在所有指标上都达到极致但它们为我们提供了评价的绝对参照系。2.3 第三步计算距离与相对贴近度——用尺子量出优劣接下来就是计算每个真实方案点到理想解和负理想解的“距离”。这里通常使用欧几里得距离即直线距离。公式如下到理想解的距离\[ D_i^ \sqrt{\sum_{j1}^{n} w_j (z_{ij} - z_j^)^2 } \] 到负理想解的距离\[ D_i^- \sqrt{\sum_{j1}^{n} w_j (z_{ij} - z_j^-)^2 } \]公式里的 \( w_j \) 是第j个指标的权重。这是Topsis法另一个核心也是主观性可能介入的地方。如果所有指标同等重要则 \( w_j 1/n \)。但通常我们需要用熵权法、AHP层次分析法等来确定权重。这里为了简化假设权重相等各1/3。以手机A为例\( D_A^ \sqrt{ \frac{1}{3}[(0.593-0.593)^2 (0.481-0.722)^2 (0.535-0.802)^2] } \approx \sqrt{ \frac{1}{3}[0 0.0581 0.0713] } \approx \sqrt{0.0431} \approx 0.208 \)\( D_A^- \sqrt{ \frac{1}{3}[(0.593-0.396)^2 (0.481-0.481)^2 (0.535-0.428)^2] } \approx \sqrt{ \frac{1}{3}[0.0388 0 0.0114] } \approx \sqrt{0.0167} \approx 0.129 \)最后计算每个方案的相对贴近度 \( C_i \) \[ C_i \frac{D_i^-}{D_i^ D_i^-} \]\( C_i \) 的取值范围在0到1之间。\( C_i \) 越大说明该方案离理想解越近离负理想解越远也就越好。手机A的贴近度\( C_A 0.129 / (0.208 0.129) \approx 0.383 \)同理计算出所有手机的贴近度并排序就能得到最终的综合评价排名。这个排名综合考虑了所有指标并且有了明确的数学含义贴近度0.6的方案就是比0.5的方案更接近理想状态。3. 权重赋值Topsis法的“灵魂”与熵权法实战在上面的例子中我们假设了所有指标权重相等。但在实际建模中这往往是不合理的。性能、价格、续航对消费者的重要程度显然不同。权重赋值是Topsis法最具“灵魂”的一步它直接决定了评价的导向。赋权方法主要分两类主观赋权法如AHP和客观赋权法如熵权法。在数学建模中为了体现客观公正熵权法的使用频率极高。3.1 熵权法原理用数据自身的“混乱程度”决定话语权熵源于热力学在信息论中代表信息的混乱程度或不确定性。熵权法的思想很巧妙如果一个指标下各个方案的数据差异很大即该指标的数据分布很“混乱”包含的信息量大那么这个指标在区分方案优劣时就越重要应该赋予更大的权重。反之如果某个指标下所有方案的数据都差不多熵值大但差异小实际信息量小说明这个指标对决策的帮助不大权重就应该小。它的计算步骤紧密衔接在Topsis的规范化之后计算比重对于规范化后的矩阵假设已处理过指标类型计算每个数值在该指标下的比重 \( p_{ij} z_{ij} / \sum_{i1}^{m} z_{ij} \)。这里用的是规范化后的值 \( z_{ij} \)。计算信息熵计算第j个指标的信息熵 \( e_j -k \sum_{i1}^{m} p_{ij} \ln(p_{ij}) \)其中 \( k 1/\ln(m) \) 是归一化常数保证 \( e_j \) 在[0,1]之间。计算差异系数\( d_j 1 - e_j \)。熵 \( e_j \) 越小差异系数 \( d_j \) 越大说明该指标越重要。确定权重将差异系数归一化得到权重 \( w_j d_j / \sum_{j1}^{n} d_j \)。3.2 熵权法实操中的两大陷阱与解决方案听起来很顺畅但实操中坑不少。陷阱一对数计算遇到零值。在计算 \( p_{ij} \ln(p_{ij}) \) 时如果某个 \( p_{ij} 0 \)\( \ln(0) \) 是没有定义的。很多初学者在这里程序报错。解决方案是做一个微小的平移。在计算比重前可以给整个规范化矩阵的每个元素加上一个极小的正数如1e-10或者直接判断当 \( p_{ij}0 \) 时令 \( p_{ij} \ln(p_{ij}) 0 \)。在编程实现时如MATLAB或Python务必加入这个判断。陷阱二熵权法完全依赖数据可能违背常识。这是熵权法最大的争议点。比如评价城市安全如果所有城市的“万人刑事案件发生率”数据都很接近差异小熵权法会赋予这个指标极低的权重。但从常识看安全是极其重要的维度权重不应该这么低。解决方案是使用组合赋权。常用的是“AHP主观赋权 熵权法客观赋权”进行加权综合。例如主观权重占40%客观权重占60%。这样既考虑了专家经验又尊重了数据规律模型的说服力更强。在我参与评审的一次比赛中有支队伍直接用熵权法给“GDP增长率”赋了很低的权因为所有城市的数据差异不大。结果被评委质疑“经济增长的重要性能完全由这一年的数据差异决定吗”他们后来在论文中补充了组合赋权的敏感性分析才挽回了局面。4. Topsis法的编程实现从MATLAB到Python的代码细节理论懂了最终要落地到代码。无论是MATLAB还是Python实现Topsis的流程都是标准化的。这里我给出一个注重鲁棒性和可读性的Python实现示例并附上关键注释。import numpy as np import pandas as pd def topsis(data, weightsNone, impactsNone): TOPSIS综合评价函数。 参数: data : numpy.ndarray 或 pandas.DataFrame 原始决策矩阵行是方案列是指标。 weights : list, optional 各指标的权重向量。如果为None则默认等权。 impacts : list, optional 各指标的影响方向表示效益型越大越好-表示成本型越小越好。 如果为None则默认所有指标为效益型。 返回: result_df : pandas.DataFrame 包含各方案排序结果的数据框包含得分和排名。 # 转换为numpy数组便于计算 X np.array(data, dtypefloat) m, n X.shape # m个方案n个指标 # 默认权重等权 if weights is None: weights np.ones(n) / n else: weights np.array(weights, dtypefloat) weights weights / weights.sum() # 归一化确保和为1 # 默认影响方向全部为效益型 if impacts is None: impacts [] * n # 1. 数据正向化 X_normalized X.copy() for j in range(n): if impacts[j] -: # 成本型指标采用倒数法正向化确保无零值 col X[:, j] # 避免除零如果最小值0则进行平移 if np.min(col) 0: col col - np.min(col) 1e-10 # 平移至正数区间 X_normalized[:, j] 1 / col # 效益型指标无需处理 # 2. 向量规范化 norm_factors np.sqrt(np.sum(X_normalized ** 2, axis0)) Z X_normalized / norm_factors # 规范化矩阵 # 3. 计算加权规范化矩阵 Z_weighted Z * weights # 4. 确定理想解和负理想解 ideal_best np.max(Z_weighted, axis0) ideal_worst np.min(Z_weighted, axis0) # 5. 计算距离 # 使用欧几里得距离axis1表示对每个方案计算 dist_best np.sqrt(np.sum((Z_weighted - ideal_best) ** 2, axis1)) dist_worst np.sqrt(np.sum((Z_weighted - ideal_worst) ** 2, axis1)) # 6. 计算相对贴近度 score dist_worst / (dist_best dist_worst 1e-10) # 加极小值防止除零 # 7. 排序 rank score.argsort()[::-1] 1 # 得分从高到低排序排名从1开始 # 整理结果 result_df pd.DataFrame({ 方案: [f方案{i1} for i in range(m)], Topsis得分: score, 排名: rank }) result_df result_df.sort_values(排名).reset_index(dropTrue) return result_df, Z_weighted, ideal_best, ideal_worst # 示例使用之前的手机数据价格已预先正向化处理 data np.array([ [90, 1/5000, 10], # 手机A价格用倒数表示 [80, 1/4000, 12], # 手机B [70, 1/3000, 8], # 手机C [60, 1/3500, 15] # 手机D ]) # 注意由于价格用了倒数已经是越大越好所以所有指标都是效益型() impacts [, , ] # 假设权重为性能0.5价格0.3续航0.2 weights [0.5, 0.3, 0.2] result_df, Z_weighted, best, worst topsis(data, weightsweights, impactsimpacts) print(加权规范化矩阵 Z_weighted:) print(Z_weighted) print(\n理想解 (best):, best) print(负理想解 (worst):, worst) print(\n综合评价结果:) print(result_df)这段代码的几个关键实现细节成本型指标处理采用了倒数法并加入了防零处理if np.min(col) 0。这是工业级代码的必备考虑。距离计算在计算贴近度的分母中加了1e-10防止出现距离均为零的极端情况导致除零错误。灵活性通过impacts参数灵活指定指标类型通过weights参数支持自定义权重方便与熵权法等模块对接。输出丰富不仅返回排名和得分还返回了中间过程的加权矩阵和理想解便于后续的敏感性分析或可视化。对于MATLAB用户思路完全一致只是矩阵运算语法不同。核心是利用./进行点除利用sum(,1)或sum(,2)按维度求和利用max和min函数求最值。编写时同样要注意处理可能出现的除零情况。5. 进阶应用与模型优化让Topsis更强大、更可靠掌握了基础Topsis和熵权法已经能解决大部分评价类问题。但要拿高分尤其是在国赛、美赛这种高手云集的竞赛中还需要考虑模型的深化和优化。5.1 指标动态权重与敏感性分析权重不是一成不变的。在评价区域发展水平时也许十年前“固定资产投资”权重很高但现在“科技创新投入”的权重应该上升。我们可以引入时间序列计算每一年的熵权观察权重随时间的变化趋势这本身就是一个很好的分析点。更重要的环节是敏感性分析。评委常问“你的结果对权重的变化敏感吗如果某个指标的权重微调排名会大变吗”如果排名对权重极其敏感说明你的评价体系不稳定结论不可靠。做法是固定其他权重让某个关键指标的权重在合理范围内波动例如±10%观察排名变化。如果前几名始终稳定则模型稳健如果稍有变动就“翻盘”则需要在论文中讨论这种不确定性并提出可能需要结合其他方法如模糊综合评价来辅助决策。5.2 结合其他模型AHP-熵权-TOPSIS组合拳单独使用Topsis有时会显得单薄。与AHP层次分析法结合是经典套路。AHP确定主观权重通过专家打分构建判断矩阵计算出一套权重 \( W_s \)。熵权法确定客观权重基于数据计算出一套权重 \( W_o \)。组合赋权采用线性加权如 \( W \alpha W_s (1-\alpha)W_o \)其中 \( \alpha \) 是主观偏好系数可以通过优化或经验设定常用0.3-0.5。也可以采用更复杂的博弈论组合赋权法寻找使主客观权重差异最小的组合。Topsis进行排序将组合权重 \( W \) 代入Topsis模型计算。这套组合拳在论文中显得思考周全既有理论依据AHP又有数据支撑熵权法最后用成熟方法Topsis集成输出结果。5.3 处理模糊信息模糊Topsis现实中的数据往往不是精确值。比如评价服务质量“满意度”可能是“高、中、低”这样的语言变量。这时可以用三角模糊数或梯形模糊数来表示指标值。模糊Topsis的核心步骤与经典Topsis一致但计算的是模糊数之间的距离如顶点距离最后得到的贴近度也是一个模糊数需要通过去模糊化如计算重心得到精确的排序值。这在评价含有主观、定性指标的系统时非常有用。5.4 结果可视化让结论一目了然好的建模论文离不开出色的可视化。对于Topsis结果除了表格可以尝试雷达图展示每个方案在各个指标上规范化后的表现直观对比优劣势。散点图以 \( D_i^ \) 为横轴\( D_i^- \) 为纵轴画散点图。越靠近右下角离理想解近离负理想解远的点其综合表现越好。排序条形图清晰展示最终得分和排名顺序。这些图表不仅能提升论文颜值更能帮助读者评委快速抓住核心结论。6. 避坑指南Topsis实战中那些“教科书不会写”的教训走过这么多弯路总结几个最容易失分、也最容易出错的点希望你能避开。第一坑指标正向化方法选择不当。这是新手第一道坎。除了倒数法还有“最小最大值法”对于成本型指标令 \( x (\max(x) - x) / (\max(x) - \min(x)) \)。倒数法对原始数据的数值分布敏感如果数据量级差异大倒数后可能放大噪声。最小最大值法能将所有指标归一化到[0,1]但受极端值影响大。我的经验是如果数据均为正且没有零值可以尝试倒数法否则优先使用最小最大值法并在论文中说明理由。更稳妥的做法是在附录中展示不同正向化方法的结果进行稳健性检验。第二坑忽略权重和为1的检验。无论是熵权法还是AHP最终得到的权重向量必须进行归一化确保和为1。这是一个简单的步骤但很多人在编程计算后忘记检查直接代入距离公式导致距离尺度失真。务必在代码中加入weights weights / np.sum(weights)这样的归一化语句。第三坑对结果不做任何检验和讨论。算出排名就结束了这是大忌。你必须问自己这个排名符合常识吗如果不符合是数据问题、权重问题还是模型本身不适用一定要做敏感性分析哪怕只是简单分析一两个关键指标权重变动的影响。在论文中设置一个“模型检验与结果分析”小节讨论排名的合理性、模型的局限性这能体现你的批判性思维和模型的完整性。第四坑误用Topsis的适用场景。Topsis适用于方案有限、指标明确的排序问题。如果方案数量极多如上万条或者指标间存在强烈的非线性交互关系Topsis可能不是最佳选择。例如在预测问题上Topsis无能为力。在建模时首先要论证为什么选择Topsis它的假设如指标可加性、独立性在你的问题中是否大致成立。我记得有一次辅导学生他们用Topsis评价共享单车投放点其中一个指标是“周边人口密度”另一个是“地铁站距离”。这两个指标实际上有相关性地铁站附近人口密度高。直接使用Topsis相当于重复计算了部分信息。后来他们引入了主成分分析先对指标进行降维、去除相关性再用主成分得分作为Topsis的新指标结果合理了很多。掌握Topsis不仅仅是掌握一个算法更是掌握一套系统化的多属性决策思维。从数据预处理到权重确定从距离计算到结果检验每一步都需要严谨的推敲和清晰的表述。把它当作一把好用的尺子但也要知道这把尺子的量程和精度。在下次面对复杂的评价决策时希望你能 confidently 说出“我们来用Topsis算一下距离。”
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进