2026/11/2 13:44:01

基于AHP的城市竞争力评价:判断矩阵、权重计算与一致性检验

基于AHP的城市竞争力评价:判断矩阵、权重计算与一致性检验 简介这份文档围绕层次分析法AHP在城市竞争力评价中的应用展开适合经济学、统计学、城市规划与系统工程等方向的学习者以及需要构建综合评价指标体系的课程研究者参考。资源以单一 doc 文件交付压缩包约 832KB内容集中为一份课程学习报告便于直接查阅与整篇研读。已有 140 人学习说明其在方法入门与案例理解上具有一定参考价值。文档从 AHP 的基本思想入手梳理目标层、准则层、要素层与指标层的建模过程并结合判断矩阵构造、1—9 标度、层次单排序、权重计算与一致性检验展开说明后半部分以城市竞争力评价为实例展示指标筛选、权重赋值和综合评价思路。读者可据此理解多因素评价的完整分析链条也可将层次化建模与权重计算思路迁移到其他综合评估场景。1. 一份交不出标准答案的排名表层次分析法用在一座城市的竞争力评价上最先遇到的往往不是数学问题而是资料问题手边只有一本统计年鉴和几位专家的口头判断却要交出一张能解释得通的排名表。城市竞争力评价的指标一抓七十多项GDP、财政收入、科研投入、绿化覆盖率、城乡收入比全在里面量纲从亿元到百分比方向有正有负。等权叠加省事可没人信主成分分析能算算出来的成分却没法翻译成评委听得懂的话。这套方案走的是另一条路把七十多项指标压进四层结构让专家判断变成可检验的权重再用一致性检验来约束主观随意性。它适合正在做城市评价类课程设计、需要一套完整可复现流程的人也适合手里已经有指标数据、只缺一套赋权方法的人。2. 需求拆解与技术选型为什么落在 AHP 而不是 PCA 或熵权法2.1 评价任务的真实约束指标多、方向杂、数据还缺城市竞争力评价的任务书通常长这样给定一组城市用统计年鉴里的公开数据排出名次并且说清名次背后的原因。指标层摊开之后麻烦才开始显形——经济实力下面是 GDP 总量、人均 GDP、财政收入、固定资产投资政府作用下面是财政支出结构、行政管理费用占比对外开放下面是进出口总额、实际利用外资环境水平下面是建成区绿化覆盖率、污水处理率、空气质量优良天数。七十多项指标量纲从亿元跨到百分比再到天数方向有正有负还有一批指标根本拿不到连续年份的数据。更难的是权重。等权叠加是最省事的做法但等权意味着「空气质量优良天数」和「GDP 总量」对城市竞争力的贡献完全一样这个假设在任何答辩现场都站不住脚。主成分分析能给出方差贡献率可它的主成分是原始指标的线性组合很难翻译成「经济实力占 41.62%」这种评委能直接听懂的话。熵权法完全跟着数据离散程度走某个指标在所有城市之间差异极小权重就趋近于零可这个指标在理论上恰恰很重要比如「政府作用」——各城市财政支出结构本来就差不多熵权法会把它判成无关变量。所以这套方案要的不是一个「最先进」的算法而是一条能把理论框架、专家判断和统计数据串起来、并且每一步都能被追问的赋权链路。AHP 正好落在这个位置上它把「哪个维度更重要」这种本来只能靠争论解决的问题变成一组可以被一致性检验约束的数字而且每一层的权重都能单独拎出来汇报。2.2 四类赋权方法的横向对比选型不能凭感觉得摆在台面上比。下面这张表是这类评价任务里最常被拿来比较的四种方法评价维度按「能不能支撑一次完整的答辩」来定而不是按算法复杂度。方法权重来源对样本量要求结果可解释性在本场景的适配度AHP专家两两比较低单城市截面也能算高每一层权重可单独汇报高天然适配分层指标体系主成分分析方差贡献率与载荷中高样本数少于指标数时结果不稳中主成分含义需要二次解释中更适合降维而非赋权熵权法指标离散程度中城市数量少时权重跳动明显中权重可能与理论重要性冲突中适合做客观修正项DEA投入产出效率中对异常值敏感中评的是效率而不是水平低与综合竞争力不是一个概念主成分分析的问题不在算法本身在于它回答的是「哪些指标一起变动」而不是「哪个指标更重要」。因子分析同理旋转之后载荷矩阵确实漂亮可要把载荷翻译成权重还得再做一次人为归一化绕了一圈又回到主观判断。熵权法的优点是客观缺点是太客观——完全无视指标在实际评价体系里的地位只要数据离散度不够权重就掉下去最后算出来的排名往往和常识打架。DEA 更偏题。它衡量的是给定投入下产出能达到多高评的是效率而城市竞争力评价要的是综合水平。一个中小城市资源利用效率可能很高但综合竞争力排不到前面这两件事不能混。AHP 也不是没有代价。它的权重来自专家对两两重要性的判断主观性是内建的一致性检验只能保证判断之间不打架不能保证判断本身正确。这一点必须在报告里写清楚而不是藏起来。2.3 选择 AHP 之后要接受的三个代价第一个代价是主观性消不掉。能做的是用一致性比率把它压到可接受范围再用敏感性分析说明结论稳不稳。指望 AHP 给出一个「客观真理」式的权重方向就错了。判断矩阵改了权重要变这是特性不是缺陷。第二个代价是每层元素数量有上限。1-9 标度的语义上限就是 9一层挂十几个元素专家填到后面全靠猜。所以指标必须分层这也是下一章四层结构的由来。第三个代价是指标相关性会被重复计权。GDP 总量和人均 GDP 高度相关同时挂在经济实力下面等于给经济实力加了两次权。处理办法是事前人工筛一遍把相关系数超过 0.9 的一对指标留一个或者各降一半权重并在附录里写清楚删了哪个、为什么删。提示如果导师追问「为什么不用组合赋权」可以答「AHP 定序、熵权法定量修正」但组合之前要先证明两套权重排序不冲突否则组合出来的结果谁都解释不了。3. 指标体系设计四层骨架与 71 项指标的归位规则3.1 四层结构的必要性从 153 次比较降到可操作如果把 71 项指标直接挂在 4 个准则层下面每个准则要带 17 到 18 个指标专家得完成 C(18,2)153 次两两比较。这不只是工作量的问题人的一致性根本撑不住——比到第四十对的时候专家已经记不住前面填过什么一致性比率必然崩最后只能靠回头硬改矩阵凑数那份矩阵也就失去意义了。四层结构解决的就是这件事。目标层只有 1 个元素即城市综合竞争力它是最终要算出来的那个指数不参与比较。准则层是第一刀切成动力、阻力、相互影响、环境水平四块。要素层是第二刀比如动力再拆成经济实力、政府作用、消费水平、人力资源、科技实力五项。指标层是最底层能直接从年鉴里查到数字。这样每一层的分支数都被控制在 2 到 9 之间单次比较任务最重的一层只有 9 个元素、36 次比较专家半小时内能填完一致性也稳。层次结构的另一个好处是错位可查。最终排名出来某个城市总分低可以顺着树往下看是哪一层拖的后腿——是动力不足还是环境水平太差。这种可追溯性是扁平指标表给不了的。3.2 准则层四个维度的划分逻辑动力和阻力是一对。动力指推动城市竞争力上升的因素经济实力、政府作用、消费水平、人力资源、科技实力都归在这里。阻力指拖住竞争力的因素报告里只放了贫富分化一项。这种数量上的不对称是有意为之阻力维度本身就是一个提醒城市竞争力不是所有指标都越大越好贫富差距拉大竞争力要往下走指标方向必须单独处理。相互影响维度下面挂对外开放和依存度本质描述的是城市与外部的关系。环境水平维度下面挂基础设施和环境水平两个要素。这里有个容易踩的细节准则层叫「环境水平」要素层里也有一个叫「环境水平」同名节点在代码里做字典索引时会互相覆盖权重直接串行。工程实现时给每个节点加唯一 id比如C4、F4-2名字只用于展示索引一律走 id。下面这张表是四层结构在指标层的落地样子方向一栏是后面无量纲化的依据建模阶段就要定死。准则层要素层指标层举例指标方向动力经济实力GDP 总量、人均 GDP、地方财政收入正向动力政府作用财政支出占 GDP 比重、行政管理费用占比正向 / 适度动力消费水平社会消费品零售总额、居民人均消费支出正向动力人力资源每万人高等学校在校生数、从业人员占比正向动力科技实力RD 经费支出、专利授权量正向阻力贫富分化城乡收入比、基尼系数负向相互影响对外开放进出口总额、实际利用外资正向相互影响依存度外贸依存度适度环境水平基础设施人均道路面积、万人拥有公交车辆数正向环境水平环境水平建成区绿化覆盖率、污水处理率正向3.3 指标筛选、方向标注与数据来源处理71 项指标不是都得进模型。筛选盯三条数据可得连续三年能查到口径一致同一本年鉴、同一个指标名不能今年叫「实际利用外资」明年叫「实际使用外资」区分度够所有城市取值几乎一样的指标直接删它进模型只会稀释权重。共线性要人工过一眼GDP 总量和人均 GDP 同时保留等于给经济实力重复计权通常留一个或者两个各降一半。方向标注必须在建模阶段完成分正向、负向、适度三类。城乡收入比越高越差负向外贸依存度不是越高越好适度。这个标注直接决定后面无量纲化用哪个公式标错了排名会整体反过来而且是那种「流程全跑通了、结果怎么都不对」的错排查起来极其费时间。数据来源以统计年鉴和城市统计公报为主缺失值不要填 0。常用做法是用同一城市相邻年份的均值补或者用同省同类城市的均值补并在附录里列出每一个补值位置和补值依据。评委问起来能说清哪几个数不是原始值比假装数据完整要稳得多。原始数据最好单独存一张宽表行是城市、列是指标编码编码和层次结构里的 id 一一对应后面写脚本时直接按编码取列避免手工对表出错。4. 判断矩阵与权重计算从 1-9 标度到全局权重4.1 1-9 标度与判断矩阵的构造规则AHP 把「哪个更重要」量化成 1 到 9 的整数及其倒数。这套标度的语义边界很清晰超出 9 就没有语言能对应了这也是每层元素不能超过 9 个的根本原因。标度含义1两个元素同等重要3前者比后者稍重要5前者比后者明显重要7前者比后者强烈重要9前者比后者极端重要2、4、6、8上述相邻判断的中间值倒数若 i 对 j 的标度为 a则 j 对 i 为 1/a判断矩阵 A 是 n×n 方阵元素 a_ij 表示「相对于上一层某个元素本层第 i 个元素比第 j 个元素重要多少」。它有三条硬约束对角线全为 1因为自己跟自己同等重要a_ij × a_ji 1互反性所有元素为正。第三条一般不会错前两条是后面一致性检验能不能通过的前提也是代码里最该写断言的地方。以准则层为例动力、阻力、相互影响、环境水平四个元素专家给出的判断是动力比阻力明显重要5动力比相互影响稍重要3动力比环境水平稍重要3相互影响比环境水平稍重要2阻力和相互影响、环境水平相比都略次要1/3。填成矩阵就是下面这样行是「比较方」列是「被比较方」顺序一旦定下来就不能中途换。动力 阻力 相互影响 环境水平 动力 1 5 3 3 阻力 1/5 1 1/3 1/3 相互影响 1/3 3 1 2 环境水平 1/3 3 1/2 14.2 两种求权重的方法与可运行实现求权重的主流做法有两种。算术平均法先按列归一化再按行取均值直观、手算可复现课程报告里最常被要求用这一种。特征值法求判断矩阵最大特征值对应的特征向量再归一化理论上更严谨也是大多数软件包的默认实现。矩阵阶数不大的时候两者结果差异通常在千分位用哪种都不影响结论但报告里要写明用了哪种。import numpy as np # Saaty 随机一致性指标键为矩阵阶数 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_weight(A, methodeigen): 计算判断矩阵的权重向量与一致性指标。 A : 判断矩阵二维 list 或 ndarray必须为正互反矩阵 method : eigen 特征值法mean 算术平均法 返回 : (权重向量, 最大特征值, CI, CR) A np.array(A, dtypefloat) n A.shape[0] # 两条硬约束错了后面全白算 assert np.allclose(np.diag(A), 1.0), 对角线必须全为 1 assert np.allclose(A * A.T, 1.0), 必须满足互反性 a_ij * a_ji 1 if method eigen: vals, vecs np.linalg.eig(A) k int(np.argmax(vals.real)) # 最大特征值所在位置 lam float(vals.real[k]) w np.abs(vecs[:, k].real) # 特征向量取实部并取正 else: col_sum A.sum(axis0) # 按列求和 w (A / col_sum).mean(axis1) # 列归一化后按行取均值 lam float(np.mean((A w) / w)) # 由 Aw λw 反推 λ w w / w.sum() # 归一化权重和必须为 1 CI (lam - n) / (n - 1) if n 1 else 0.0 CR CI / RI_TABLE[n] if RI_TABLE.get(n, 0) 0 else 0.0 return w, lam, CI, CR代码里两个断言看着不起眼实际能省掉大量返工。互反性写成A * A.T是逐元素相乘再判断是否全为 1比手写双重循环快得多也更容易在答辩现场解释。method参数留着是方便对照同一份矩阵分别用两种方法跑一遍如果权重差了 5% 以上多半是矩阵本身有问题而不是方法选错了。拿 4.1 的准则层矩阵跑一遍得到的权重约是 0.525、0.072、0.234、0.169最大特征值约 4.082CI 约 0.027CR 约 0.030。和报告里给出的 0.4883、0.0893、0.2328、0.1896 同向同量级差异来自专家打分本身的浮动属于正常范围。CR 远小于 0.1这一层的一致性可以接受。4.3 全局权重的合成与无量纲化打分每一层算出来的都是局部权重——相对于上一层某个父节点的权重不能直接拿去加权求和。全局权重得沿着树往下乘某个指标层的全局权重 它所属准则层权重 × 所属要素层权重 × 它自身的局部权重。import numpy as np # 三个层次的局部权重示例实际由 ahp_weight 逐层算出 w_criteria np.array([0.5254, 0.0724, 0.2338, 0.1685]) # 动力/阻力/相互影响/环境水平 w_factor np.array([0.4162, 0.2618, 0.0624, 0.0986, 0.1611]) # 动力下五个要素 w_index np.array([0.4000, 0.3000, 0.2000, 0.1000]) # 经济实力下四个指标 # 沿路径相乘准则 0 - 要素 0 - 四个指标 w_global w_criteria[0] * w_factor[0] * w_index print(np.round(w_global, 6), round(float(w_global.sum()), 6))乘完之后必须做一次自检把整棵树上所有叶子节点的全局权重加起来结果应当等于 1浮点误差内。如果加起来是 0.87 或者 1.13说明某一层的权重没归一化或者漏了某个分支——这是跑完整套流程后最容易出现的错而且不看求和根本发现不了。权重有了指标值还得先变成可加的分数。极差标准化是最常用的做法正向指标越大越好负向指标越小越好适度指标离中心越近越好。import numpy as np def normalize(x, directionpositive): 极差标准化把不同量纲的指标压到 [0, 1] 区间。 x : 一维数组某个指标在各城市上的取值 direction : positive 正向 / negative 负向 / moderate 适度 x np.asarray(x, dtypefloat) lo, hi x.min(), x.max() if hi lo: # 所有城市取值相同给中性分 return np.full_like(x, 0.5) if direction positive: return (x - lo) / (hi - lo) if direction negative: return (hi - x) / (hi - lo) mid (hi lo) / 2 # 适度指标偏离中心越远扣分越多 return 1 - np.abs(x - mid) / (hi - lo) # 综合指数 全局权重向量与标准化指标向量的内积 # score float(np.dot(w_all, x_norm))标准化这一步有两个参数要留心。direction必须和 3.3 的指标方向表严格对应标错一个那个指标的打分就整体翻转排名跟着乱。hi lo的分支是防止除零顺手给个 0.5 的中性分比直接报错要稳——真实数据里总有一两个指标在所有样本城市上取值完全相同比如某些年份的污水处理率。指标标准化完之后加权求和得到城市综合得分按得分降序排列就是竞争力排名。分维度再算一遍还能得到每个城市在动力、阻力、相互影响、环境水平四个维度上的分项得分用来解释「这个城市为什么排在这儿」比只给一个总分有用得多。5. 常见问题排查一致性检验和权重汇总里最容易翻的五个点5.1 矩阵构造阶段互反性写反与专家打分趋同最容易翻车的是互反性写反。现象是脚本跑得通、CR 也正常可算出来的权重和预期完全相反——本想表达「动力比阻力重要」结果权重跑到了阻力那边。原因基本都出在行列方向上填表时按「列是前者、行是后者」的习惯写代码却按「行是前者、列是后者」解读两个约定没对齐。解决方式很土但有效在填表模板的表头明确写上「行相对列」矩阵填完立刻检查一遍A[0][1] * A[1][0]是否等于 1每一对都过一遍两分钟能省掉一下午。第二个坑是专家打分趋同。现象是算出来的权重几乎均等每个维度都在 0.25 上下浮动排名基本等于等权叠加。原因是专家为了避免判断出错下意识全填 1、3 这类安全值或者干脆所有格子都填同一个数。这种矩阵的一致性比率会好得出奇CR 接近 0但信息量为零。解决办法是在打分表里加一条强制规则同一层里至少要有两组判断的标度差达到 3 以上否则退回重填同时在报告里说明专家人数和打分轮次一轮定稿的专家打分说服力有限。5.2 计算与数据处理阶段RI 取错阶数与负向指标漏处理第三个坑是随机一致性指标取错。现象是 CR 算出来忽大忽小有时候 4 阶矩阵的 CR 突然低于 0.01好得不像真的。原因通常是 RI 表按元素个数索引时错位了一位或者公式里分母用了 n 而不是 n-1。CI 的分母是 n-1这是自由度RI 的本文还有配套的精品资源点击获取