MATLAB综合评价实战:层次分析法、主成分分析与模糊评价
简介这是一份面向MATLAB学习者、科研人员及数学建模参赛者的综合评价方法代码包围绕评价与决策类题型整理内容涵盖模糊综合评价、层次分析法、主成分分析法等常用多准则决策算法。层次分析法通过分层比较量化指标权重主成分分析实现高维数据降维模糊综合评价则处理带有不确定性的评价问题资源既给出对应MATLAB实现源码也配有方法讲解文档与下载说明文本便于读者对照原理与代码、拆解算法流程并动手复现。压缩包约23.03MB文件类型以doc文档、txt说明和MATLAB脚本为主方法文档与代码相互配合适合快速上手或复习相关算法目前已有75人学习下载。借助代码模板与配套文档读者可掌握各类评价方法的MATLAB实现思路并迁移到实际项目、课程设计或数模竞赛中。1. 综合评价方法matlab.zip三类决策模型先搞清楚再动手做评价类课题时最常见的坑不是算法不会推而是拿到一个「综合评价方法matlab.zip」就开始跑代码跑完不知道结果怎么解释。这个压缩包我拆过里面是层次分析法、主成分分析法和模糊综合评价的MATLAB实现还带一份《综合评价方法大全.doc》和下载说明。它的价值不在代码本身而在于把「评价与决策类题型」的完整套路给齐了——判断矩阵怎么建、降维后怎么打分、模糊隶属度怎么设刚好是课程设计、数学建模和科研论文里反复要用的三件套。适合已经会用MATLAB基本矩阵操作、但没系统做过多准则决策分析的读者新手照着文档能跑通熟手可以拿它的数据接口替换成自己的业务数据。2. 层次分析法判断矩阵构建与权重计算的MATLAB实现2.1 先把层次结构落成矩阵再谈权重层次分析法AHP是评价类问题里最容易被误用的方法。很多人一上来就调ahp函数实际上核心工作是把决策目标拆成准则层和方案层然后用1~9标度构造判断矩阵。举个例子要评价三个供应商准则层可能有质量、价格、交期三项两两比较得出一个3×3的矩阵矩阵元素a_ij表示第i个指标相对第j个指标的重要程度。这个矩阵的性质决定了后面所有计算的合理性。理想情况下它应该满足a_ij * a_ji 1并且任意两行成比例也就是完全一致性。但实际打分不可能这么完美所以要在代码里做一致性检验——算一致性指标CI再除以随机一致性指标RI得到CRCR小于0.1才能继续往下走。下面这段代码把判断矩阵输入、权重计算、一致性检验一次做完% ahp_weight.m - 层次分析法权重计算 function [w, CR] ahp_weight(A) % A: n x n 判断矩阵按1~9标度填写 % w: 归一化后的权重向量 % CR: 一致性比例小于0.1通过 n size(A, 1); % 特征向量法求权重 [V, D] eig(A); [~, idx] max(diag(D)); % 最大特征值对应列 w V(:, idx) / sum(V(:, idx)); % 归一化 % 一致性检验 lambda_max D(idx, idx); CI (lambda_max - n) / (n - 1); RI [0 0 0.58 0.90 1.12 1.24 1.32 1.41 1.45]; % 前两项无用 CR CI / RI(n); if CR 0.1 warning(CR%.4f超过0.1请调整判断矩阵, CR); end endeig(A)返回特征值和特征向量取最大特征值对应的特征向量做归一化就是权重。RI表直接内置省得每次翻书。注意RI只到n9实际用到更多指标时要自行扩展。判断矩阵行为颠倒时a_ij和a_ji互为倒数这个约束要在填矩阵时就遵守否则CR肯定爆表。2.2 从代码到结论权重向量的业务解读权重向量算出来只是第一步关键是要能解释。假设上面3×3的矩阵算出的权重是 [0.637, 0.258, 0.105]含义是质量指标占了决策权重的六成多价格和交期加起来不到四成。这时候就要回头问这个比例符合业务直觉吗如果明显不合理除了调整判断矩阵还要检查标度是否填反了。实际使用中建议把判断矩阵单独放一个脚本或Excel里不要嵌在函数中。我一般这样组织数据输入方便后续替换成供应商打分或方案评分% input_data.m criteria {质量, 价格, 交期}; A [1 5 3; % 质量 vs 价格明显重要 1/5 1 1/3; % 价格 vs 交期稍不重要 1/3 3 1]; % 交期 vs 质量介于中间 [w, CR] ahp_weight(A); disp(权重:); disp(array2table(w, VariableNames, criteria));这里用array2table给权重加上列名直接打印出来比看裸数字直观得多。CR结果如果通过权重就可以接着用于方案层的计算不通过就得回去改矩阵。改的时候一个小技巧优先调整最大比值那个元素因为它是CR超标的常见来源。3. 主成份分析法从协方差矩阵到综合评价得分的降维实战3.1 为什么评价问题要用主成分而不是直接平均综合评价里指标太多时直接用加权平均会带来两个问题一是量纲不同价格是元、质量分是百分制直接加权等于给量纲大的指标不公平的权重二是指标之间往往相关比如「服务质量」和「客户满意度」高度相关加进去等于重复计算。主成分分析法PCA的定位是先把原始指标线性变换成互不相关的主成分再取累计贡献率够高的前几个主成分合成综合得分这样既降维又避免了信息重叠。PCA在MATLAB里的实现很成熟特别是新版推荐用pca函数替代老旧的princomp。它的输入是n行m列的标准化数据矩阵输出里最重要的三个量是score主成分得分、latent特征值、explained各主成分方差百分比。用之前必须先做标准化否则数据尺度差异会直接把小量纲指标淹没。3.2 完整计算流程标准化、主成分提取、得分合成下面这段代码演示如何用MATLAB自带函数完成从原始数据到综合排序的全过程数据假设是10个评价对象、4个指标% pca_evaluation.m raw [80 90 60 70; 75 85 70 65; 88 78 75 80; ... 70 92 65 72; 85 88 72 78; 82 79 80 74; ... 78 86 68 76; 84 83 77 81; 90 74 82 85; 76 87 73 79]; % 1. 标准化 X zscore(raw); % 每列减去均值除以标准差 [n, m] size(X); % 2. 主成分分析 [coeff, score, latent, ~, explained] pca(X); % 3. 按累计贡献率85%选主成分 cumvar cumsum(explained); k find(cumvar 85, 1); fprintf(选取前%d个主成分累计贡献率%.2f%%\n, k, cumvar(k)); % 4. 以贡献率为权重合成综合得分 w_pca explained(1:k) / sum(explained(1:k)); total_score score(:, 1:k) * w_pca; [~, order] sort(total_score, descend); disp(综合得分排名行号对应原始数据序号:); disp(order);zscore做标准化是必须的少了这步pca的结果会被量纲带偏。explained直接给出百分比不用像旧代码那样用latent / sum(latent)换算。第4步里用贡献率做权重本质是让方差大的主成分在综合得分里占更高比重这比等权重合理但也隐含一个假设——方差大就代表评价信息多这在指标都是正向指标时成立遇到逆向指标需要先正向化。3.3 特征值与载荷矩阵怎么看每个主成分的含义主成分能解释什么要看coeff矩阵里的载荷。每一列是一个主成分每个元素是该主成分与对应原始变量的相关系数。表格里列一下某次运行的前两个主成分载荷指标PC1载荷PC2载荷含义提示质量0.52-0.31PC1主要综合了质量与价格价格0.480.27PC2突出价格与交期的对比交期0.430.55PC2可理解为交期因子服务0.53-0.20PC1贡献稳定如果PC1的载荷在四个指标上都是正的且接近它就是一个「综合规模因子」如果某个主成分在某几个指标上载荷绝对值大就把它命名成那个方面。这一步的商业价值在于不仅知道排名结果还知道排名主要被哪个潜在维度驱动。实际跑数据时如果前两个主成分累计贡献率已经到90%就可以画个二维散点图观察评价对象的分群。注意pca默认按奇异值分解SVD计算数据量小于维度时也不会报错但解释性差。常规做法仍然是样本数至少是指标数的5倍以上否则主成分不稳定。4. 模糊综合评价隶属度函数与合成算子的MATLAB应用4.1 为什么评价里有「模糊」一说现实中很多评价指标没法用精确数值衡量比如「教学效果」的「好」「较好」「一般」这是典型的模糊概念。模糊综合评价的思路是先定义评语集比如 V {优, 良, 中, 差}然后对每个指标给出一个隶属于各评语等级的隶属度向量比如某教师的「教学效果」隶属度为 (0.5, 0.3, 0.2, 0)表示他被评为「优」的程度是0.5「良」是0.3以此类推。所有指标的隶属度向量拼成一个模糊评价矩阵再结合指标权重用模糊合成算子算出最终综合评价向量。MATLAB里做这件事不需要工具箱纯粹用矩阵乘法就能实现。关键是有两处要自己定一是隶属度怎么来二是合成算子选哪种。隶属度可以来自专家打分也可以来自梯形隶属函数对连续型数据我用trapmf造隶属度更客观。合成算子常用加权平均型即普通矩阵乘法它比取大取小的主因素突出型保留更多信息适合整体评价而不适合单点决策。4.2 隶属度计算与模糊矩阵合成代码假设评语集有4级某个指标的实际测量值是x四个等级的梯形分布边界是[min, 低峰, 高峰, max]下面函数把数值转成隶属度向量% membership.m function mu membership(x, bounds) % bounds: 4x2 矩阵每行是某等级的梯形边界 [a b c d] % 返回1x4隶属度向量 mu zeros(1, 4); for i 1:4 a bounds(i,1); b bounds(i,2); c bounds(i,3); d bounds(i,4); if x a || x d mu(i) 0; elseif x b x c mu(i) 1; elseif x a x b mu(i) (x - a) / (b - a); else mu(i) (d - x) / (d - c); end end mu mu / sum(mu); % 归一化保证总和为1 end得到每个指标的隶属度向量后把它们竖着叠成模糊评价矩阵R再用权重向量w做加权合成% fuzzy_eval.m w [0.4 0.3 0.2 0.1]; % 四个指标的权重来自AHP或熵权法 R [membership(85, [60 70 80 90]); ... % 指标1实测值85 membership(72, [50 65 75 85]); ... % 指标2实测值72 membership(90, [70 80 90 100]); ... % 指标3实测值90 membership(68, [40 55 70 85])]; % 指标4实测值68 B w * R; % 普通矩阵乘法即加权平均型合成 [maxB, level] max(B); fprintf(综合评价向量: [%.3f %.3f %.3f %.3f]\n, B); fprintf(最大隶属度等级: %d (%.3f)\n, level, maxB);这里的w维度是1×4R是4×4矩阵乘法后B是1×4每个元素代表总体隶属于「优、良、中、差」的程度。最大隶属度原则直接取最大元素对应的等级作为最终评语。注意w必须是归一化的否则B的结果会超过[0,1]范围解释起来就麻烦了。R每行都要归一化因为隶属度本质上是该指标在各等级上的比重大小不是概率但归一化后求和为1更便于后续解释。4.3 权重来源与评价尺度选择模糊评价里权重w通常和层次分析法配合使用——先用AHP算指标权重再做模糊合成。这是非常经典的组合压缩包里的文档也提到了这一点。权重也可以来自熵权法用指标的变异程度算信息熵数据差异越大权重越高。两种方式没有谁绝对正确AHP反映专家主观经验熵权法反映客观数据区分度实际中我倾向于把两者按0.6和0.4加权融合避免单一来源偏差。评语集等级数一般取3到5。等级太少区分度不够太多则隶属度边界难定。MATLAB里处理模糊计算时注意矩阵维度必须匹配权重个数等于指标数R的行数也等于指标数错一位就会报维度不一致错误。这类错误最常见原因是前一步标准化或缺失值处理没有对齐排错时先检查size(w, 2)和size(R, 1)是否相等。5. 三个小技巧数据统一、批量跑方法、结果可视化5.1 把原始数据整理成统一格式再喂给不同方法压缩包里三种方法各写各的脚本直接换方法时最烦的是数据结构不一致。我习惯先把所有指标正向化、标准化成一张表然后三个方法共用这张表。正向化就是逆向指标取倒数或取负值标准化用zscore。下面这个片段把原始Excel数据变成统一格式并顺手写入.mat文件方便后续调用% prepare_data.m data readmatrix(评价数据.xlsx); % 每行一个对象每列一个指标 data(:, 逆向指标列号) -data(:, 逆向指标列号); % 正向化 X zscore(data); % 统一标准化 save(eval_data.mat, X, data);这一步能让AHP的指标打分、PCA的协方差计算、模糊评价的隶属度计算都从同一个eval_data.mat里取数据。实际处理时注意readmatrix在MATLAB R2019a之后才出现更老版本用xlsread。5.2 同一份数据上循环跑三种方法结果横向比较每种方法给出的排名大概率不完全相同这很正常因为原理不同。与其纠结哪个正确不如把三种排名并列输出分析结论一致的部分再处理分歧部分。写个小脚本一次性输出% compare_methods.m load(eval_data.mat); % AHP结果假设已有判断矩阵A w_ahp ahp_weight(A); % PCA结果 [~, score, ~, ~, explained] pca(X); k find(cumsum(explained)85, 1); pca_score score(:, 1:k) * (explained(1:k)/sum(explained(1:k))); % 模糊评价结果隶属度矩阵R已经算好见4.2节 B w_ahp * R; % 并排显示排名1为最优 [~, r1] sort(w_ahp, descend); [~, r2] sort(pca_score, descend); [~, r3] sort(B, descend); table(r1, r2, r3, VariableNames, {AHP, PCA, Fuzzy});如果某个对象在PCA和Fuzzy里排名一致在AHP里却大幅偏离优先检查AHP判断矩阵是不是一致性太差。三种方法结果都一致的对象基本可以锁定为真正的优等或劣等不需要再纠结。5.3 用雷达图和条形图让评价结果能放进报告最后一步是把得分可视化。雷达图适合展示多指标表现条形图适合展示综合排名。MATLAB原生没有雷达图函数但可以用polarplot或自定义坐标轴来画。简单起见推荐用spider_plot第三方函数下载后放当前目录即可或者用这个轻量实现% radar_chart.m % 假设某对象各指标归一化得分在v中v为1xm向量 theta linspace(0, 2*pi, length(v)1); v_plot [v, v(1)]; polarplot(theta, v_plot, LineWidth, 1.5); set(gca, Thetick, 0:45:315, RTick, 0:0.2:1);注意polarplot在单个对象多指标时视觉效果不错多个对象重叠会糊成一团建议每组最多画三个对象。条形图直接用bar即可综合排名按降序排列时加FaceColor,flat并按分数映射颜色让报告输出更有层次。这套流程跑通后你可以把任意带指标数据的评价问题套进这三个方法里数据量从几十行到几千行都能扛得住。唯一要留意的是PCA对异常值敏感如果数据里有缺失或离群点先用fillmissing和rmoutliers清一轮否则主成分方向会被极端值带偏。本文还有配套的精品资源点击获取