ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

TOPSIS优劣解距离法:多属性决策与综合评价的Python实战指南

TOPSIS优劣解距离法:多属性决策与综合评价的Python实战指南 1. 从“选谁最好”到“谁离最优最接近”TOPSIS法的核心思想在数学建模、管理决策、甚至我们日常的选择困难症里常常会遇到一个经典问题面对一堆各有优劣的方案到底该选哪一个比如公司要采购一批设备有价格、性能、售后、能耗等多个指标或者评选优秀员工要看业绩、能力、团队协作等多个维度。这些指标往往单位不同、量纲不一有的越大越好如性能有的越小越好如价格直接比较就像拿苹果和橙子比大小无从下手。这时候一个朴素的想法是能不能先想象出一个“完美”的方案它所有指标都达到了理论上的最佳值价格最低、性能最高、能耗最小……再想象出一个“最差”的方案所有指标都是最糟糕的。那么一个现实中的方案如果它离那个“完美”方案越近同时离那个“最差”方案越远它不就应该是越好的选择吗这个听起来非常直观且符合人类思维习惯的想法就是TOPSISTechnique for Order Preference by Similarity to Ideal Solution法中文常译为“优劣解距离法”或“逼近理想解排序法”的核心。它不关心指标之间复杂的相互影响而是用一种几何上的“距离”来衡量方案的优劣。这里的“距离”通常指欧氏距离也就是多维空间中点与点之间的直线距离。通过计算每个方案与理想最优解和理想最劣解的距离并综合这两个距离得到一个相对贴近度最终根据这个贴近度对所有方案进行排序值越大表示方案越优。我第一次在数学建模竞赛中用到TOPSIS法是在处理一个城市宜居性评价的问题。当时有十几个城市评价指标包括人均GDP、绿化率、PM2.5浓度、房价收入比、医院床位数量等等。这些指标正负向混杂单位天差地别。TOPSIS法就像一把尺子清晰地量出了每个城市与“理想宜居城市”和“理想不宜居城市”的差距最终排序结果不仅合理而且过程透明易于向评委解释。从那以后它就成了我处理多属性决策问题时的“首选工具”之一。2. TOPSIS法的四步操作流程从原始数据到最终排序TOPSIS法的实现可以清晰地分为四个步骤数据预处理、确定权重、计算距离、排序。下面我们结合一个具体的例子来拆解每一步。假设我们要评价四款手机A, B, C, D考虑三个指标价格元成本型越小越好、电池容量mAh效益型越大越好、摄像头像素万效益型越大越好。原始数据如下表方案价格元电池容量mAh摄像头像素万手机A2999450048手机B3999500064手机C2599400032手机D349955001082.1 第一步数据预处理——统一量纲与方向原始数据直接计算距离是没有意义的因为价格是几千的量级像素是几十的量级单位也不同。此外价格是越小越好成本型而电池和像素是越大越好效益型。预处理的目标就是消除量纲影响并将所有指标转化为效益型即数值越大越优。1. 指标正向化统一方向对于成本型指标如价格我们需要将其转化为效益型。常用方法是取倒数或做差值转换。这里采用更通用的方法对于成本型指标用该指标中的最大值减去每个值这样原来的最小值最好就会变成最大值。价格指标成本型转化新值 Max(价格) - 原价格Max(价格) 3999手机A新价格 3999 - 2999 1000手机B新价格 3999 - 3999 0手机C新价格 3999 - 2599 1400手机D新价格 3999 - 3499 500 转化后价格指标也变成了“数值越大越好”。2. 数据标准化消除量纲即使方向一致了数值大小差异依然存在。标准化常用向量归一化法。对于矩阵中的每一个元素 \(x_{ij}\)第i个方案的第j个指标其标准化值 \(z_{ij}\) 计算公式为 \[ z_{ij} \frac{x_{ij}}{\sqrt{\sum_{i1}^{m} x_{ij}^2}} \] 其中m是方案个数这里m4。 这个公式的本质是将每个指标的所有数据看作一个向量然后让这个向量的模长变为1。计算过程如下价格列已正向化数值为 [1000, 0, 1400, 500]分母 √(1000² 0² 1400² 500²) √(1,000,000 0 1,960,000 250,000) √3,210,000 ≈ 1791.65手机A标准化价格 1000 / 1791.65 ≈ 0.558手机B标准化价格 0 / 1791.65 0手机C标准化价格 1400 / 1791.65 ≈ 0.781手机D标准化价格 500 / 1791.65 ≈ 0.279电池容量列数值为 [4500, 5000, 4000, 5500]分母 √(4500² 5000² 4000² 5500²) √(20,250,000 25,000,000 16,000,000 30,250,000) √91,500,000 ≈ 9565.56标准化值分别为0.470, 0.523, 0.418, 0.575摄像头像素列数值为 [48, 64, 32, 108]分母 √(48² 64² 32² 108²) √(2304 4096 1024 11664) √19088 ≈ 138.16标准化值分别为0.347, 0.463, 0.232, 0.782得到标准化决策矩阵 Z方案标准化价格标准化电池容量标准化摄像头像素手机A0.5580.4700.347手机B00.5230.463手机C0.7810.4180.232手机D0.2790.5750.782注意这里演示的是最常用的向量归一化。还有一种方法是极差标准化Min-Max Normalization但向量归一化在TOPSIS中更普遍因为它能保持各方案间相对差距的某种比例关系。2.2 第二步确定指标权重——熵权法实战在标准化矩阵Z的基础上我们通常认为不同指标的重要性不同。比如你可能觉得电池容量比像素更重要。权重确定方法有主观如AHP层次分析法和客观如熵权法两种。熵权法是一种完全基于数据波动性的客观赋权法波动越大信息量越大的指标权重越高。这里我们演示熵权法的计算。1. 计算比重 \(p_{ij}\)\[ p_{ij} \frac{z_{ij}}{\sum_{i1}^{m} z_{ij}} \] 确保每一列的所有比重之和为1。 以标准化价格列为例总和 0.558 0 0.781 0.279 1.618手机A比重 0.558 / 1.618 ≈ 0.345手机B比重 0 / 1.618 0手机C比重 0.781 / 1.618 ≈ 0.483手机D比重 0.279 / 1.618 ≈ 0.172 同理计算其他列。2. 计算第j项指标的熵值 \(e_j\)\[ e_j -\frac{1}{\ln(m)} \sum_{i1}^{m} p_{ij} \ln(p_{ij}) \] 其中 m4ln(4)≈1.386。当 \(p_{ij}0\) 时规定 \(p_{ij}\ln(p_{ij}) 0\)。 计算价格列的熵值e_价格 -1/1.386 * [0.345ln(0.345) 0ln(0) 0.483ln(0.483) 0.172ln(0.172)]≈ -0.722 * [0.345*(-1.064) 0 0.483*(-0.728) 0.172*(-1.760)]≈ -0.722 * [(-0.367) 0 (-0.352) (-0.303)] -0.722 * (-1.022) ≈ 0.738 同理计算得过程略e_电池 ≈ 0.983e_像素 ≈ 0.8193. 计算差异系数 \(g_j\) 和权重 \(w_j\)\[ g_j 1 - e_j \] \[ w_j \frac{g_j}{\sum_{j1}^{n} g_j} \] 其中n是指标数量这里n3。g_价格 1 - 0.738 0.262g_电池 1 - 0.983 0.017g_像素 1 - 0.819 0.181差异系数总和 0.262 0.017 0.181 0.460w_价格 0.262 / 0.460 ≈ 0.570w_电池 0.017 / 0.460 ≈ 0.037w_像素 0.181 / 0.460 ≈ 0.393从熵权结果看价格指标的权重最高0.57因为经过正向化后其数据在不同手机间波动最大有0有1400包含信息最多电池容量权重极低0.037因为其标准化后数据相对接近0.418~0.575区分度小。这是一个重要的实操洞察熵权法完全依赖数据本身若某指标所有方案数值很接近其权重就会很低这可能与我们的主观认知冲突。在实际建模中往往需要将熵权法得到的结果与主观权重如AHP法结合进行组合赋权。得到权重向量 W [0.570, 0.037, 0.393]。4. 构造加权标准化矩阵 V将标准化矩阵 Z 的每一列乘以其对应的权重。 \[ v_{ij} w_j \times z_{ij} \] 例如手机A的加权价格 0.570 * 0.558 ≈ 0.318。 最终得到加权标准化矩阵 V方案加权价格加权电池容量加权摄像头像素手机A0.3180.0170.136手机B00.0190.182手机C0.4450.0150.091手机D0.1590.0210.3072.3 第三步计算距离——寻找理想点与负理想点1. 确定理想最优解 \(V^\) 和理想最劣解 \(V^-\)理想最优解 \(V^\) 由每个指标在加权矩阵 V 中的最大值构成因为所有指标都已转为效益型。 理想最劣解 \(V^-\) 由每个指标在加权矩阵 V 中的最小值构成。 从矩阵 V 中按列取最大、最小值\(V^\) [ max(价格列), max(电池列), max(像素列) ] [0.445, 0.021, 0.307]\(V^-\) [ min(价格列), min(电池列), min(像素列) ] [0, 0.015, 0.091]2. 计算各方案到 \(V^\) 和 \(V^-\) 的欧氏距离计算方案 \(i\) 到 \(V^\) 的距离 \(D_i^\) 和到 \(V^-\) 的距离 \(D_i^-\)。 \[ D_i^ \sqrt{\sum_{j1}^{n} (v_{ij} - v_j^)^2 } \] \[ D_i^- \sqrt{\sum_{j1}^{n} (v_{ij} - v_j^-)^2 } \] 以手机A为例\(D_A^ \sqrt{(0.318-0.445)^2 (0.017-0.021)^2 (0.136-0.307)^2} \sqrt{(-0.127)^2 (-0.004)^2 (-0.171)^2} \sqrt{0.01613 0.00002 0.02924} \sqrt{0.04539} \approx 0.213\)\(D_A^- \sqrt{(0.318-0)^2 (0.017-0.015)^2 (0.136-0.091)^2} \sqrt{(0.318)^2 (0.002)^2 (0.045)^2} \sqrt{0.10112 0.000004 0.00203} \sqrt{0.10315} \approx 0.321\) 同理计算其他手机手机B: \(D_B^ \approx 0.307, \quad D_B^- \approx 0.182\)手机C: \(D_C^ \approx 0.236, \quad D_C^- \approx 0.445\)手机D: \(D_D^ \approx 0.171, \quad D_D^- \approx 0.394\)2.4 第四步计算相对贴近度并排序相对贴近度 \(C_i\) 定义为 \[ C_i \frac{D_i^-}{D_i^ D_i^-} \] \(C_i\) 的取值范围在0到1之间。\(C_i\) 越大说明该方案离理想最优解越近离理想最劣解越远方案越优。 计算各手机贴近度手机A: \(C_A 0.321 / (0.213 0.321) \approx 0.601\)手机B: \(C_B 0.182 / (0.307 0.182) \approx 0.372\)手机C: \(C_C 0.445 / (0.236 0.445) \approx 0.653\)手机D: \(C_D 0.394 / (0.171 0.394) \approx 0.697\)排序结果\(C_D (0.697) C_C (0.653) C_A (0.601) C_B (0.372)\) 因此四款手机的优劣排序为手机D 手机C 手机A 手机B。这个结果可能有些反直觉最便宜的手机C2599元排名第二而最贵的手机B3999元排名垫底。这正是TOPSIS综合权衡的结果在价格权重很高0.57的情况下手机C和A在价格上优势巨大手机D虽然价格不低但其摄像头像素权重0.393的绝对优势弥补了价格的劣势手机B则在两个高权重指标价格和像素上均无优势。3. TOPSIS法的Python代码实现与解析手动计算适用于教学和理解原理但在实际建模中面对几十个方案、十几个指标的数据我们必须借助编程。下面用Python实现一个完整的、带有熵权法的TOPSIS评价函数并逐段解析。import numpy as np import pandas as pd def topsis(data, weightNone, positive_indicesNone): 实现TOPSIS优劣解距离法排序 Parameters: ----------- data : ndarray or DataFrame 决策矩阵行为方案列为指标。 weight : ndarray, optional 各指标的权重向量。默认为None使用熵权法计算。 positive_indices : list, optional 效益型指标的列索引列表从0开始。默认为None表示所有指标均为效益型。 若提供则会将非效益型指标成本型等进行正向化处理。 Returns: -------- result_df : DataFrame 包含各方案到正/负理想解距离、相对贴近度及排序的结果DataFrame。 # 转换为numpy数组便于计算 X np.array(data, dtypefloat) m, n X.shape # m个方案n个指标 # 1. 指标正向化 if positive_indices is not None: # 创建所有列的索引列表 all_indices set(range(n)) # 找出需要正向化的成本型等指标索引不在positive_indices中的列 cost_indices list(all_indices - set(positive_indices)) # 对于成本型指标使用“最大值-原值”进行正向化 for idx in cost_indices: col_max np.max(X[:, idx]) X[:, idx] col_max - X[:, idx] # 如果所有指标都是效益型则跳过此步 # 2. 数据标准化向量归一化 Z X / np.sqrt(np.sum(X**2, axis0)) # 3. 确定权重熵权法 if weight is None: # 计算比重矩阵 P Z / np.sum(Z, axis0) # 避免log(0)的情况将0替换为一个极小值 P np.where(P 0, 1e-10, P) # 计算熵值 e -np.sum(P * np.log(P), axis0) / np.log(m) # 计算差异系数 g 1 - e # 计算权重 weight g / np.sum(g) else: weight np.array(weight, dtypefloat) # 确保权重和为1 weight weight / np.sum(weight) print(f各指标权重: {weight}) # 4. 计算加权标准化矩阵 V Z * weight # 5. 确定理想解和负理想解 V_positive np.max(V, axis0) # 理想最优解 V_negative np.min(V, axis0) # 理想最劣解 # 6. 计算各方案到理想解的距离 # 使用欧氏距离axis1表示对每一行方案计算 D_positive np.sqrt(np.sum((V - V_positive) ** 2, axis1)) D_negative np.sqrt(np.sum((V - V_negative) ** 2, axis1)) # 7. 计算相对贴近度 C D_negative / (D_positive D_negative) # 8. 排序降序贴近度越大越好 rank np.argsort(-C) 1 # argsort返回升序索引取负变降序1使排名从1开始 # 整理结果到DataFrame result_df pd.DataFrame({ 方案: [f方案{i1} for i in range(m)], D_positive: D_positive, D_negative: D_negative, C: C, Rank: rank }) # 按排名排序 result_df result_df.sort_values(Rank).reset_index(dropTrue) return result_df, weight # 使用示例 if __name__ __main__: # 示例数据4个方案3个指标 # 列顺序价格成本型电池容量效益型摄像头像素效益型 data_matrix np.array([ [2999, 4500, 48], # 方案1 [3999, 5000, 64], # 方案2 [2599, 4000, 32], # 方案3 [3499, 5500, 108] # 方案4 ]) # 指定哪些列是效益型指标从0开始计数 # 这里第1列索引1电池和第2列索引2像素是效益型 # 第0列价格是成本型函数会自动正向化 positive_idx [1, 2] # 调用TOPSIS函数 result, calculated_weights topsis(data_matrix, positive_indicespositive_idx) print(TOPSIS综合评价结果) print(result)代码关键点解析与避坑指南正向化逻辑的通用性代码中通过positive_indices参数让用户指定哪些列是效益型其余自动视为成本型并进行“最大值-原值”处理。这是一种常见处理方式。实际上指标类型还有区间型、固定型等如需处理可以扩展正向化函数例如对于区间型指标[a, b]计算每个值与区间端点的距离后再处理。熵权法中的“除零”问题计算熵值时如果某个p_ij为00 * ln(0)在数学上无定义。代码中P np.where(P 0, 1e-10, P)用了一个极小的正数1e-10替代0这是一个标准且稳定的处理技巧。权重的归一化无论用户输入自定义权重还是熵权法计算权重最后都进行了归一化weight weight / np.sum(weight)确保权重和为1。这是一个好习惯能避免因权重和不为1导致的距离计算尺度问题。距离公式的向量化计算np.sqrt(np.sum((V - V_positive) ** 2, axis1))这行代码利用NumPy的广播机制一次性计算了所有方案到理想解的距离避免了低效的for循环。这是Python科学计算的核心技巧。排序技巧np.argsort(-C)通过对贴近度取负值实现了降序排列argsort默认升序。1是为了让排名从1开始更符合阅读习惯。注意这个函数是一个基础框架。在实际数学建模竞赛中你可能需要根据赛题要求调整正向化方法如用倒数法、标准化方法如极差法或者采用组合赋权法。将权重计算部分抽象成一个独立的函数如calculate_entropy_weight(Z)会让代码更清晰、更易扩展。4. 数学建模实战TOPSIS法的典型应用场景与进阶思考TOPSIS法因其概念清晰、计算简单、结果直观在数学建模中应用极其广泛。它特别适合解决多属性决策问题即从多个备选方案中选优或排序。4.1 典型应用场景举例综合评价类问题城市综合发展水平评估指标可包括GDP、人均收入、绿化率、空气质量、犯罪率等。TOPSIS可以给出各城市的综合排名。企业财务状况评价选取资产负债率、流动比率、净资产收益率、营业收入增长率等财务指标评价不同企业的财务健康度。学生综合素质测评将学业成绩、社会实践、创新能力、体育素质等作为指标对学生进行综合排序。资源选择与供应商评估竞赛题目实例如“光伏建筑一体化板块投资选择”、“医疗器械产品评价”等赛题核心就是根据一系列经济、技术、风险指标对多个候选对象进行排序。TOPSIS是解决这类问题的标准工具之一。方案优选问题工程项目选址、产品设计方案选择、物流配送路径规划等。每个方案都有多个评价属性成本、时间、效益、风险等TOPSIS能提供一个量化的比较依据。4.2 建模中的关键细节与进阶思考指标体系的构建是灵魂TOPSIS本身只是一个计算工具结果的可靠性首先取决于指标选取是否科学、全面、无冗余。在建模时需要花大量篇幅论证指标体系的构建过程可能用到文献调研、专家咨询、相关性分析剔除高度相关指标等方法。权重的确定是核心争议点如前所述熵权法是完全客观的但可能违背常识如本例中电池权重极低。主观赋权法如AHP能体现专家经验但可能带入主观偏见。因此在高质量论文中组合赋权是一个加分项。例如用AHP得到主观权重 \(w_j^s\)用熵权法得到客观权重 \(w_j^o\)然后通过线性组合 \(w_j \alpha w_j^s (1-\alpha)w_j^o\) 得到综合权重其中 \(\alpha\) 是偏好系数。正向化方法的多样性我们例子中用了“最大值-原值”处理成本型指标。还有其他方法倒数法对于成本型指标令 \(x 1/x\)要求x0。但此法会放大小值的影响且改变数据分布。区间型指标处理若指标值落在某个区间[a, b]内最优则可以通过一个分段函数将值映射为效益型数值越接近区间中心得分越高。 在论文中需要说明你选择某种正向化方法的理由。标准化方法的选择我们用了向量归一化。另一种常用方法是极差标准化Min-Max \[ z_{ij} \frac{x_{ij} - \min(x_j)}{\max(x_j) - \min(x_j)} \] 效益型 这种方法将所有数据压缩到[0,1]区间且保留了原始数据的线性关系。它的缺点是受极端值极大、极小影响大。在论文中可以进行敏感性分析即尝试不同的标准化方法看排序结果是否稳定。如果结果基本一致则结论更可靠。结果的解读与可视化计算出贴近度C后不要只给一个排序表。可以绘制柱状图或雷达图展示排名前几的方案在各个指标上的表现直观看出其优势与短板。进行灵敏度分析微调某个重要指标的权重观察排序结果是否发生变化。如果某方案在权重合理变动范围内始终排名靠前说明其鲁棒性好。结合其他方法例如可以将TOPSIS与灰色关联分析结合先用灰色关联分析筛选出与理想方案关联度高的方案再用TOPSIS精细排序。4.3 一个完整的建模论文片段构思假设赛题是“评估某地区乡村振兴发展水平”你可以这样组织内容引言简述乡村振兴战略意义提出用综合评价方法衡量发展水平的必要性。指标体系构建从“产业兴旺、生态宜居、乡风文明、治理有效、生活富裕”五个维度选取15个具体指标如农业劳动生产率、生活垃圾处理率、文明村镇占比、村民自治满意度、农民人均可支配收入等并说明数据来源。方法论详细阐述TOPSIS模型的原理、步骤。重点说明针对成本型指标如贫困发生率采用的正向化方法。采用熵权法确定客观权重的计算过程。为弥补熵权法不足引入AHP法获取主观权重并通过最小二乘法或博弈论组合主客观权重。实证分析数据预处理与描述性统计。展示权重计算结果并分析高权重指标的现实意义。计算各乡村的贴近度C并排序。将结果按C值分为“领先型”、“发展型”、“追赶型”等梯队。绘制排名前五和后五的乡村雷达图对比其优劣势。稳健性检验更换标准化方法如改用极差法重新计算排序通过斯皮尔曼等级相关系数检验两次排序的一致性。结论与建议根据评价结果总结领先乡村的成功经验指出落后乡村的共性短板提出针对性政策建议。通过这样一套完整的流程TOPSIS就从单纯的算法变成了一个有血有肉、逻辑严谨的数学模型足以支撑起一篇数学建模论文的核心部分。记住在建模中清晰透明的过程往往比一个惊艳的结果更重要TOPSIS正好提供了这样一个过程。
返回列表