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

CRITIC赋权法MATLAB实现:原理、代码与工程实践

CRITIC赋权法MATLAB实现:原理、代码与工程实践 ★ FEATURED ARTICLE
简介这份资源面向多属性决策分析的学习者与科研人员提供在Matlab环境下实现CRITIC赋权法的完整代码用于客观确定各属性权重并对方案综合打分适合具备Matlab基础、需要处理评价与选优问题的中初级用户。压缩包共1个文件为单个m脚本体积约586B代码结构涵盖数据预处理、属性归一化、一致性、相关性与强度指标计算、权重求解及对象打分等环节并配有子函数划分便于按模块阅读与替换实际数据。目前已有1658人学习下载说明其在同类方法实现中具有一定参考价值。读者可据此快速搭建可运行的赋权流程理解CRITIC准则的计算逻辑并在此基础上扩展可视化或与其他决策方法组合使用。1. 从一张“权重表”说起CRITIC 赋权法在 MATLAB 里到底解决什么问题做综合评价的人大多踩过同一个坑手上有七八个指标领导要一张权重表拍脑袋定权重显得不专业用熵权法又发现某些指标明明高度相关却被重复计权。CRITIC 赋权法就是冲着这个痛点来的——它同时看两件事一是指标自身的对比强度标准差二是指标之间的冲突性相关系数把“波动大且和别人不重复”的指标权重抬上去。MATLAB 实现这套逻辑特别顺手矩阵运算一行顶别人十行corrcoef、std直接调用几十行代码就能跑出一套可复现的权重结果。这份资源适合正在做评价类课题、论文复现或工程选型打分的人拿过去改改指标矩阵就能用。2. 项目结构与技术选型为什么用 MATLAB 而不是 Python2.1 目录与文件组织这类赋权法实现通常不会做成庞大工程核心就是一个主脚本加若干函数文件常见组织方式如下critic_weight/ ├── main_critic.m % 主入口读数据、调函数、输出权重 ├── critic_weight.m % CRITIC 核心计算函数 ├── normalize_data.m % 指标正向化与归一化 ├── data_sample.xlsx % 示例指标矩阵行样本列指标 └── result_weight.mat % 运行后保存的权重结果主脚本负责流程编排critic_weight.m只做纯计算normalize_data.m单独处理量纲问题。这种拆法的好处是换一批数据只改main_critic.m里的读取路径核心算法一行不用动想对比熵权法再挂一个entropy_weight.m即可。我一般会把正向化逻辑也塞进normalize_data.m因为效益型、成本型、区间型指标的预处理方式不同混在主脚本里很快就会乱。2.2 技术选型MATLAB 的优势与边界选 MATLAB 做 CRITIC 不是情怀是实打实的效率考量。CRITIC 的核心是相关系数矩阵和标准差向量MATLAB 的corrcoef返回对称矩阵std(X,0,1)按列求样本标准差一行到位换成 Python 得注意numpy.corrcoef的默认行为、pandas的std(ddof1)差异新手容易在自由度上翻车。另外 MATLAB 的表格数据类型读 Excel 很稳readtable自动识别表头省掉一堆列名映射代码。边界也要说清楚MATLAB 不适合做大规模部署或 Web 服务如果权重结果要嵌进线上系统通常是把 MATLAB 算好的权重导出成 JSON 或 CSV再由后端读取。所以这份资源的定位是“离线计算工具”不是“在线服务”。常见做法是跑完main_critic.m后用writematrix把权重落盘后续系统只消费结果。2.3 数据输入约定指标矩阵的约定必须提前定死否则后面全是血泪经验。约定如下项目约定说明矩阵形状行样本列指标与readtable默认方向一致缺失值不允许 NaN需在预处理阶段插补或剔除指标方向统一转为效益型成本型取倒数或负向化量纲归一化到 [0,1]避免标准差被大量纲指标主导这个约定看起来琐碎但它决定了后面所有公式能不能直接套。尤其是“统一转为效益型”这一步很多人跳过结果成本型指标比如能耗、成本权重算出来是正的方向却反了结论直接翻车。3. 核心算法拆解CRITIC 三步计算与 MATLAB 实现3.1 第一步指标正向化与归一化CRITIC 对量纲敏感必须先归一化。效益型指标用极差法成本型指标先取负再极差区间型指标单独处理。核心代码如下function Xn normalize_data(X, types) % X: 原始指标矩阵行样本列指标 % types: 指标类型向量1效益型-1成本型0区间型 [n, m] size(X); Xn zeros(n, m); for j 1:m col X(:, j); if types(j) 1 % 效益型越大越好 Xn(:, j) (col - min(col)) / (max(col) - min(col) eps); elseif types(j) -1 % 成本型越小越好先取负再极差 neg -col; Xn(:, j) (neg - min(neg)) / (max(neg) - min(neg) eps); else % 区间型落在 [a,b] 内最优此处简化为距区间中心越近越好 a min(col); b max(col); center (a b) / 2; dist abs(col - center); Xn(:, j) 1 - dist / (max(dist) eps); end end end逻辑说明eps是防止分母为零的保险丝极差为 0 说明该指标所有样本取值相同这种指标本身没有区分度归一化后整列为 0后续标准差也是 0权重自然为 0符合直觉。参数types必须和列顺序严格对应我见过有人把成本型标成效益型跑出来的权重表看着正常结论却完全相反——这种错误不会报错只会静默出错最坑。3.2 第二步计算对比强度与冲突性CRITIC 的两个核心量对比强度用标准差sigma_j表示冲突性用sum(1 - r_ij)表示其中r_ij是指标 i 和 j 的相关系数。代码如下function [C, sigma, R] critic_core(Xn) % Xn: 归一化后的指标矩阵 [n, m] size(Xn); % 对比强度按列求样本标准差自由度 n-1 sigma std(Xn, 0, 1); % 相关系数矩阵 R corrcoef(Xn); % 冲突性每个指标与其他指标相关系数补数之和 conflict zeros(1, m); for j 1:m conflict(j) sum(1 - R(j, :)); end % 信息量 C_j sigma_j * conflict_j C sigma .* conflict; end逻辑说明std(Xn, 0, 1)第二个参数 0 表示按样本标准差除以 n-1第三个参数 1 表示按列计算这两个参数写错是高频翻车点。corrcoef返回 m×m 对称矩阵对角线为 1所以1 - R(j,:)中 j 自身那项为 0不影响求和。conflict越大说明该指标和其他指标越不相关信息越独立权重应该越高。参数层面如果某两个指标完全线性相关R对应位置为 1冲突性贡献为 0这正是 CRITIC 想去重的场景。3.3 第三步归一化权重并输出信息量C算出来后权重就是C归一化function w critic_weight(X, types) % 完整流程封装输入原始矩阵输出权重向量 Xn normalize_data(X, types); [C, sigma, R] critic_core(Xn); w C / sum(C); % 打印中间结果方便排查 fprintf(对比强度 sigma: %s\n, mat2str(sigma, 4)); fprintf(信息量 C: %s\n, mat2str(C, 4)); fprintf(权重 w: %s\n, mat2str(w, 4)); end逻辑说明sum(C)是所有指标信息量之和归一化后权重和为 1。打印中间结果是排查利器——如果某个指标权重异常高先看它的sigma是不是被量纲放大了再看conflict是不是因为和其他指标都不相关而被抬高。参数types从主脚本传入示例数据里如果全是效益型指标直接传ones(1, m)即可。3.4 主脚本串联% main_critic.m data readmatrix(data_sample.xlsx); % 读入指标矩阵 types [1, 1, -1, 1, -1]; % 按列标注指标类型 w critic_weight(data, types); % 计算权重 writematrix(w, result_weight.csv); % 落盘供后续系统消费readmatrix比xlsread更现代返回纯数值矩阵省去单元格解析。writematrix输出 CSV后端语言都能直接读。这套流程跑通后换数据只需改文件路径和types向量算法层零改动。4. 跑起来与避坑从示例数据到自己的指标矩阵4.1 环境准备与首次运行MATLAB R2019b 及以上版本即可readmatrix和writematrix在这个版本之后才稳定。首次运行步骤把整个文件夹加入 MATLAB 路径右键文件夹 → 添加到路径 → 所选文件夹。打开main_critic.m确认data_sample.xlsx与脚本同目录。按 F5 运行命令行应输出 sigma、C、w 三行中间结果。检查当前目录下是否生成result_weight.csv。如果报“未定义函数或变量”九成是路径没加对如果报“索引超出矩阵维度”检查types长度是否等于指标列数。这两类错误占了新手问题的八成。4.2 换成自己的数据替换数据时按这个顺序操作能少走弯路先把 Excel 整理成纯数值、无合并单元格、无表头行或表头单独放再用readmatrix读入然后数一下列数写types向量最后跑一遍看权重和是否接近 1浮点误差允许 1e-6 偏差。如果权重和明显不等于 1说明中间有 NaN 混入sum(C)变成了 NaN归一化自然失效。4.3 常见问题排查现象一权重全是 NaN。原因通常是原始矩阵含 NaN 或某列极差为 0 且未加eps。解决运行前加assert(~any(isnan(data(:))), 存在缺失值)把问题挡在入口。现象二某个指标权重接近 1其他接近 0。原因多半是该指标量纲远大于其他指标归一化没生效或types标错导致该列没走极差。解决打印Xn每列的min和max确认都在 [0,1] 区间。现象三corrcoef报警告“矩阵接近奇异”。原因是指标间存在完全线性相关或样本数少于指标数。解决样本数至少是指标数的 3 倍否则相关系数估计不可靠完全相关的指标考虑合并或剔除。现象四结果和论文里的权重对不上。原因通常是标准差自由度选择不同除以 n 还是 n-1或归一化方法不同极差法 vs 向量归一法。解决对照论文公式逐项核对std的第二个参数就是自由度开关。提示每次改完types或数据源先跑一遍并肉眼检查中间输出别直接看最终权重表。中间量对了结果才可信。5. 二次开发把 CRITIC 嵌进评价流水线的几个改造点5.1 与熵权法组合做组合赋权单一赋权法都有偏差CRITIC 偏重冲突性熵权法偏重离散度工程上常见做法是两者加权组合。改造思路把critic_weight.m和entropy_weight.m并列调用得到w1和w2再用w alpha*w1 (1-alpha)*w2合成alpha取 0.5 是默认起点也可以用博弈论组合赋权求最优系数。验证方法对比组合权重与单一权重的排序一致性用 Spearman 相关系数衡量corr(w1, w_combined, type, Spearman)一行就能看。5.2 批量跑多组数据课题里经常要对比多个年份或多个方案手改路径太低效。把主脚本改成函数外层套循环files dir(data_*.xlsx); W zeros(numel(files), m); for k 1:numel(files) data readmatrix(files(k).name); W(k, :) critic_weight(data, types); end writematrix(W, weight_matrix.csv);这样一次跑完所有文件权重矩阵按行对应文件后续做趋势分析直接读。注意m要在循环外确定且所有文件列数必须一致否则W预分配会出错。5.3 结果可视化与报告输出权重表给领导看光有数字不够。加一段横向条形图barh(w); set(gca, YTickLabel, indicator_names, YTick, 1:numel(w)); xlabel(权重); title(CRITIC 赋权结果);indicator_names从 Excel 表头读或手写元胞数组。图出来后用exportgraphics(gcf, weight_bar.png, Resolution, 300)导出高清图直接贴进报告。这一步花不了十分钟但能让结果的可信度上一个台阶。5.4 一个我踩过的坑早些年做某评价项目数据里有个成本型指标忘了标-1跑出来的权重表看着挺正常排序也像模像样结果汇报时被问“为什么能耗越高得分越高”当场愣住。回头查才发现是types向量错位。从那以后我每次跑赋权之前都强制先打印一张“指标名—类型—归一化后均值”的对照表肉眼过一遍再往下算。这个习惯救过我至少三次。希望这份拆解能帮你少走一遍我走过的弯路把 CRITIC 这套逻辑真正用进自己的评价流水线里。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站