多准则决策分析:从ANP网络分析到TOPSIS排序的建模实践
2026/8/28 20:58:19 网站建设 项目流程

1. 问题拆解与建模思路:从“多目标”到“可计算”

去年带队做美赛ICM的D题,题目是关于联合国可持续发展目标(SDGs)的优先级排序。这题乍一看很“文科”,一堆描述性指标,但内核是个典型的多准则决策分析问题。很多队伍一上来就懵,要么陷入对17个目标庞杂文本的纠结,要么试图找一个“万能公式”硬套。我的思路是,先把“优先级”这个模糊概念,拆解成几个可以量化的维度。

优先级排序,本质上是在资源有限、目标间存在复杂关联(协同与权衡)的约束下,寻找一个最优的资源配置或行动序列。所以,我们的模型至少要回答三个问题:

  1. 紧迫性:哪些目标不立刻解决,后果最严重或不可逆?
  2. 影响力:推动哪些目标,能对其他目标产生最大的正向带动效应(杠杆效应)?
  3. 可行性:以当前或可预见的技术、经济、政治条件,哪些目标更容易实现?

基于这个框架,我设计了一个三阶段的混合模型。第一阶段,用网络分析法来量化目标间的相互影响关系,找出核心枢纽目标。第二阶段,结合TOPSIS法,引入外部数据(如各国发展指数、环境绩效指数等)来评估每个目标的紧迫性与基础条件。第三阶段,用一个简单的优化模型,模拟在资源约束下,如何分阶段投入以实现整体效益最大化。整个流程用Python实现,从数据爬取、处理、建模到可视化,形成闭环。

这里的关键在于,不要幻想用一个模型解决所有问题。ANP(网络分析法)擅长处理元素间相互依赖的关系,正好用来刻画SDGs之间“牵一发而动全身”的特性。而TOPSIS(优劣解距离法)则适合在多指标下对方案(即SDGs)进行排序。两者结合,一个看“内在关联”,一个看“外在表现”,相互校验,结论会更稳健。

注意:美赛ICM题往往没有标准答案,评委看重的是建模过程的逻辑性、假设的合理性以及结论的洞察力。清晰阐述你的模型如何对应现实世界的决策逻辑,比追求复杂的数学公式更重要。

2. 数据基石:寻找与构造量化指标

没有数据,再漂亮的模型也是空中楼阁。SDGs本身有大量的定性描述,我们的首要任务就是将其转化为可计算的指标。官方渠道(如UN Stats, World Bank, WHO)是首选,但直接对应17个目标169个具体目标的完美数据集并不存在,需要我们自己动手,丰衣足食。

我们的策略是“代表性指标”法。为每个SDG选取2-3个最具代表性、数据可获得性高的子指标。例如:

  • SDG 1(无贫困):选用“日均生活费用低于1.9美元的人口比例”、“社会保障覆盖率”。
  • SDG 3(良好健康与福祉):选用“五岁以下儿童死亡率”、“每千人医生数”。
  • SDG 7(经济适用的清洁能源):选用“可再生能源消费占比”、“通电人口比例”。
  • SDG 13(气候行动):选用“人均二氧化碳排放量”、“气候变化应对准备指数”。

数据来源方面,我们主要利用了世界银行的World Development Indicators (WDI)数据库和联合国开发计划署的人类发展报告数据。使用Python的pandas-datareaderwbdata库可以方便地批量获取。对于缺失值,我们采用了时间序列插值(向前/向后填充)和基于相似国家的均值填充法,并在论文中明确说明了处理方法及其潜在影响。

更重要的是数据标准化。不同指标量纲和极性(有的越大越好,有的越小越好)不同,必须统一。我们采用了极差标准化法。对于效益型指标(越大越好):(x - min) / (max - min);对于成本型指标(越小越好):(max - x) / (max - min)。这样,所有指标值都落在了[0, 1]区间,且都是越大越优。

import pandas as pd import numpy as np # 假设df是一个DataFrame,行是国家/年份,列是各个指标 def normalize_data(df, benefit_columns, cost_columns): """ 标准化数据 :param df: 原始数据DataFrame :param benefit_columns: 效益型指标列名列表 :param cost_columns: 成本型指标列名列表 :return: 标准化后的DataFrame """ df_normalized = df.copy() for col in benefit_columns: if col in df.columns: min_val = df[col].min() max_val = df[col].max() if max_val != min_val: df_normalized[col] = (df[col] - min_val) / (max_val - min_val) else: df_normalized[col] = 0.5 # 处理常数列 for col in cost_columns: if col in df.columns: min_val = df[col].min() max_val = df[col].max() if max_val != min_val: df_normalized[col] = (max_val - df[col]) / (max_val - min_val) else: df_normalized[col] = 0.5 return df_normalized # 示例:假设我们有几个指标 # benefit_cols = ['Renewable_energy_%', 'Physicians_per_1000'] # cost_cols = ['Child_mortality_rate', 'CO2_emissions_per_capita'] # df_normalized = normalize_data(df, benefit_cols, cost_cols)

这一步是后续所有分析的基础,务必细致。在论文中,我们用一个表格清晰列出了每个SDG对应的量化指标、数据来源和处理方法,这能极大增强模型的可信度。

3. 核心模型一:基于网络分析法的关联影响评估

SDGs不是一个简单的清单,它们之间存在着复杂的相互作用。例如,提升教育水平(SDG 4)会促进性别平等(SDG 5),也会减少贫困(SDG 1)。这种网络化的相互依赖关系,正是ANP(网络分析法)的用武之地。我们用它来构建SDGs的影响关系网络,并计算每个目标的“中心度”,从而识别出哪些目标是撬动整个系统的关键支点。

第一步,构建直接影响矩阵。我们通过专家问卷(模拟)和文献综述相结合的方式,来判定SDG i对SDG j的影响程度。采用1-9标度法:1表示影响极其微弱,9表示影响极其强烈。这是一个17x17的矩阵。这里的一个技巧是,我们要求判断必须是“非对称”的,即A对B的影响程度,与B对A的影响程度分别判断。这能更好地捕捉现实中的单向或强弱不对称影响。

第二步,计算综合影响矩阵。直接影响矩阵只反映了一步影响。在系统中,影响会通过其他目标间接传递。我们需要计算综合影响矩阵T = X + X^2 + X^3 + ...(其中X是标准化后的直接影响矩阵)。数学上,这等价于求T = X * (I - X)^(-1),其中I是单位矩阵。这个矩阵T中的元素t_ij就表示目标i对目标j的直接和间接影响的总和

第三步,计算中心度指标。对综合影响矩阵T的行和与列和进行分析:

  • 影响度D_i = sum(t_ij for j in 1...n)。表示目标i对所有其他目标的综合影响程度。值越大,说明该目标越像“驱动者”。
  • 被影响度R_j = sum(t_ij for i in 1...n)。表示目标j受到所有其他目标的综合影响程度。值越大,说明该目标越像“结果”。
  • 中心度C_i = D_i + R_i。这是一个非常重要的指标,它综合反映了目标i在网络中的活跃程度和重要性。高中心度的目标,通常是系统干预的优先候选。
import numpy as np import pandas as pd def anp_analysis(direct_influence_matrix): """ 执行ANP分析,计算影响度、被影响度和中心度 :param direct_influence_matrix: 直接影响矩阵,numpy array, shape (n, n) :return: 包含各指标结果的DataFrame """ X = direct_influence_matrix.astype(float) n = X.shape[0] # 1. 标准化直接影响矩阵(行和归一化) row_sums = X.sum(axis=1, keepdims=True) X_norm = X / row_sums # 处理全零行 X_norm = np.where(np.isnan(X_norm), 0, X_norm) # 2. 计算综合影响矩阵 T = X_norm * (I - X_norm)^(-1) I = np.eye(n) try: # 使用伪逆增加数值稳定性 T = np.linalg.lstsq((I - X_norm), X_norm, rcond=None)[0] # 或者使用求逆,但前提是矩阵可逆 # T = np.dot(X_norm, np.linalg.inv(I - X_norm)) except np.linalg.LinAlgError: print("矩阵(I - X_norm)可能奇异,使用伪逆或添加小扰动") # 添加一个小扰动项确保可逆 T = np.dot(X_norm, np.linalg.pinv(I - X_norm + 1e-10 * np.eye(n))) # 3. 计算影响度(D)、被影响度(R)和中心度(C) D = T.sum(axis=1) # 行和 R = T.sum(axis=0) # 列和 C = D + R # 4. 整理结果 sdg_labels = [f'SDG {i+1}' for i in range(n)] results_df = pd.DataFrame({ 'SDG': sdg_labels, 'Influence_Degree (D)': D, 'Dependence_Degree (R)': R, 'Centrality (C)': C }).sort_values(by='Centrality (C)', ascending=False) return results_df, T # 示例:假设我们有一个17x17的直接影响矩阵(这里用随机矩阵代替) np.random.seed(42) n_sdgs = 17 # 生成一个随机矩阵,模拟直接影响关系 direct_matrix = np.random.randint(0, 5, size=(n_sdgs, n_sdgs)).astype(float) # 将对角线设为0,自己对自己无直接影响 np.fill_diagonal(direct_matrix, 0) anp_results, total_influence_matrix = anp_analysis(direct_matrix) print(anp_results.head())

在我们的分析中,SDG 4(优质教育)、SDG 8(体面工作和经济增长)、SDG 9(产业、创新和基础设施)通常表现出很高的中心度。这意味着它们是高度互联的枢纽,对这些目标的投资会产生广泛的涟漪效应。这个结论与许多国际研究机构的报告是吻合的,为我们的优先级排序提供了坚实的“网络关系”依据。

4. 核心模型二:基于TOPSIS的综合绩效排序

ANP给了我们“内在关联”视角的优先级,但它高度依赖于我们构建的影响矩阵的主观判断。为了增加客观性,并与现实世界的数据接轨,我们引入TOPSIS法。TOPSIS的核心思想很直观:优先方案应该离理想解最近,离负理想解最远。我们将每个SDG视为一个“方案”,用第二阶段收集和标准化的指标数据作为其“属性”。

第一步,构建加权规范化决策矩阵。我们已经有了标准化后的数据矩阵V(m个国家/地区 * n个指标)。现在需要确定每个指标的权重。我们采用了熵权法,这是一种客观赋权法,根据指标数据的离散程度来确定权重。信息熵越小,指标的变异程度越大,提供的信息量越多,权重也就越大。这避免了主观随意性。

第二步,确定理想解与负理想解。

  • 理想解 A+:由所有指标在所有方案中的最大值构成。
  • 负理想解 A-:由所有指标在所有方案中的最小值构成。 因为我们已经标准化(且统一为效益型),所以理想解就是每个指标列的最大值组成的向量,负理想解就是每个指标列的最小值组成的向量。

第三步,计算距离与贴近度。计算每个SDG(在数据上体现为每个国家在该SDG指标上的综合表现,我们可以先对国家层面求平均,得到一个全球层面的SDG表现向量)到理想解和负理想解的欧氏距离(D+和D-)。最后计算贴近度C_i = D- / (D+ + D-)。C_i 值介于0和1之间,越接近1,说明该SDG的综合表现越接近理想状态,即基础越好或进展越顺利;反之,越接近0,则说明该SDG距离理想状态越远,可能更紧迫或更落后。

def entropy_weight(data): """ 计算指标的熵权 :param data: 标准化后的数据矩阵,numpy array, shape (m个样本, n个指标) :return: 权重向量, shape (n,) """ # 防止log(0) data = np.where(data == 0, 1e-10, data) # 计算比重 p = data / data.sum(axis=0, keepdims=True) # 计算信息熵 k = 1 / np.log(data.shape[0]) e = -k * (p * np.log(p)).sum(axis=0) # 计算差异系数 d = 1 - e # 计算权重 w = d / d.sum() return w def topsis(decision_matrix, weights=None, benefit_attributes=None): """ 执行TOPSIS评估 :param decision_matrix: 决策矩阵,numpy array, shape (m个方案, n个指标) :param weights: 权重向量,如果为None则使用熵权法计算 :param benefit_attributes: 效益型指标索引列表,如果为None则默认全为效益型 :return: 贴近度得分和排序 """ m, n = decision_matrix.shape if benefit_attributes is None: benefit_attributes = list(range(n)) # 1. 数据标准化 (这里假设输入已经是标准化后的效益型数据) # 如果输入是原始数据,需要先进行标准化处理(如第2部分所述) norm_matrix = decision_matrix.copy() # 2. 确定权重 if weights is None: weights = entropy_weight(norm_matrix) else: weights = np.array(weights) if len(weights) != n: raise ValueError("权重向量长度与指标数不符") # 3. 构建加权规范化矩阵 weighted_matrix = norm_matrix * weights # 4. 确定理想解和负理想解 ideal_best = weighted_matrix.max(axis=0) ideal_worst = weighted_matrix.min(axis=0) # 5. 计算距离 # 到理想解的距离 dist_best = np.sqrt(((weighted_matrix - ideal_best) ** 2).sum(axis=1)) # 到负理想解的距离 dist_worst = np.sqrt(((weighted_matrix - ideal_worst) ** 2).sum(axis=1)) # 6. 计算贴近度 closeness = dist_worst / (dist_best + dist_worst + 1e-10) # 加一个小数防止除零 return closeness, dist_best, dist_worst, weights # 示例:假设我们有17个SDG,每个SDG用3个标准化后的指标表示 np.random.seed(123) n_sdgs = 17 n_indicators = 3 # 生成模拟的标准化数据(值在0-1之间) simulated_data = np.random.rand(n_sdgs, n_indicators) # 使用TOPSIS计算 closeness_scores, d_plus, d_minus, calculated_weights = topsis(simulated_data) sdg_list = [f'SDG {i+1}' for i in range(n_sdgs)] topsis_results = pd.DataFrame({ 'SDG': sdg_list, 'Closeness Score': closeness_scores, 'Distance to Ideal (D+)': d_plus, 'Distance to Worst (D-)': d_minus }).sort_values(by='Closeness Score', ascending=False) print("指标权重:", calculated_weights) print(topsis_results.head())

TOPSIS的结果往往显示,像SDG 1(无贫困)、SDG 2(零饥饿)、SDG 6(清洁饮水和卫生设施)这类基础生存需求目标,其贴近度得分较低(即距离理想解远),表明在全球范围内这些目标的实现情况相对滞后,紧迫性更高。这与ANP得出的“枢纽目标”形成了有趣的对比:一个指向“杠杆点”,一个指向“短板”。

5. 模型融合与动态优先级决策

现在我们手上有两份排序清单:一份来自ANP的“中心度”排序(代表影响力/杠杆效应),一份来自TOPSIS的“贴近度”排序(代表紧迫性/现状差距)。直接平均?太粗糙了。我们引入一个动态加权融合模型,并在此基础上构建一个简单的资源分配优化模型,让优先级服务于决策。

第一步,构建综合优先级指数。我们定义综合优先级指数P_i = α * (1 - C_i_topsis) + β * C_i_anp

  • (1 - C_i_topsis):TOPSIS贴近度的补数。C_i_topsis越小(表现越差),这个值越大,代表紧迫性越高。
  • C_i_anp:ANP的中心度。值越大,代表影响力/杠杆效应越强。
  • αβ是权重,满足α + β = 1。它们反映了决策者更看重“弥补短板”还是“发挥杠杆”。我们可以进行敏感性分析,展示不同权重下优先级的变化,这本身就是论文的一个亮点。

第二步,基于优先级的资源分配模拟。假设我们有一个总预算B,投入到每个SDG i 都能产生一定的“效益”,这个效益与我们的综合优先级指数P_i正相关,同时也遵循边际效益递减规律(例如,可以用对数函数模拟)。我们建立一个简单的优化问题: 最大化总效益Σ( k * ln(1 + r_i * x_i) ),其中x_i是分配给目标i的资源,r_i是该目标的“效益转化系数”(可以与P_i挂钩),k是缩放常数,约束条件是Σ x_i <= Bx_i >= 0

这个模型可以用Python的scipy.optimize库快速求解。通过改变总预算B和权重α, β,我们可以生成不同的资源分配方案,从而为“优先级”这个概念提供动态的、基于场景的解读。

import numpy as np from scipy.optimize import minimize def allocate_resources(priority_scores, total_budget, efficiency_coefs=None): """ 基于优先级分数进行资源分配优化(简化模型) :param priority_scores: 综合优先级指数,越高越优先 :param total_budget: 总预算 :param efficiency_coefs: 各目标的效益转化系数,如果为None则用priority_scores替代 :return: 最优资源分配方案 """ n = len(priority_scores) if efficiency_coefs is None: efficiency_coefs = priority_scores # 简化假设:优先级越高,资金使用效率也越高 # 定义目标函数:最大化总效益(假设效益函数为对数形式,体现边际递减) def objective(x): # x是分配的资源数组 # 总效益 = sum( efficiency_coef * log(1 + resource) ) # 加1是为了防止log(0) total_benefit = -np.sum(efficiency_coefs * np.log(1 + x)) # 取负因为minimize求最小值 return total_benefit # 初始猜测:按优先级比例分配 x0 = total_budget * priority_scores / priority_scores.sum() # 约束条件:总资源不超过预算,且每个项目资源非负 constraints = ( {'type': 'ineq', 'fun': lambda x: total_budget - np.sum(x)}, # sum(x) <= B ) bounds = [(0, total_budget) for _ in range(n)] # 每个x_i >= 0 # 优化求解 result = minimize(objective, x0, method='SLSQP', bounds=bounds, constraints=constraints) if result.success: optimal_allocation = result.x # 由于数值计算,可能和极小,我们将其归零 optimal_allocation[optimal_allocation < 1e-3] = 0 # 重新归一化,确保总和等于预算(处理数值误差) optimal_allocation = optimal_allocation / optimal_allocation.sum() * total_budget return optimal_allocation else: print("优化失败:", result.message) return x0 # 返回初始分配作为后备 # 示例:假设我们得到了17个SDG的综合优先级指数 np.random.seed(2023) comprehensive_priority = np.random.rand(17) comprehensive_priority = comprehensive_priority / comprehensive_priority.sum() * 10 # 放大一些 total_budget = 1000 # 总预算1000个单位 optimal_resources = allocate_resources(comprehensive_priority, total_budget) allocation_result = pd.DataFrame({ 'SDG': [f'SDG {i+1}' for i in range(17)], 'Priority Score': comprehensive_priority, 'Optimal Allocation': optimal_resources }).sort_values(by='Optimal Allocation', ascending=False) print(allocation_result.head(10))

通过这个融合与优化过程,我们最终输出的不再是一个简单的排名,而是一套决策支持工具。我们可以告诉决策者:“如果你更关注解决最紧迫的问题(α高),那么资源应倾斜于SDG 1, 2, 6;如果你更关注投资的长期杠杆效应(β高),那么应聚焦SDG 4, 8, 9。这是在不同预算水平下的最优分配方案。” 这种动态的、可交互的结论,远比一个静态的排行榜更有价值。

6. 可视化呈现与论文写作要点

建模和编程完成只算成功了一半,如何清晰、有力地在25页的论文里呈现出来,是另一半挑战。可视化是关键。

第一,关系网络图。使用networkxmatplotlibplotly绘制SDGs之间的影响关系网络。节点大小代表中心度,颜色代表TOPSIS贴近度(用渐变色)。边的大小和颜色代表影响强度。这样一张图,可以直观展示哪些目标是核心枢纽(大节点),哪些目标现状堪忧(暖色/冷色取决于配色方案)。确保图例清晰,并在文中对关键节点进行解读。

第二,优先级雷达图/条形图对比。将ANP中心度、TOPSIS贴近度(或1-贴近度)、综合优先级指数放在一起比较。可以使用分组条形图,让评委一眼看出不同方法排序的异同。雷达图则可以展示某个特定SDG在各个评估维度上的表现。

第三,敏感性分析热图。展示当权重α和β在0到1之间变化时,前5名优先SDG是如何变化的。可以用热图表示,X轴是α,Y轴是排名,颜色代表不同的SDG。这能强力证明你的模型是稳健的,并且能容纳不同的政策偏好。

论文写作上,务必注意:

  • 假设驱动:每一个建模选择(如为什么用1-9标度、为什么用熵权法)都要有合理论述,引用相关管理科学或决策理论。
  • 模型检验:对ANP矩阵进行一致性检验(虽然我们模拟数据,但要提这个步骤);对TOPSIS结果进行鲁棒性分析(比如随机扰动指标权重,看排名是否稳定)。
  • 讨论与拓展:明确指出模型的局限性(如数据质量、主观判断的影响、未考虑的地域差异),并提出改进方向(如引入模糊理论处理不确定性、分地区建模等)。这体现了批判性思维。
  • 摘要要精炼:用最后写摘要。用三四句话概括问题、方法、核心模型、关键发现和建议。避免在摘要里出现公式和代码。

整个代码框架应模块化,包含数据获取、清洗、ANP分析、TOPSIS分析、模型融合、优化求解和可视化等多个.py文件或Jupyter Notebook单元。注释要详尽,确保评委(或任何读者)能跟随你的代码逻辑。最终,你的论文和代码共同讲述了一个完整、严谨、有洞察力的故事:我们如何用一个可计算的框架,去逼近“可持续发展目标优先级”这个复杂的决策问题。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询