尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

AHP层次分析法:判断矩阵、一致性检验、权重计算与MATLAB全流程

AHP层次分析法:判断矩阵、一致性检验、权重计算与MATLAB全流程 1. 从矩阵填完就出结果说起AHP被用坏的三处硬伤层次分析法AHP大概是所有决策类方法里门槛最低、被引用最多、也最容易被用残的一个。我见过太多这样的场景论文里贴出一张判断矩阵紧接着一行经计算CR0.030.1通过一致性检验然后权重表一列完事。答辩老师随口一句你这个1到9的分是谁定的人就慌了。问题不在于AHP本身有多难而在于绝大多数人只学了操作流程没弄明白每一步在管什么。这一节先把三个最常见的硬伤摆出来后面再逐个拆。1.1 判断矩阵不是打分表它是两两比较的压缩表达很多人第一次接触AHP脑子里留下的印象是给指标打分。这是错的。判断矩阵填的是相对重要性不是绝对分数。价格这一项你不是给价格打7分而是在问和交期相比价格重要多少。这个区别决定了三件事。第一判断矩阵必须是正互反矩阵对角线全为1第i行第j列与第j行第i列互为倒数即a_ij × a_ji 1。这一条几乎没人会填错因为大家知道对称位置要取倒数。但真正的约束在第二件事上。第二AHP隐含了一个更强的假设——传递性。理想情况下如果价格比质量重要3倍质量比交期重要2倍那价格就应该比交期重要6倍。现实里专家打分经常给出5倍、4倍甚至3倍。这种不一致无法避免因为人脑对倍的感知本来就是粗糙的、非线性的。AHP的处理方式不是强行要求你填得完全一致而是量化这个不一致的程度再给一个容忍阈值。这就是一致性检验存在的全部理由它不是流程里的装饰。第三判断矩阵是信息压缩。n个指标如果让人直接给权重专家会很犹豫你让他说价格占0.35、质量占0.23他大概率是瞎凑的凑出来还不一定加起来等于1。但两两比较是人的强项问哪个更重要比问重要多少绝对数值要容易得多。n个指标需要 n(n-1)/2 次比较4个指标只要6次7个指标21次10个指标就是45次。这个数字后面会再提它是AHP实用性的分水岭。1.2 一致性检验不是盖章它是在替你找逻辑矛盾我见过最典型的误用是程序跑出CR0.15不通过于是回去把某个3改成2再跑0.08通过。这种做法在结果上是解决了在逻辑上是把矛盾藏了起来。一致性检验抓的是基数型矛盾也就是倍数关系自相冲突。举个夸张的例子甲比乙强3倍乙比丙强3倍逻辑上甲该比丙强9倍但你在矩阵里填了2甲比丙只强2倍。这时候矩阵内部就打架了。CR算出来的就是这个打架的严重程度。但要注意一致性检验抓不住次序型矛盾。什么是次序型矛盾甲比乙好、乙比丙好、丙又比甲好这是个循环。这种矩阵单独看不出来问题——它只是很不一致CR会很大你还得回头看。但更隐蔽的情况是三个循环里只循环了一部分CR居然还能通过。所以我一直建议算完CR之后回头把每一行的排序位置在脑子里过一遍确认没有甲乙丙甲的鬼打墙。程序算的是数字逻辑得人来守。还有一个反直觉的点CR通过不代表权重合理。CR只说明你的比较没有严重自相矛盾不说明你的比较符合事实。一份按错误认知填的、内部高度一致的矩阵照样能跑出漂亮的CR0.01然后给出一组完全跑偏的权重。一致性是必要条件不是充分条件。1.3 算完单层权重就收工方案层合成这一步被整层跳过这是三个硬伤里最要命、也最常见的一个。完整的AHP至少有三层目标层选最优方案、准则层价格、质量、交期、服务、方案层甲、乙、丙三家供应商。你需要在准则层做一次两两比较得到准则权重然后对每一个准则单独再做一次方案层的两两比较得到在价格这个维度下甲乙丙各得多少分。4个准则、3个方案意味着你要做 1 4 5 个判断矩阵。很多人的流程是做一个准则层矩阵算权重展示结束。方案层根本没建或者建了一个就贴上去。这样得到的结论是价格占0.54、质量占0.23这是半成品回答问题的话必须落到所以选甲。方案层的合成方式是加权求和某个方案的总得分 Σ该方案在第j个准则下的权重 × 第j个准则的权重。这一步叫层次总排序。而且这里还有第二个坑总排序也要做一致性检验用的是把各准则的CI和RI按准则权重加权后的合成值。这个检验十个做AHP的人里九个不做。2. 1-9标度、互反性与人脑量化的边界判断矩阵到底怎么填是整个AHP里最考验功力的地方。算法部分是确定的、可复现的填矩阵部分是经验的、需要解释的。这一节把标度的来历、填矩阵的操作规范以及一个完整案例讲清楚。2.1 为什么是1到9而不是1到100Saaty当年定这个标度不是拍脑袋。他做过心理学实验结论是普通人对同时出现的对象能可靠区分的重要性等级大约在7±2个。也就是说你让人区分稍微重要和明显重要他能分你让人区分重要2.3倍和重要2.7倍他分不出来而且今天分出来的和明天分出来的还不一样。于是1-9标度的定义是这样的标度含义前者相对后者1同等重要3稍微重要5明显重要7强烈重要9极端重要2, 4, 6, 8上述相邻判断的中间值倒数若i与j比较得 a_ij则j与i比较得 1/a_ij这里有个新手最容易踩的坑方向搞反。矩阵第3行第1列填的应该是交期相对价格的重要性不是价格相对交期。填反了整套权重就翻转了而且因为倒数关系矩阵看起来还是合法的CR照样能过你不会发现。我的土办法是填之前先在草稿纸上写一行行比列贴在屏幕上填完再抽查两个格子——挑一个大的看看对称位置是不是它的倒数再念一遍第i行指标相对第j行指标的重要程度通常就能抓住。另一个问题是标度不够用。比如两家供应商报价100和103这个差距用1-9标度完全体现不出来只能填1同等重要但那明明是有差别的。这时候有两种处理一是承认差异不显著填1二是改用实际比值构造矩阵前提是这个准则可以量化、且方向统一越大越优或越小越优。后一种做法后面案例里会演示。2.2 填矩阵时的实操细节谁填、填几轮、怎么问我做过几轮企业咨询里的AHP打分总结下来几个经验。第一打分人必须是真正懂业务的人不是职位最高的人。我见过一次选供应商的评估让总经理填质量准则的矩阵结果他把所有指标都填成同等重要因为他不关心细节。这类矩阵CR一定漂亮因为全是1但毫无信息量。正确做法是每个准则找对应的负责人价格找采购、质量找品控、交期找计划。没人比干活的人更清楚哪个更重要。第二不要让人看到完整矩阵要拆成一个个问题问。你把一张4×4的表扔给专家他第一反应是这要填多久第二反应是我随便填填。正确的做法是问价格和质量比哪个重要重要到什么程度等他回答完再问下一个。问他答的时候把1-9的含义表放在手边。一次问6个到10个问题是合理的超过20个专家就开始疲劳后面的答案质量断崖式下跌。这也是为什么准则层指标数建议控制在7个以内。第三量纲要统一别混着来。有的准则越大越优质量得分、服务水平有的越小越优价格、交货周期。如果在同一层里混着专家脑子会绕。我的习惯是先全部转成越大越优的表达比如价格优势而不是价格本身交期响应速度而不是交货天数。第四写清口径。质量到底指什么是抽检合格率、还是客户投诉率、还是使用寿命不写清楚不同专家对同一个词的理解能差出十万八千里最后汇总出来的矩阵就是个四不像。我的做法是在打分表最上面加一行指标定义用一句话给每个准则下操作性定义必要的时候带上数据来源。2.3 一个完整案例三家供应商比价选型说一百遍不如走一遍。假设我们要从甲、乙、丙三家供应商里选一家准则四个价格C1、质量C2、交期C3、服务C4。先做准则层。我的判断是价格最重要质量次之交期再次服务最后。填出来的矩阵如下——C1 价格C2 质量C3 交期C4 服务C1 价格1345C2 质量1/3123C3 交期1/41/212C4 服务1/51/31/21用列归一化再取行平均这个方法叫和积法后面还会细讲得到准则权重价格0.5423质量0.2333交期0.1397服务0.0847四个数加起来正好等于1。最大特征值 λmax ≈ 4.052CI (4.052−4)/3 ≈ 0.0173查RI表n4时RI0.89所以 CR 0.0173/0.89 ≈ 0.0195远小于0.1通过。然后是方案层四条准则各做一个3×3矩阵。价格这一项三家的报价分别是甲100元、乙120元、丙90元。这是典型的成本型指标可以直接用报价比值构造矩阵a_ij 报价j / 报价i。——甲乙丙甲11.20.9乙0.833310.75丙1.11111.33331这个矩阵是完美一致的因为它的每一行都是同一个向量的倍数λmax 严格等于3CI0。权重就是报价倒数的归一化甲0.3396、乙0.2830、丙0.3774。丙最便宜所以拿最高分符合直觉。质量这一项是定性的靠专家判断。结论是甲最好、丙次之、乙最差——甲乙丙甲132乙1/311/2丙1/221用方根法每行元素连乘后开n次方再归一化算甲 (1×3×2)^(1/3) 1.8171乙 (1/3×1×1/2)^(1/3) 0.5503丙 (1/2×2×1)^(1/3) 1。归一化后得甲0.5396、乙0.1634、丙0.2970。λmax ≈ 3.0093CI ≈ 0.00465CR ≈ 0.0089通过。交期这一项乙响应最快甲次之丙最慢而且差距明显——甲乙丙甲11/22乙214丙1/21/41这个矩阵恰好也是完美一致的因为 a_甲丙 a_甲乙 × a_乙丙 0.5×4 2。权重为甲0.2857、乙0.5714、丙0.1429。服务这一项丙最好甲次之乙最差——甲乙丙甲121/2乙1/211/3丙231方根法得甲0.2970、乙0.1634、丙0.5396λmax ≈ 3.0093CR ≈ 0.0089通过。最后做总排序把方案层权重矩阵3×4乘上准则权重向量4×1供应商价格质量交期服务综合得分甲0.33960.53960.28570.29700.3751乙0.28300.16340.57140.16340.2853丙0.37740.29700.14290.53960.3396结论是甲胜出但优势不大只比丙高了0.0355。这种时候就该做敏感性分析了——把价格的权重从0.5423调到0.45看看结论会不会翻盘。如果一调就翻说明这个结论是脆弱的决策者需要知道这一点。这一步绝大多数人不做但它恰恰是AHP最有价值的部分之一不是告诉你选谁而是告诉你这个选择有多稳。3. 权重算法四选一特征值法、方根法、和积法、最小二乘判断矩阵填好了接下来是怎么从矩阵里把权重抠出来。教科书上一句话带过求最大特征值对应的特征向量归一化即为权重。但实际用起来你会发现同一份矩阵用不同方法算出的权重能差出几个百分点。这一节把这几种方法的来龙去脉讲透。3.1 特征值法的数学含义为什么偏偏取最大特征值严格地说特征值法是AHP的官方解法。逻辑是这样的如果判断矩阵是完美一致的那么它必然可以写成a_ij w_i / w_j的形式其中 w 就是我们要的权重向量。把这个式子代进Aw里你会发现Aw n·w——也就是说完美一致的矩阵w 就是它的特征向量对应的特征值是 n。现实中的矩阵不一致Aw n·w不成立。但根据Perron-Frobenius 定理正互反矩阵的最大特征值 λmax 一定是实数、单重、且大于等于n对应的特征向量一定存在且全为正分量。λmax 越接近n矩阵越一致。所以取最大特征值对应的特征向量作为权重在数学上是最贴合如果它是一致的它就应该是那个样子这个思路的近似。这里有个工程上必须知道的细节特征向量的正负号和归一化。用 MATLAB 的eig()求出来的特征向量符号是不确定的可能是全负、可能部分为正。Perron-Frobenius 保证了最大特征值对应的特征向量同号但求出来的数值可能整体乘了-1。所以不能直接w v/sum(v)因为如果 sum(v) 是负数归一化后就变成了负数权重。稳妥的写法是先取绝对值再归一化或者判断一下sum的符号。另一个细节eig()返回的特征值里有可能是复数3阶以上矩阵经常有一对共轭复根。直接对整个特征值数组取max()在复数情况下会报错或者给出错误结果。必须先用real()取实部。这两点看着琐碎但我见过不止一个人卡在这里跑出来的权重是负数还以为是矩阵填错了。3.2 方根法与和积法的手算验证与误差对比特征值法精度最高但要解特征方程手算基本不可能。所以实务中有两个近似算法误差通常在千分之一到百分之一量级完全够用。方根法几何平均法把每一行的 n 个元素连乘再开 n 次方最后归一化。r_i (∏(j1..n) a_ij)^(1/n) w_i r_i / Σ r_j和积法算术平均法先对每一列做归一化每列除以该列的和然后对每一行求平均。w_i (1/n) · Σ(j1..n) [ a_ij / Σ(k1..n) a_kj ]回到上面那个准则层的矩阵我们对比一下三种方法的结果准则特征值法方根法和积法价格0.54170.54230.5423质量0.23360.23330.2333交期0.13980.13970.1397服务0.08490.08470.0847差异在小数点后第三位。对于决策问题来说这个精度差异完全可以忽略。我一般建议正式论文里报特征值法的结果因为它是AHP的标准解法评委认手工验算或者快速试算时用方根法拿计算器就能算。如果三种方法算出来的排序结果不一样那就说明矩阵本身太敏感了得回头审视打分而不是纠结用哪种算法。有一点需要提醒方根法在元素差距极大时比如矩阵里有9和1/9同时出现稳定性会比和积法稍差因为连乘容易放大误差。如果你的标度跨度很大优先用和积法或特征值法。3.3 归一化方式对结果的影响被高估了吗网上经常有人争论权重到底该按列和归一化还是按行和归一化还有人问要不要先对矩阵做标准化。我的看法是对正互反矩阵来说这些都是伪问题。原因很简单AHP的权重本质是比例不是绝对量。所有正确的算法最后都会得到一个正向量你把它归一化到和为1就得到了权重。归一化方式只影响中间过程不影响最终排序和相对比例。真正影响结果的是矩阵本身填得对不对。倒是有一个容易被忽略的点如果某个准则下所有方案的评分都一样那个准则对总排序就不起作用。比如服务这一项如果三家打分完全相同那这个准则的权重再高也是白搭。判断这种情况的方法是看方案层权重矩阵的列——某一列如果全是相同的数这一列就是废列。这时候可以考虑把该准则删掉或者重新审视打分是不是过于保守大家都填1。我在实际项目里遇到过一次四个准则里有两个的方差极小一问才知道打分人图省事凡是拿不准的全填了1。这就属于数据质量问题算法救不了。4. CI、RI、CR一致性检验的完整链路与它的软肋一致性检验是AHP区别于普通打分法的地方也是最容易被当成形式主义的一步。这一节把它拆到根上。4.1 CI的推导λmax 为什么天然大于等于n前面说过完美一致时 λmax n。那不一致时会怎样Perron-Frobenius 给出了下界对任意 n 阶正互反矩阵λmax ≥ n等号成立当且仅当矩阵完美一致。这就有了一致性指标的天然形式CI (λmax − n) / (n − 1)为什么要除以 (n−1)因为 λmax 与 n 的差距会随矩阵阶数增大而累积。所有特征值之和等于矩阵的迹而正互反矩阵的迹恒为n对角线全是1。剩下的 n−1 个特征值在复数平面上张成一个区域λmax 超出n的部分本质上是从这 n−1 个残余里分出来的。除以 (n−1) 就是把它摊平得到一个与阶数无关的尺度。CI 0 意味着完美一致。CI 越大矛盾越严重。但CI本身没法直接判断好坏因为多大的CI算大跟阶数有关——3阶矩阵的CI天然就小8阶矩阵的CI天然就大。所以需要RI来归一化。4.2 RI表是怎么造出来的n1和2为什么不检验RI 叫随机一致性指标它的生成方法很朴素随机生成大量通常500到1000个同阶的正互反矩阵每个元素从 {1/9, 1/8, ..., 1/2, 1, 2, ..., 9} 里均匀随机取然后对每个矩阵算 CI最后取这些 CI 的平均值。直觉上就是如果一个人完全瞎填平均会产生多大的不一致 CR CI/RI 的意思就是你的不一致程度相当于瞎填的平均水平的百分之多少。小于0.1说明你比瞎填强了十倍。常用的RI表这也是中文教材和MATLAB代码里最常出现的一套n123456789101112131415RI000.520.891.121.261.361.411.461.491.521.541.561.581.59n1和n2为什么不用检验因为做不到不一致。1阶矩阵只有一个元素12阶矩阵只有 a12 和 a21互为倒数无论怎么填都自洽。CI 恒等于0RI 也定义为00/0没有意义所以这两阶直接跳过。程序里如果不做这个判断会报 NaN 错误。这里插一个非常实用的提醒不同文献的RI表数值不完全一样。Saaty 原始论文里 n3 用的是 0.58n4 用的是 0.90和上表略有出入。这意味着同一份矩阵用不同RI表算出来的 CR 会有百分之几的差异。如果你在写论文一定要注明用的是哪套RI值否则复现的人会以为你算错了。我个人的习惯是用上面这套许树柏版本也是最通行的一套在论文里写一句RI取值参照许树柏《层次分析法原理》。4.3 CR不达标的四条修正路径及代价CR 超过 0.1 怎么办这里有四条路按推荐程度排序。第一条也是最正确的一条回头审视判断本身。把矩阵里最大的那几个元素找出来看看有没有明显的传递性冲突。比如 a_ij7、a_jk5那 a_ik 理论上应该接近35远超标度上限9这就是结构性的不一致——说明你用7和5的时候实际上是在说i远胜j和j远胜k但i和k之间的比较又被标度限死在9以内。这种情况下应该把7和5降到3和2让整体协调。这条路的代价是耗时但收益是把打分的逻辑理顺了。第二条微调最接近临界的元素。如果CR是0.11、0.12这种轻微超标找出对CR贡献最大的元素通常是绝对值最大的把它往相邻标度挪一格比如从5改成4。这条路快但要注意改动幅度要小否则会引入新的不一致。改完必须重新算CR且要保证排序结论不变——如果改完之后甲的排序掉了那说明原矩阵本来就是脆的。第三条放宽阈值到0.2。有文献支持这个做法理由是0.1这个阈值本身是经验性的缺乏统计学的严格依据而且高阶矩阵n≥7很难通过0.1。我不太推荐在论文里这么干除非你能引用文献佐证。在企业内部决策场景里0.2是可以接受的因为决策本身就不是精确科学。第四条用一致性改进算法迭代修正。有专门的算法把你的矩阵往一致方向投影比如最小二乘投影法。结果是数学上漂亮了但改动可能很大最后得到的矩阵已经不是你原来打分的那个意思了。这条路我基本不用。我个人的底线是CR超过0.2就别硬撑了重新组织打分。0.2以上的不一致多半不是手滑而是打分人对指标理解有偏差或者指标定义本身有问题。这时候改数字没用得改定义。4.4 被漏掉的层次总排序一致性检验这是本节的重点也是我最想强调的一点。绝大多数人只对每个单层矩阵做了一致性检验忘了总排序也要检验。逻辑是这样的单层矩阵各自都通过检验但它们的不一致会累加到最终排序里。总排序的合成一致性指标是CI_total Σ(j1..m) w_cj · CI_j RI_total Σ(j1..m) w_cj · RI_j CR_total CI_total / RI_total其中 w_cj 是第j个准则的权重CI_j 是这个准则下方案层矩阵的一致性指标RI_j 是它对应的随机一致性指标。用前面供应商的例子算一遍。准则层权重是 (0.5423, 0.2333, 0.1397, 0.0847)四个方案层矩阵的CI分别是 0价格完美一致、0.00465质量、0交期完美一致、0.00465服务。CI_total 0.5423×0 0.2333×0.00465 0.1397×0 0.0847×0.00465 0.00108 0.00039 0.00147 RI_total (0.5423 0.2333 0.1397 0.0847) × 0.52 1.0 × 0.52 0.52 CR_total 0.00147 / 0.52 0.0028远小于0.1通过。这个例子里的值很小是因为两个矩阵完美一致实际项目里没那么幸运。但不管怎样这个检验必须做而且必须在论文里写出来。审稿人看到这一步会知道你确实懂AHP而不是照抄模板。5. MATLAB从零到跑通单层权重到总排序的完整脚本关键词里带了层次分析法matlab代码说明很多人是要落到实现的。这一节给一套可以直接跑、可以直接改的完整脚本并且把埋在里面最容易出错的几个地方标出来。5.1 单层权重函数三行代码里藏着的坑先写最核心的单层权重计算函数。function [w, lambda_max, CI, CR] ahp_single(A) % A: 判断矩阵正互反 % w: 归一化权重向量 n size(A, 1); if n 1 w 1; lambda_max 1; CI 0; CR 0; return; end % 特征值法 [V, D] eig(A); lambda_all real(diag(D)); % 坑1特征值可能是复数必须取实部 [lambda_max, idx] max(lambda_all); v real(V(:, idx)); % 坑2特征向量可能整体为负 w abs(v) / sum(abs(v)); % 坑3先取绝对值再归一化 CI (lambda_max - n) / (n - 1); RI [0 0 0.52 0.89 1.12 1.26 1.36 1.41 1.46 1.49 ... 1.52 1.54 1.56 1.58 1.59]; if n numel(RI) error(矩阵阶数超过15RI表不够用请改用其他一致性判据); end if n 2 CR 0; else CR CI / RI(n); end end三个坑都在注释里标出来了逐个说。坑1复数特征值。3阶以上的正互反矩阵eig返回的特征值经常是一对共轭复数加一个实数。如果直接max(diag(D))MATLAB 在比较复数时会按模长比较可能选中的不是实数的最大特征值。必须先real()。坑2特征向量符号。前面解释过eig返回的特征向量符号任意。对于正互反矩阵最大特征值对应的特征向量是严格同号的Perron-Frobenius所以取绝对值是安全的、不会改变信息。坑3归一化。如果先sum(v)再除sum是负数的话权重全变负最后得到的排序会是反的而且不报错。这个坑极隐蔽我用abs一次性解决。再补一个实践建议加输入校验。判断矩阵该满足的三个条件——对角线为1、a_ij × a_ji 1、所有元素为正——写个断言检查一下。手填矩阵时打错一个倒数太常见了不加校验你可能要调试半天。assert(all(abs(diag(A) - 1) 1e-9), 对角线必须全为1); assert(max(max(abs(A .* A - 1))) 1e-6, 矩阵不满足互反性 a_ij * a_ji 1); assert(all(A(:) 0), 矩阵元素必须为正);5.2 多层合成的完整流程脚本有了单层函数多层合成就是循环加矩阵乘法。下面是一套完整的主脚本直接用前面供应商的例子。%% 层次分析法供应商选择完整示例 clear; clc; %% 第一层准则层 A_c [1 3 4 5; 1/3 1 2 3; 1/4 1/2 1 2; 1/5 1/3 1/2 1]; [w_c, lam, CI_c, CR_c] ahp_single(A_c); fprintf(准则层权重: %.4f %.4f %.4f %.4f\n, w_c); fprintf(准则层 λmax%.4f CI%.4f CR%.4f\n, lam, CI_c, CR_c); %% 第二层方案层对每个准则各建一个矩阵 % 价格 C1 A1 [1 1.2 0.9; 1/1.2 1 0.75; 1/0.9 1/0.75 1]; % 质量 C2 A2 [1 3 2; 1/3 1 1/2; 1/2 2 1]; % 交期 C3 A3 [1 1/2 2; 2 1 4; 1/2 1/4 1]; % 服务 C4 A4 [1 2 1/2; 1/2 1 1/3; 2 3 1]; A_list {A1, A2, A3, A4}; m numel(A_list); p 3; % 方案数 W zeros(p, m); % 方案层权重矩阵 CI_vec zeros(1, m); RI_vec zeros(1, m); RI [0 0 0.52 0.89 1.12 1.26 1.36 1.41 1.46 1.49 ... 1.52 1.54 1.56 1.58 1.59]; for j 1:m [W(:, j), ~, CI_vec(j), CRj] ahp_single(A_list{j}); RI_vec(j) RI(p); fprintf(准则%d 方案层权重: %.4f %.4f %.4f CR%.4f\n, ... j, W(:, j), CRj); end %% 层次总排序 score W * w_c; fprintf(\n综合得分: 甲%.4f 乙%.4f 丙%.4f\n, score); [best, idx] max(score); fprintf(最优方案编号: %d\n, idx); %% 总排序一致性检验最容易被漏掉的一步 CI_total sum(w_c .* CI_vec); RI_total sum(w_c .* RI_vec); CR_total CI_total / RI_total; fprintf(总排序 CI%.4f RI%.4f CR%.4f\n, ... CI_total, RI_total, CR_total); if CR_total 0.1 disp(总排序一致性检验通过); else disp(总排序一致性检验未通过需重新审视判断矩阵); end跑下来输出的综合得分是 甲0.3751、乙0.2853、丙0.3396和手算完全对上。总排序CR0.0028通过。注意脚本里w_c .* CI_vec这一句w_c是列向量4×1CI_vec是行向量1×4直接相乘会做矩阵乘法得到标量恰好是这个加权和但语义不清晰。加转置后做点乘得到的是向量再sum逻辑更明确。这个小细节在探索代码时能省不少调试时间。5.3 群决策聚合为什么用几何平均而不是算术平均实际项目里很少只有一个人打分。三个专家给出三份判断矩阵怎么汇总直接对每个位置取算术平均(a_ij^(1) a_ij^(2) a_ij^(3))/3是错的。为什么因为算术平均不保持互反性。举个例子专家A填 a_12 3专家B填 a_12 1/3完全相反的意见算术平均得 (30.3333)/2 1.667。再看反方向两位专家给的 a_21 分别是 1/3 和 3平均还是 1.667。但 1.667 × 1.667 ≠ 1矩阵不再是互反的后面的特征值计算全部失效。正确做法是几何平均a_ij (∏(k1..K) a_ij^(k))^(1/K)几何平均有个漂亮的数学性质如果每个专家的矩阵都满足a_ij × a_ji 1那么聚合后的矩阵也满足。验证一下上面的例子√(3 × 1/3) 1反向 √(1/3 × 3) 1互为倒数成立。如果专家有权重比如首席专家权重0.5另外两位各0.25就用加权几何平均a_ij ∏(k1..K) (a_ij^(k))^(α_k), Σα_k 1MATLAB 里一行搞定function A_group ahp_group(A_cell, alpha) % A_cell: 1×K 的 cell每个元素是一个判断矩阵 % alpha: 1×K 的专家权重和为1 K numel(A_cell); n size(A_cell{1}, 1); A_group ones(n); for i 1:n for j 1:n vals zeros(1, K); for k 1:K vals(k) A_cell{k}(i, j)^alpha(k); end A_group(i, j) prod(vals); end end end还有一条路是先各自算权重再平均。但这样得到的是权重的平均而几何平均得到的是矩阵的平均两者不完全等价。我倾向于先聚合矩阵再算权重因为这样你还能对聚合后的矩阵跑一致性检验得到一个整体的CR供汇报。如果先算权重各专家矩阵的CR是分散的汇报时说不清。还有一个实务上的坑如果两位专家意见严重对立一个人说甲比乙强7倍另一个人说乙比甲强7倍几何平均会把它们压成1也就是不偏不倚。这在数学上合理但在决策上很危险——它掩盖了专家之间的真实分歧。我的做法是聚合之前先算一下专家之间的一致性程度如果分歧太大不聚合而是把分歧本身作为结论汇报上去让决策者去协调。数字不该替人做这种判断。6. AHP的适用边界与组合玩法AHP好用但不是万能。这一节聊聊它什么时候会失灵以及怎么和别的方法组合。6.1 什么时候AHP会失灵第一指标太多的时候。前面提过n个指标要填 n(n-1)/2 个格子。n7 是21次比较n10 是45次n15 是105次。超过20次比较专家的判断质量就会明显下滑后面的答案开始敷衍。所以准则层的指标数控制在7个以内是有道理的这也是心理学上7±2这个神奇数字的来源之一。如果指标确实很多正确的做法是分层——先分成3到4个大类每个大类下再分3到4个细指标做成四层结构。这样每一层的比较次数都控制在可接受范围内。第二需要完全客观的时候。AHP本质是主观赋权法判断矩阵来自人的经验。如果你面对的是纯客观的数据问题比如按历史数据排序AHP不合适。这时候该用熵权法、变异系数法、CRITIC法这类客观赋权方法。第三方案数远大于准则数、且方案差异性很小的时候。AHP擅长的是少数几个方案在少数几个维度上的比较。如果方案有几十个方案层的判断矩阵会大到填不动而且方案之间的细微差异用1-9标度根本表达不出来。这时候AHP通常只用来定准则权重方案排序交给别的方法。第四准则之间高度相关的时候。AHP假设各准则相互独立。如果你同时放了销售额和利润额两个准则它们在很大程度上是同一件事权重会被重复计算。判断方法很简单算一下准则之间的相关系数如果超过0.8考虑合并或者删掉一个。6.2 AHP熵权法主客观组合赋权的正确姿势最经典也最实用的组合是AHP 定主观权重 熵权法定客观权重 组合赋权。熵权法的逻辑是从数据本身出发某个指标下各方案的数值差异越大说明这个指标携带的信息越多该给更高的权重如果所有方案在该指标上数值都一样这个指标没有区分度权重应该接近0。它不需要专家打分但缺点是权重完全跟着数据走可能得出价格最不重要这种反常识的结论。组合的方式有几种我用得最多的是乘法合成后归一化w_i (w_AHP_i × w_熵权_i) / Σ(w_AHP_j × w_熵权_j)还有一种更灵活的是线性加权w_i α · w_AHP_i (1 − α) · w_熵权_iα 取0.5是最省事的做法但更严谨的做法是用博弈论组合赋权或者距离函数法去解一个最优的α。博弈论那套的思路上是找到一个α使得组合权重与两种单一权重的偏差之和最小。听起来复杂其实就是解一个两变量的最优化问题MATLAB里几行fmincon就完了。实操上要注意一点熵权法需要原始数据矩阵而且要做无量纲化处理。效益型指标用(x - min)/(max - min)成本型用(max - x)/(max - min)处理后所有值落在[0,1]之间。有个细节坑如果某列的最小值和最大值相等所有方案一样会出现分母为0。标准做法是对整列赋一个相同的小权重或者干脆删掉这个指标。另外为了取对数不出现负无穷通常要把数据平移一个极小量比如统一加0.0001。6.3 AHPTOPSIS从权重到排序的最后一公里AHP给出准则权重TOPSIS给出方案排序这是一对黄金搭档。TOPSIS的思路很直观先把所有方案的指标值归一化然后构造出正理想解每个指标都取最好值和负理想解每个指标都取最差值计算每个方案到这两个理想解的距离最后算贴近度C_i d_i^- / (d_i^ d_i^-)C_i 越大方案越优。AHP的权重在这里的作用是给距离计算加权——计算欧氏距离时每个维度的差值乘以对应权重的平方根。这套组合的好处是TOPSIS直接用原始数据不需要像AHP那样对每个准则再建一个方案层判断矩阵。也就是说如果你有客观数据报价、合格率、交货天数那么准则权重用AHP定方案排序用TOPSIS做两头都省事。只有那些完全没法量化的准则比如企业声誉才需要真的去建方案层矩阵。用前面那个例子改造一下价格、质量、交期、服务四项如果前三项都有客观数据只有服务是定性的那么你只需要为服务建一个3阶判断矩阵剩下三项直接用数据。代码上的改动很小把W矩阵中对应列换成归一化后的客观数据即可。最后分享一个我在实际项目里踩过的坑。TOPSIS对指标方向的敏感度极高效益型和成本型搞反一个排序就全乱。我现在的习惯是在数据预处理阶段就给每个指标加一个方向标签然后在代码里用if分支处理绝不靠我记得这个指标是越小越好。写代码时省的那点事debug的时候要还回去十倍。另外如果某个指标下所有方案数值相同TOPSIS里它对距离的贡献为0但它的权重还在——这时候各种方法的结论会有微妙差异值得在报告里提一句。我个人在实际操作中的体会是AHP真正的价值不在那个权重数字而在填矩阵的过程。当你逼着自己回答价格和质量哪个更重要的时候很多原本含糊的判断被逼到了明面上。我做过的一个项目里采购和质量两个部门为哪个准则更重要吵了两个小时最后吵出来的矩阵CR只有0.02但那个讨论过程让整个决策逻辑清晰了这比任何权重数字都值钱。至于算法本身记住三件事就够了判断矩阵是两两比较不是打分、CR一定要算、总排序的一致性别忘了。剩下的都是细节。
返回列表