首页 / 资讯中心 / 文章详情

AHP城市竞争力评价复现:四层指标、权重计算与一致性检验

AHP城市竞争力评价复现:四层指标、权重计算与一致性检验 ★ FEATURED ARTICLE
简介这份文档围绕层次分析法在城市竞争力评价中的应用展开面向经济学、统计学、城市规划与系统工程等专业的学生、研究者及政策分析人员帮助解决多指标、多维度城市竞争力难以量化比较的问题。内容从AHP基本思想入手讲解目标层、准则层、要素层与指标层的四层结构说明如何以1—9标度构造判断矩阵、计算特征向量获得权重并通过一致性比率CR小于0.1检验判断可靠性同时结合中国城市竞争力评价实例展示准则层、要素层和指标层权重的逐级赋值与综合评分思路。压缩包内含1个doc文件大小约832KB适合作为课程报告、方法学习或评价模型搭建的参考材料。已有140人学习读者可从中获取AHP建模流程、指标体系组织方式、判断矩阵与一致性检验的完整示例以及将权重结果用于城市竞争力分析的基本路径。1. 拿到一份 AHP 城市竞争力评价报告先别翻结论页那份课程报告躺在硬盘里很久了封面、目录、四章正文最后停在由于数据量庞大暂不计算城市排名。多数人扫一眼就走我拆的时候先翻附件——附件里那张 AHP 赋权表才是整份资源唯一不可替代的东西。层次分析法用在城市竞争力评价上公式在教科书里到处都是真正稀缺的是有人把 71 项候选指标压成目标层、准则层、要素层、指标层四层结构又逐层把判断矩阵填完、把一致性检验跑过、把权重算到小数点后四位。这套链路对做城市评估、园区打分、区域对比的人来说可以直接照搬对只是想学 AHP 的人它是一个比课本例子大一号、又没大到做不完的完整样本。下面按我复现的顺序拆结构怎么搭、矩阵怎么填、权重怎么解、CR 卡住怎么办、哪几个细节最容易把权重算废。2. 四层指标体系怎么搭从 71 项候选指标到可计算的层次结构指标体系这一步决定后面所有计算有没有意义。AHP 不负责帮你选指标它只负责在你选完之后给出权重所以结构搭歪了后面矩阵填得再漂亮也是白算。报告里给的 71 项候选指标是原始素材真正要落地的是把它们分桶、定层、挂到正确的父节点下面。2.1 四个层级各自管什么以及为什么不能只做三层目标层只有一个元素就是最终那个标量——城市综合竞争力指数所有计算最后都收敛到它身上。准则层是分解总目标的第一刀报告切成动力、阻力、相互影响、环境水平四块。要素层是对准则的再解释比如动力下面拆成经济实力、政府作用、消费水平、人力资源、科技实力五项。指标层是可以直接查到数的基层条目人均 GDP、财政支出占比、每万人专利数这类。层级数量的选择有个很实在的算术约束。一个 n 阶判断矩阵需要做 n(n−1)/2 次两两比较。如果把 71 项指标直接挂在目标层下面做一个扁平结构比较次数是 71×70/2 2485 次没有任何专家团队能保质保量填完而且一致性必然崩盘。做成四层之后最大的矩阵是动力层下的 5×5只有 10 次比较准则层的 4×4 是 6 次要素层的 2×2 和 3×3 更少。全表加起来一百多次比较一个下午能开完一场专家会。这就是分层的第一性理由不是为了让报告好看是为了把人类判断力的规模控制在可执行区间内。每层元素个数建议压在 3 到 7 之间超过 9 就超出 1-9 标度的表达能力那时候该做的不是继续填矩阵而是回去重新分桶。提示判断矩阵的阶数上限不是软件限制是 1-9 标度的语义边界。标度只区分到极端重要一旦元素超过 9 个专家在明显重要和极端重要之间就分不出层次了。2.2 动力与阻力分开正负向指标不能混在一个准则里报告把贫富分化单独拎出来放进阻力层这个处理值得说一句。城市竞争力不是一堆指标的简单加总有些指标越高越好有些越高越糟。AHP 本身只输出权重不识别方向方向问题要到无量纲化阶段才处理。如果一开始就把贫富分化塞进经济实力里权重会把它当成一个正向贡献项后面再怎么调无量纲化公式都掰不回来。分开之后有两个好处。第一权重可解释——阻力层的权重直接回答负面因素在这个评价体系里占多大分量这个数在写政策建议时很好用。第二敏感性分析时能量化杠杆把阻力层权重从 0.0893 调到 0.15看排名怎么动这比笼统说负面因素也重要要有说服力。代价也要说清楚。阻力层下面只挂了贫富分化一个要素单元素层的判断矩阵是 1×1RI 等于 0一致性检验退化成形式检查算出来的 CR 没有意义。这种情况正确做法是跳过检验并在报告里注明而不是硬凑一个 0。报告权重表里贫富分化那一格空着多半就是卡在这儿——单元素层算不出权重填表的人索性留白结果组合权重链断了一节。这个坑在第 5 章展开。2.3 用一份嵌套字典把层次结构固化下来指标体系一旦定稿第一件事是把它写成代码里的数据结构而不是继续留在 Word 表格里。后面所有权重计算、组合权重、排名输出都从这里取数改一处全链路跟着动。# 层次结构骨架只保留层级关系与节点名指标数据另外用 CSV 挂 # 指标层条目在实际项目里从附件表导入这里用占位名演示结构 HIERARCHY { 城市综合竞争力: { # 目标层唯一根节点 动力: { # 准则层 经济实力: [地区生产总值, 人均地区生产总值, 固定资产投资额], 政府作用: [财政支出占GDP比重, 行政审批事项数], 消费水平: [社会消费品零售总额, 居民人均消费支出], 人力资源: [每万人高等教育在校生数, 从业人员占比], 科技实力: [RD经费投入强度, 每万人发明专利授权量], }, 阻力: { # 负向准则单独成层 贫富分化: [城乡收入比, 基尼系数估算值], }, 相互影响: { 对外开放: [实际利用外资额, 进出口总额占GDP比重], 依存度: [外贸依存度, 外资企业产值占比], }, 环境水平: { 基础设施: [人均道路面积, 万人拥有公共交通车辆], 环境水平: [建成区绿化覆盖率, 单位GDP能耗], }, } } def flatten_leaves(node, path()): 递归展开到指标层返回 [(完整路径, 指标名), ...] out [] for key, val in node.items(): if isinstance(val, dict): out.extend(flatten_leaves(val, path (key,))) elif isinstance(val, list): for item in val: out.append((path (key,), item)) return out leaves flatten_leaves(HIERARCHY) print(len(leaves)) # 指标层条目总数 print(leaves[0]) # ((动力, 经济实力), 地区生产总值)HIERARCHY里字典的深度就是层级深度键名是节点名列表是叶子。flatten_leaves用递归把所有叶子拉平返回的元组前半段是完整的父节点路径后半段是指标名——这个路径在计算组合权重时直接当键用避免后面靠字符串拼接出错。参数path是递归累加器初始为空元组不需要手动传。把结构写进代码的另一个好处是能立刻做完整性检查遍历一遍凡是空列表的节点说明指标没挂满凡是有字典又有列表的节点说明层级混了。这类错误在 Word 表格里肉眼看不出来在代码里一行断言就能拦住。3. 判断矩阵与权重求解1-9 标度、算术平均法与特征向量层次结构定了接下来是整份资源里最花时间的部分把每一层元素两两比较填成判断矩阵再解出权重向量。报告里准则层、要素层、指标层一共十几张矩阵全都用手工填表加算术平均法求解。3.1 1-9 标度到底在标什么判断矩阵 A 是个正互反矩阵元素 a_ij 表示对上层某个目标而言元素 i 相对元素 j 的重要程度满足 a_ij 0、a_ji 1/a_ij、a_ii 1。标度取值限制在 1 到 9 及其倒数。标度含义反向取值1i 与 j 同等重要13i 比 j 稍微重要1/35i 比 j 明显重要1/57i 比 j 强烈重要1/79i 比 j 极端重要1/92,4,6,8上述相邻判断的中间值1/2,1/4,1/6,1/8实操上别直接问专家经济实力比科技实力重要几倍人对倍数不敏感问出来全是拍脑袋。我一般改成两段式提问先问这两个哪个更重要再问是稍微重要、明显重要还是强烈重要最后映射到 3、5、7。多轮下来同一批专家的结果稳定性明显好于直接报倍数。多个专家打分时聚合方式要用几何平均而不是算术平均。原因是标度是比率尺度1/9 和 9 表达的是同一对关系的两个方向算术平均会得到 (9 1/9)/2 ≈ 4.5把极端重要稀释成接近明显重要语义直接崩掉。几何平均 √(9 × 1/9) 1正好还原成同等重要这才是比率尺度该有的聚合方式。注意几何平均只对同一位置的多个专家值做聚合聚合完仍然要检查互反性。工程上更稳的做法是只让专家填上三角下三角由程序取倒数从源头消灭手填不一致。3.2 算术平均法列归一化、行求和、归一化报告用的是算术平均法也叫和积法。三步判断矩阵按列归一化归一化后按行求平均得到权重向量 w再用 A w 和 w 的逐元素比值求最大特征值 λ_max。import numpy as np RI_TABLE {1: 0.00, 2: 0.00, 3: 0.58, 4: 0.90, 5: 1.12, 6: 1.24, 7: 1.32, 8: 1.41, 9: 1.45} def ahp_weights(A): 算术平均法求权重、最大特征值、CI、CR A np.asarray(A, dtypefloat) n A.shape[0] assert np.allclose(A * A.T, np.ones((n, n))), 矩阵不是正互反矩阵 B A / A.sum(axis0) # 1) 按列归一化 w B.mean(axis1) # 2) 行平均得到权重 Aw A w lam_max float((Aw / w).mean()) # 3) 最大特征值 CI (lam_max - n) / (n - 1) if n 1 else 0.0 RI RI_TABLE.get(n, 1.49) CR CI / RI if RI 0 else 0.0 return w, lam_max, CI, CRA.sum(axis0)是列求和A / ...广播成逐元素除法得到的 B 每列和为 1。B.mean(axis1)按行取平均正好是每个元素的权重。Aw / w逐元素相除后取均值就是 λ_max 的近似——完全一致时这个比值恒等于 n。assert那一行是必须的。手填矩阵最常见的错误是 a_ij 填了 3a_ji 忘了填 1/3 而填了 0.3这种矩阵算出来的权重会出现负值或量级错乱不加断言很难第一时间发现。RI_TABLE.get(n, 1.49)在阶数超过 9 时回退到 1.49这是个近似值实际项目里遇到 10 阶以上应该回去重新分层。3.3 幂法交叉验证两套算法结果对不上就是有 bug算术平均法给的是 λ_max 的近似幂法给的是精确迭代解。两套方法算同一张矩阵如果 λ_max 差超过 1e-6说明中间某一步实现错了而不是方法本身有误差。def power_method(A, eps1e-10, max_iter2000): 幂法迭代求主特征向量和最大特征值 A np.asarray(A, dtypefloat) n A.shape[0] v np.ones(n) / n # 正规化初始向量 for _ in range(max_iter): u A v v_new u / u.sum() # 每步归一化防止数值溢出 if np.abs(v_new - v).max() eps: v v_new break v v_new lam float((A v / v).mean()) # 收敛后用瑞利商近似 return v, lam A_demo np.array([ [1, 3, 5, 7], [1/3, 1, 3, 5], [1/5, 1/3, 1, 3], [1/7, 1/5, 1/3, 1], ], dtypefloat) w1, lam1, ci, cr ahp_weights(A_demo) w2, lam2 power_method(A_demo) print(w1.round(4), lam1.round(6), round(cr, 4)) print(w2.round(4), lam2.round(6)) print(两法偏差:, abs(lam1 - lam2))eps控制收敛精度1e-10 对 9 阶以内的矩阵通常几十次迭代就够。max_iter是保险丝正常不会触发。归一化那一步不能省——不归一化的话 v 的模会随迭代指数增长十几轮就溢出成 inf。这套交叉验证我在每个项目里都会跑一遍。血泪经验是算术平均法的 bug 往往不体现在权重上权重看起来还是归一化的、还是正数只体现在 λ_max 上而 λ_max 又直接决定 CR最后表现为明明矩阵填得挺合理CR 死活过不了 0.1。先排除实现错误再去改矩阵顺序不能反。3.4 组合权重从单层排序推到总目标排序单层排序只回答在父节点下各元素占多少最终要的是每个要素对总目标的贡献这就要逐层相乘。报告的准则层权重是动力 0.4883、阻力 0.0893、相互影响 0.2328、环境水平 0.1896动力层下经济实力 0.4162、政府作用 0.2618、消费水平 0.0624、人力资源 0.0986、科技实力 0.1611。def combine_weights(layer_weights, parent_weight1.0, prefix): 递归计算组合权重layer_weights 是嵌套 dict叶子为 float result {} for name, val in layer_weights.items(): full f{prefix}/{name} if prefix else name if isinstance(val, dict): result.update(combine_weights(val, parent_weight * 1.0, full)) else: result[full] round(parent_weight * val, 6) return result # 以准则层 - 要素层两级为例 criteria {动力: 0.4883, 阻力: 0.0893, 相互影响: 0.2328, 环境水平: 0.1896} factors { 动力: {经济实力: 0.4162, 政府作用: 0.2618, 消费水平: 0.0624, 人力资源: 0.0986, 科技实力: 0.1611}, 相互影响: {对外开放: 0.6667, 依存度: 0.3333}, 环境水平: {基础设施: 0.5, 环境水平: 0.5}, } combined {} for c, wc in criteria.items(): if c in factors: for f, wf in factors[c].items(): combined[f{c}/{f}] round(wc * wf, 6) else: combined[c] wc # 阻力层下无要素细分直接挂准则权重 print(combined) print(合计:, round(sum(combined.values()), 6))跑出来的要素层组合权重是经济实力 0.20323、政府作用 0.127837、消费水平 0.03047、人力资源 0.048146、科技实力 0.078665、对外开放 0.155194、依存度 0.077596、基础设施 0.0948、环境水平 0.0948、阻力 0.0893合计 1.000038。最后那个 0.000038 的小尾巴不是打印误差是上游权重只保留四位小数导致的累积舍入。它在单个城市打分时影响可以忽略但在做城市间排名、尤其是几个城市分数咬得很近的时候这 3.8e-5 有可能改变名次。组合权重算完必须做一次归一化除以总和这是流程里最容易被跳过的一步。4. 一致性检验CR 逼近 0.1 时的三条修正路径判断矩阵是人填的人对多因素相对重要性的判断天然不自洽——觉得 A 比 B 重要、B 比 C 重要但填 A 对 C 的时候又手抖写了稍微重要三元关系就崩了。一致性检验的作用是把这种不自洽量化出来超过阈值就退回去改不带着错误往下算。4.1 CI、RI、CR 三个量的计算与查表完全一致的正互反矩阵满足 a_ik a_ij · a_jk此时 λ_max 恰好等于 n。实际矩阵 λ_max 总是大于 n超出的部分就是不一致的量。CI 定义为 (λ_max − n)/(n − 1)再用同阶随机矩阵的平均 CI 做归一化得到 CR CI / RI。阶数 n123456789RI000.580.901.121.241.321.411.45判定规则是 CR 0.1 认为一致性可接受。n 等于 1 或 2 时 RI 为 0CR 无定义这两种情况直接跳过检验——1 阶矩阵恒一致2 阶正互反矩阵也恒一致检查没有信息量。代码里常见的翻车是没判 RI 0 就做除法n2 时直接抛 ZeroDivisionError 或者返回 nan然后这个 nan 一路传到权重表里最后整张表全是 nan。报告里准则层那张 4×4 矩阵算出来 λ_max 略大于 4CI 是个小正数除以 RI 0.90 之后 CR 落在 0.1 以内判定为满意的一致性。原文把这一步写得很短实际操作时这一步最花时间——报告里那几张矩阵之所以能一次过是因为填表的人在正式定稿前已经反复调过。4.2 定位最矛盾的三元组别整张表重打CR 超了 0.1最常见的错误反应是把整张矩阵推倒重填。这么做的问题是会把专家的真实偏好一起抹掉——原本经济实力确实比消费水平重要得多重填之后这个判断被稀释权重的业务含义就没了。正确做法是定位到具体哪几个元素在打架。不一致的数学来源就是三元组违反传递性也就是 a_ik 和 a_ij · a_jk 偏离最大的那一组。def worst_triplet(A): 找出违反传递性最严重的 (i, j, k) 三元组 A np.asarray(A, float) n A.shape[0] best None for i in range(n): for j in range(n): for k in range(n): if len({i, j, k}) 3: continue pred A[i, j] * A[j, k] # 传递性预测值 err abs(pred - A[i, k]) / A[i, k] if best is None or err best[0]: best (err, i, j, k, pred, A[i, k]) return best err, i, j, k, pred, actual worst_triplet(A_demo) print(f最不一致三元组 ({i},{j},{k}) 误差 {err:.3f} f传递性预测 {pred:.2f}实际填写 {actual:.2f})pred是沿着 i→j→k 两步走出来的间接判断actual是直接填的 i→k。两者比值偏离 1 越远这一组越该改。改的时候只动 a_ik 一个元素同步把 a_ki 取倒数重算 CR再找下一组循环到 CR 达标为止。改哪个方向有讲究。如果 pred 远大于 actual说明间接路径认为 i 比 k 重要得多而直接填的比较保守通常是把 a_ik 往上调调到接近 pred 的平方根附近比较稳——直接调到 pred 往往矫枉过正把另一组三元组又搞崩了。我一般的习惯是一次只调一档标度比如从 3 调到 5然后重算宁可多迭代两轮。提示调整前先记下原始的 a_ik 和调整理由。AHP 的一致性修正是有主观成分的报告里如果只写调整后 CR 0.1而不写调了哪个元素、为什么调审阅的人没法判断权重还是不是专家原本的意思。4.3 把检验做成流水线里的断言十几张矩阵靠人工一张张检查 CR出错是迟早的事。最省心的办法是写成一个装饰器或者断言函数任何一张矩阵进来先过一遍不达标直接抛异常并打印三元组。def check_consistency(A, namematrix, threshold0.1): 一致性守卫CR 超阈值直接抛异常附带定位信息 w, lam, ci, cr ahp_weights(A) if A.shape[0] 2: return w, cr # 1、2 阶矩阵无需检验 if cr threshold: err, i, j, k, pred, actual worst_triplet(A) raise ValueError( f[{name}] CR{cr:.4f} 超阈值 f最不一致三元组索引 ({i},{j},{k})预测 {pred:.2f} 实际 {actual:.2f} ) return w, cr # 批量校验所有层级的矩阵 matrices {准则层: A_demo} for name, mat in matrices.items(): w, cr check_consistency(mat, name) print(f{name}: CR{cr:.4f} 通过权重 {w.round(4)})把threshold做成参数是有必要的探索阶段可以放宽到 0.15 先把链路跑通定稿再收紧到 0.1。异常信息里带索引和预测值是因为改矩阵的时候人需要知道去第几行第几列动刀光看一个 CR 数字没有任何指导意义。这套断言在批量处理几十张矩阵时价值最大。曾经有一次跑一个 12 层的评估体系前 11 张全过最后一张 CR 0.31日志里直接打出三元组索引五分钟定位到是某个专家把 1/5 填成了 0.2 的倒数关系搞反。没有这个日志靠肉眼在一张 5×5 表里找错能找一下午。5. 避坑五个让权重白算的细节这一章是踩过的坑汇总每一条都真实发生过而且都不是公式错是流程和数据结构上的疏漏。公式错反而好查因为结果会明显离谱这几类错误算出来的数看着都挺正常直到排名出来才发现不对劲。5.1 权重表里有一格是空的组合权重链断在中间现象逐层乘到要素层时某个分支算不出数或者算出来之后所有组合权重加起来只有 0.91 左右怎么都对不上 1。原因单元素层的判断矩阵是 1×1RI 0一致性检验没法做填表的人索性把这一格留空。报告表里贫富分化下面没有数值就是这种情况。空值在乘法里会变成 NaN 或者被当成 0整条链从这儿断掉。解决在代码里显式处理单元素层元素权重直接赋 1.0不参与矩阵计算也不做一致性检验。同时加一条断言所有叶子权重非 None 且组合权重总和与 1 的偏差小于 1e-4。这条断言我后来加进了所有 AHP 脚本的模板里跑一次只要几毫秒能省掉半天的排查。5.2 RI 表按错误的阶数索引CR 系统性偏小现象所有矩阵的 CR 都很漂亮普遍在 0.02 以下但把某个明显矛盾的矩阵故意塞进去CR 还是只有 0.05。原因查 RI 的时候用了 n−1 而不是 n 去索引。3 阶矩阵查了 2 阶的 RI 0除法跳过直接返回 04 阶矩阵查了 3 阶的 0.58 而不是 0.90CR 被系统性放大约 1.55 倍的分母缩小判定变得过于宽松。解决RI 表用字典按阶数直接索引不要用列表加偏移量。字典的键就是 n取不到时显式报错而不是回退默认值。另外加一个自检用例构造一个已知 CR 的矩阵比如故意填一组强不一致的 4 阶矩阵验证函数返回的 CR 落在预期区间这个用例每次改代码都跑一遍。5.3 手填矩阵没保证互反权重出现负值现象权重向量里出现负数或者某个元素权重超过 0.9其余元素加起来不到 0.1。原因手工填表时只填了上三角下三角凭印象填出现 a_ij 3 而 a_ji 0.5 这种组合。矩阵不再是正互反矩阵列归一化之后行平均不再具有权重含义算术平均法的收敛前提被破坏。解决数据录入环节只让填上三角下三角在代码里统一A np.triu(A) np.triu(A, 1).T ** -1生成。如果数据来自外部 Excel入口处加一条np.allclose(A * A.T, 1)断言不通过直接拒绝不要试图修正——互反性错误的矩阵没有唯一正确答案修出来的权重是不可信的。5.4 多专家打分用算术平均聚合语义被稀释现象五位专家对同一对元素的判断分别是 9、1/9、7、1/7、1聚合后得到 3.7 左右最终权重里这一项既不算特别重要也不算无关紧要怎么看都不对。原因1-9 标度是比率尺度9 和 1/9 是同一关系的正反表达算术平均 (9 1/9)/2 ≈ 4.5 破坏了这种对称性。比率尺度的中心趋势应该用几何平均。解决同一位置的多专家值取几何平均np.exp(np.log(vals).mean())聚合完再检查互反性。如果专家意见分歧极大比如有人给 9 有人给 1/9不要强行聚合先开会吵清楚——这种分歧往往说明指标定义本身有歧义不是数学能解决的。5.5 无量纲化方向搞反负向指标越差得分越高现象某城市贫富差距越大综合得分反而越高排名靠前。检查权重没问题矩阵也没问题。原因无量纲化统一用了极差法 (x − min)/(max − min)这个公式假定所有指标都是正向的——数值越大越好。贫富分化、单位 GDP 能耗、城乡收入比这类负向指标套进去方向完全反了。解决在指标元数据里加一个 direction 字段正向用 (x − min)/(max − min)负向用 (max − x)/(max − min)中性指标用 1 − |x − target|/max|x − target|。这一步必须在权重计算之前就在数据字典里定好不能等到算综合指数时临时判断——71 项指标靠人记方向必错。6. 从权重表到排名一次敏感性验证比十页结论更有用权重算完只是半成品真正决定这份评价能不能拿去用的是它对判断扰动的鲁棒性。我现在的习惯是任何一套 AHP 权重在出排名之前先做一轮敏感性扫描把最关键的那几个判断矩阵元素按 ±1 档标度扰动重算权重、重算排名看名次会不会翻。import numpy as np from scipy.stats import spearmanr def perturb_and_rank(A, scores, delta1.5, idx(0, 1)): 把 A[idx] 乘 delta同步调整互反位比较排名变化 A2 A.copy() i, j idx A2[i, j] np.clip(A2[i, j] * delta, 1/9, 9) A2[j, i] 1 / A2[i, j] w1, *_ ahp_weights(A) w2, *_ ahp_weights(A2) r1 np.argsort(np.argsort(-(scores w1))) r2 np.argsort(np.argsort(-(scores w2))) return spearmanr(r1, r2).statistic, w1, w2 rho, w1, w2 perturb_and_rank(A_demo, np.random.rand(5, 4), delta1.5) print(f排名秩相关 {rho:.4f})scores是城市 × 指标的标准化数据矩阵delta控制扰动幅度1.5 大致相当于在 1-9 标度上动一档。秩相关系数低于 0.9 就说明这套权重不稳排名前五的城市里有谁上谁下全看专家的临场手感这种结果不适合直接写进报告。改一格判断矩阵就翻盘的指标通常只有两三个。找出来之后有两个处理方向要么在报告里显式标注该结论对 X 指标权重敏感要么回去重新审视这一格的打分依据看是不是专家会开得太快。我一般倾向前者——敏感性本身是信息藏起来不如写出来。从那以后我每次做完 AHP 赋权都会强制走一遍这个流程组合权重归一化、单元素层显式赋值、CR 断言、负向指标方向校验、最后跑一次 ±1 档扰动看排名。五步加起来不到二十分钟但能拦掉我见过的绝大多数翻车。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站