云模型MATLAB代码:正向逆向云发生器、赋权与综合云评价实战

发布时间:2026/11/4 10:36:41
云模型MATLAB代码:正向逆向云发生器、赋权与综合云评价实战 简介这份云模型 MATLAB 代码面向学习云模型理论、需要快速完成算法验证的高校学生与科研入门者重点解决从概念理解到代码落地之间缺少轻量示例的问题。压缩包仅约 1KB内含 2 个 .m 文件以 MATLAB 脚本与函数为主体分别承担主流程演示和云变换计算结构精简下载后可直接在 MATLAB 环境中运行、调试与修改。已有 1581 人学习下载说明其在课程实验、论文复现和算法自学场景中具有一定参考价值。读者可借助它观察云滴生成、云参数变换及权重相关计算的实现思路并在此基础上嵌入综合评价、决策分析或数据不确定性建模等任务代码篇幅短、依赖少也便于逐行阅读和二次开发。在涉及指标权重的综合评价场景中还可用于快速试算和结果对照适合作为云模型入门练习、课堂演示和后续扩展的基础代码。1. 从一摞专家打分表说起这套云模型 MATLAB 代码能解决什么前阵子接手一个综合评价的小需求手里只有八位专家对六个指标的重要性打分每人还附了一个“把握程度”。用均值和方差直接计算权重结果很难解释——两个指标均值几乎一样权重却要分出高下评审一看就会质疑。云模型正好适合处理这种场景Ex 表示期望En 表示离散程度He 表示对不确定性的度量三个数字能把“多数人认为重要、少数人觉得一般”这类模糊判断一起纳入计算。这套云模型 MATLAB 代码覆盖了正向云发生器、逆向云发生器、云模型权重计算和综合云评价函数都是现成的替换输入数据就能直接使用。它适合需要写评价类论文的研究生也适合把专家经验接入系统的工程开发。2. 代码结构与运行环境先看清目录再动手拿到一份 MATLAB 代码包我通常不会先运行 main而是先把目录看一遍搞清楚哪些是算法主体、哪些只是演示脚本。很多人卡住是因为把演示脚本当成了库函数直接调用结果输入输出对不上。这一章先理清文件职责和运行依赖再给一个最小可跑示例。2.1 目录结构九个文件各管一摊这份代码的组织方式比较直接一个文件夹铺平放函数没有包package目录也没有 classdef。对 MATLAB 项目来说这种风格最省事addpath 一下就能用。cloudModel/ ├── main_demo.m 演示脚本赋权 评价一条龙 ├── forwardCloud.m 正向云发生器 ├── backwardCloud.m 逆向云发生器只给云滴 x ├── backwardCloudWithMem.m 逆向云发生器给 x 和确定度 y ├── cloudWeight.m 云模型权重计算 ├── compositeCloud.m 综合云合成 ├── cloudSimilarity.m 云模型相似度 ├── plotCloud.m 云图绘制 └── data/ └── expert_score.mat 八位专家 × 六个指标的打分样例九个文件里真正参与计算的是前七个main_demo.m和data/属于“让你先看见结果”的部分。forwardCloud.m与backwardCloud.m是一对互逆操作前者把三个数字展开成几千个云滴后者把几千个云滴压缩回三个数字。cloudWeight.m是这份代码里最贴近实际业务的一个文件它把专家打分矩阵直接转换成权重向量同时给出每个指标的云参数。compositeCloud.m和cloudSimilarity.m负责最后一步把加权后的综合云与评语云比对落到“优、良、中、差”这样的等级上。理解这个分工之后改代码就有明确入口想换赋权方式只动cloudWeight.m想换评语等级只动main_demo.m里的评语云数组想换相似度算法只动cloudSimilarity.m。不要去改forwardCloud.m它是所有模块的公共依赖。2.2 运行环境与依赖R2016b 以上注意工具箱代码对 MATLAB 版本要求不高R2016b 及以上都能跑。唯一需要注意的是normrnd这个函数它位于 Statistics and Machine Learning Toolbox如果装的是基础版 MATLAB调用时会报“未定义函数或变量”。常见做法是只改一行用randn替代% 依赖 Statistics Toolbox 的写法 En_i normrnd(En, He); % 不依赖任何工具箱的等价写法randn 生成标准正态再线性变换 En_i En He * randn();randn()不带参数时返回一个标准正态随机数乘上标准差He再加上期望En得到的就是 N(En, He²) 分布与normrnd(En, He)完全等价。这个替换在forwardCloud.m里会出现两次另一处是生成云滴x(i)同样改成Ex abs(En_i) * randn()。改完之后整份代码零工具箱依赖拷到任何一台装了 MATLAB 的机器上都能跑。还有一个环境细节MATLAB 的工作路径要指到cloudModel/这一层或者手动addpath(genpath(pwd))。如果只把main_demo.m拖到别处运行会报找不到cloudWeight这是新手最常遇到的第一类错误。2.3 最小可跑示例六行代码看到一朵云先不碰权重用最短的路径确认环境没问题。新建一个脚本生成一朵Ex70, En8, He1.5的云并画出来% 最小验证确认 forwardCloud 和 plotCloud 都正常工作 addpath(genpath(pwd)); % 把当前目录及子目录加入搜索路径 N 3000; % 云滴数量3000 已经能看出形状 [x, y] forwardCloud(70, 8, 1.5, N); plotCloud(x, y, 指标A); % 第三个参数是图标题forwardCloud返回两个等长列向量x是云滴在论域上的坐标y是对应的确定度取值范围在 0 到 1 之间。plotCloud内部就是scatter(x, y, 4, filled)加坐标轴标注没有复杂逻辑可以放心替换成自己的绘图函数。跑通之后观察图形云滴应该集中在 70 附近纵向呈现“中间胖、两头瘦”的钟形。如果看到的是一团散点、中心位置也不对先别怀疑算法大概率是N太小或者He给得太大这两种情况在第五章会详细说。3. 正向云发生器Ex、En、He 三个数字怎么变成一朵云正向云发生器是整个代码包的地基。云模型的所有可视化、所有评价结果、所有论文插图最终都要靠它把三个抽象参数变成几千个看得见的点。3.1 forwardCloud.m 逐行拆解函数签名只有四个输入没有隐藏参数function [x, y] forwardCloud(Ex, En, He, N) % Ex 期望云的重心位置代表这个定性概念最典型的取值 % En 熵概念接受的范围宽度越大云越胖 % He 超熵熵的熵反映云滴离散程度的稳定性越大云越毛 % N 云滴数量决定绘制和统计的采样密度 x zeros(N, 1); % 预分配避免循环中动态扩容 y zeros(N, 1); for i 1:N En_i En He * randn(); % 第一步以 En 为期望、He 为标准差生成一个临时熵 x(i) Ex abs(En_i) * randn(); % 第二步以 Ex 为期望、En_i 为标准差生成云滴 y(i) exp(-(x(i) - Ex)^2 / (2 * En_i^2)); % 第三步算确定度 end end这个循环分三步每一步都在生成一个随机数合起来才是一次完整的正向云滴生成。第一步En_i En He * randn()是整个算法最关键的一行也是它区别于普通正态分布的地方。普通正态分布的方差是固定的而这里让“标准差本身”也随机波动波动的幅度由He决定。He0时En_i恒等于En退化成一条标准正态曲线He越大每次抽到的“临时标准差”差别越大云就越“毛糙”。第二步x(i) Ex abs(En_i) * randn()里那个abs不能省。因为En_i是从正态分布抽出来的理论上可能为负而标准差不能为负。取绝对值是最简单的处理方式代价是En_i的分布被“折叠”了一下当He相对En很大时比如En1, He3这个折叠会明显改变云滴的统计特性导致逆向反推出来的参数和正向输入对不上。这也是第五章要重点说的一条坑。第三步用确定度公式y exp(-(x-Ex)²/(2·En_i²))。注意分母里用的是En_i也就是本次抽样得到的临时标准差与x(i)的计算保持一致。如果误写成固定的En画出来的云在纵向上会过窄和理论图形对不上——这个笔误在二次开发时极易出现。参数上唯一需要留意的是N。它不参与概率分布只影响采样密度。N1000能看出形状N3000适合出图N10000适合做统计量分析。再往上就只是让图更密对结论没有实质影响。3.2 云滴数 N 与超熵 He 的取值经验N好定He不好定。He的取值会直接影响论文评审和业务方对结果的信任程度。He的物理含义是“对 En 这个不确定性度量的不确定性”。说得直白一点如果所有专家对某个指标的看法离散程度都差不多那He应该小如果有的专家打得很集中有的专家打得很散那He就大。我一般的取值区间是He ∈ [0.01·En, 0.3·En]超过 0.3 倍就要停下来想一想数据是不是有问题。用一个具体例子对比He 取值相对 En 的比例云的形态适用场景0.11.2%边缘清晰、几乎是一条正态曲线专家意见高度一致1.012.5%边缘略毛主体集中常规综合评价最常用2.531%明显发散两头出现离散点专家分歧大需要体现不确定性5.062%完全散开重心位置都看不清不建议使用通常是参数误设以Ex70, En8为例He1.0是稳妥的默认值He2.5适合在论文里专门论证“专家意见分歧显著”的场景。He5.0那档基本没法用云滴会散到论域之外画出来的图无法解释。判断He是否合理的另一个办法是看确定度分布。正常云的确定度y应该集中在 0.3 到 0.9 之间如果大量云滴的y低于 0.1说明云滴已经飘到了远离重心的位置He给大了。3.3 画图与结果判读一朵云好不好看这三点plotCloud.m的逻辑很简单但看图有三个判断标准写论文和做汇报时都用得上。function plotCloud(x, y, ttl) scatter(x, y, 4, filled, MarkerFaceAlpha, 0.35); xlabel(论域取值); ylabel(确定度); title(ttl); grid on; end这段代码里MarkerFaceAlpha是半透明参数云滴重叠的区域会自动加深形状看得更清楚。MATLAB R2014b 之前的版本不支持这个属性删掉即可。看云图时依次确认三件事。一是位置云的重心应该落在Ex附近偏了就说明x(i)那行的期望写错了。二是宽度横向跨度大致是Ex ± 3·En如果明显更宽检查是不是把He混进了x(i)的标准差里。三是厚度纵向云滴的上下分布应该随着横向远离重心而逐渐收敛形成两头尖的橄榄形如果上下边界是平行的两条带说明He被误设成了常数而没有参与抽样。提示出论文插图时把N提到 5000 以上并把scatter的点大小从 4 降到 2打印出来的云形边缘更平滑审稿人不容易挑刺。4. 逆向云发生器与云模型赋权从打分数据反推权重正向是由参数生成数据逆向是由数据反推参数。实际项目里逆向用得更多因为手头拿到的永远是一堆打分表而不是现成的 Ex、En、He。4.1 逆向云发生器两种输入两种算法代码包里给了两个逆向函数区别在于手上有没有“确定度”这一列数据。只给云滴x、不给确定度时用一阶中心矩法function [Ex, En, He] backwardCloud(x) % x: 云滴向量也就是一组观测值 % 适用于只知道数值、不知道每个数值可信度的场景 Ex mean(x); % 期望 样本均值 En mean(abs(x - Ex)) * sqrt(pi/2); % 熵由一阶绝对中心矩估计 He sqrt(max(var(x) - En^2, 0)); % 超熵由二阶中心矩扣除 En² 得到 end三行对应三个参数的矩估计。En那行的sqrt(pi/2) ≈ 1.2533是正态分布绝对偏差与标准差的换算系数不能漏漏了算出来的 En 会偏小约 20%。He那行的max(..., 0)是保护理论上var(x)必然大于等于En²但样本量小时可能出现负数开方会返回复数整个后续计算就废了。如果在同一份数据上递归做多轮评价我遇到过连续三次出现He负值的情况根因都是样本量太小一个指标只有三五个专家打分矩估计的偏差被放大了。处理办法见第五章。给定了x和对应的确定度y时用最小二乘拟合会更准function [Ex, En, He] backwardCloudWithMem(x, y) % 由确定度公式反解对 y exp(-(x-Ex)²/(2·En²)) 两边取对数 % 得到 ln(y) -(x-Ex)²/(2·En²)令 z -ln(y) 即为线性关系 z -log(max(y, 1e-8)); % 防止 y0 导致 log 无穷 A [ones(numel(x),1), x, x.^2]; % 构造二次多项式设计矩阵 coef A \ z; % 最小二乘求解 % z a b·x c·x²对照 (x-Ex)²/(2En²) x²/(2En²) - Ex·x/En² Ex²/(2En²) c coef(3); Ex -coef(2) / (2 * c); En sqrt(1 / (2 * c)); He std(sqrt(2 * abs(z)) ) / sqrt(2); % 由残差项估计超熵 end这段代码的核心思路是把非线性的确定度公式取对数后变成二次多项式再用最小二乘拟合。max(y, 1e-8)是必要的保护因为确定度理论上趋近 0 但不等于 0一旦出现 0log(0)返回-Inf拟合会直接崩掉。两个函数的适用边界很清楚backwardCloud拿一行数据就能跑适合快速估算backwardCloudWithMem需要成对的(x, y)适合对精度有要求、且有确定度原始数据的场景。多数综合评价项目里只有打分矩阵用的是前一个。4.2 云模型权重从专家打分到归一化权重向量这是整份代码里最实用的部分。输入一个专家打分矩阵直接输出权重向量和每个指标的云参数。function [w, cloud] cloudWeight(score, normalize) % score: m×n 矩阵m 位专家对 n 个指标的重要性打分 % normalize: 是否归一化默认 true % w: 1×n 权重向量 % cloud: n×3 矩阵每行是 [Ex, En, He] if nargin 2, normalize true; end [m, n] size(score); cloud zeros(n, 3); for j 1:n col score(:, j); % 取出第 j 个指标的全部专家打分 cloud(j, 1) mean(col); % Ex专家意见的中心 cloud(j, 2) mean(abs(col - cloud(j,1))) * sqrt(pi/2); % En意见离散度 cloud(j, 3) sqrt(max(var(col) - cloud(j,2)^2, 0)); % He离散度的不确定性 end w cloud(:, 1); % 先取各指标的期望值 if normalize w w / sum(w); % 归一化保证总和为 1 end end这个函数其实把 4.1 的逆向云发生器按列调用了一遍然后以期望值作为权重来源。为什么用Ex而不是En或He因为Ex代表专家群体对该指标重要性的中心判断En和He描述的是这个判断有多一致二者不参与权重排序而是作为“可信度”的参考。实际用起来经常需要更细的粒度比如把He当作“意见分歧惩罚项”分歧大的指标降低权重。常见做法是引入一个调节系数 α% 分歧惩罚版权重He 相对 Ex 越大权重被压得越低 alpha 0.15; % 惩罚强度0 等于不惩罚 penalty 1 - alpha * min(cloud(:,3) ./ cloud(:,1), 1); w (cloud(:,1) .* penalty); w w / sum(w);alpha的取值范围我一般控制在 0.1 到 0.3。设成 0 就退回原来的等权期望法设成 0.5 以上会让分歧稍大的指标权重被压得几乎归零评审会觉得“怎么这个指标权重这么低”。注意带惩罚的版本不是原始云模型的标准做法属于工程上的改良。写论文时如果用了要在方法部分说明清楚别直接引用成“云模型赋权法”。4.3 综合云与评语云评价等级怎么落定权重出来后下一步是把各指标的云合成一朵“综合云”再和预先设定好的评语云比对。先看合成function [Ex, En, He] compositeCloud(w, cloud) % w: 1×n 权重和为 1 % cloud: n×3 的 [Ex, En, He] Ex sum(w .* cloud(:,1)); % 期望线性加权 En sqrt(sum((w.^2) .* (cloud(:,2)).^2)); % 熵按平方和开根体现独立合成 He sqrt(sum((w.^2) .* (cloud(:,3)).^2)); endEx用线性加权没有争议。En和He用了平方和开根而不是线性加权理由是各指标的不确定性来源互相独立独立随机变量之和的方差等于方差之和。如果改成sum(w .* En)会把不确定性系统性低估导致综合云看起来比实际更“确定”评价结果偏乐观。接下来是等级判定。评语云一般按等级数量和论域区间对半分设定四级评语的写法% 论域 [0, 100]四级评语[差 中 良 优] grades [25, 8, 1.5; 50, 8, 1.5; 75, 8, 1.5; 95, 8, 1.5]; [Ex, En, He] compositeCloud(w, cloud); sim zeros(4, 1); for k 1:4 sim(k) cloudSimilarity([Ex, En, He], grades(k, :)); end [~, idx] max(sim); % 相似度最高的等级即为判定结果相似度的计算用两条期望曲线的重叠面积function s cloudSimilarity(c1, c2) % c1, c2: [Ex, En, He] lo min(c1(1)-3*c1(2), c2(1)-3*c2(2)); % 取两条曲线横向跨度的并集 hi max(c1(1)3*c1(2), c2(1)3*c2(2)); x linspace(lo, hi, 2000); f1 normpdf(x, c1(1), c1(2)); % 用期望曲线代替云滴避免随机性 f2 normpdf(x, c2(1), c2(2)); overlap trapz(x, min(f1, f2)); % 重叠面积 s overlap / max(trapz(x, f1), trapz(x, f2)); endnormpdf是两条期望曲线的解析式用数值积分算交叠面积。这里刻意没有用He参与计算因为相似度看的是“概念中心是否接近”而He描述的是云滴的分布形态卷进来反而会让结果不稳定同一组数据跑两次得出不同等级——这种不确定性在评审场合是致命的。grades里每个等级只填了 Ex 和 EnHe全设成 1.5因为相似度函数压根没读第三列。这是有意简化的结果不是 bug。5. 避坑与排查跑云模型代码最容易翻车的五处这一章是实际调代码时攒下来的。前四条跟算法本身有关最后一条纯属 MATLAB 环境问题。5.1 参数与数值层面的三个坑坑一逆向云算出复数 He。现象调用backwardCloud之后返回值里出现0.0000 0.4472i这样的复数后续所有计算全部报错或者结果变成 NaN。原因He sqrt(var(x) - En^2)里var(x)是一阶矩算出来En之后倒推的。样本量小比如一个指标只有 5 个专家打分时矩估计的偏差会让var(x)小于En²被开方数变成负数MATLAB 直接返回复数。解决加上max(..., 0)截断如 4.1 的代码所示。同时留意如果某次计算He恰好被截断为 0说明这一列数据的信息量不足以估计超熵写报告时要么补数据要么明确说明该指标的He按 0 处理。坑二He 相对 En 过大云图散成一片。现象正向云跑完plotCloud云滴在纵向上从 0 铺到 1横向从 -50 到 200 全有完全看不出重心位置。原因En_i En He * randn()抽出的临时标准差可能远大于En随后x(i) Ex abs(En_i) * randn()用一个巨大的标准差去生成云滴位置自然飘得没边。解决先算He / En这个比值超过 0.3 就回头检查数据。如果确实是数据分歧大导致的考虑对打分做一次预处理——剔除极端离群专家或者改用加权打分。直接调小He属于掩盖问题会让最终评价结果偏乐观。坑三权重没归一化综合云期望超出论域。现象综合云算出来Ex 340而评语论域是[0, 100]相似度计算里所有等级都判成“优”。原因cloudWeight调用时把normalize传成了false或者干脆用了自己手写的权重矩阵。compositeCloud内部只做线性加权不做归一化校验。解决在compositeCloud入口加一行断言比事后排查省事得多assert(abs(sum(w) - 1) 1e-6, 权重向量未归一化当前和为 %.4f, sum(w));这行断言我在所有涉及权重的地方都会加。血泪经验是写论文阶段反复改权重值最容易忘记重新归一化。5.2 工程与调用层面的两个坑坑四专家打分区间与评语云论域不一致。现象等级判定结果恒定落在“中”无论专家怎么打分都不变。原因专家打分用的是 1 到 9 的标度AHP 常用而评语云按 0 到 100 论域设定。综合云Ex大约在 5 附近与所有评语云都离得很远相似度全部趋近 0靠取最大值判出来的等级没有意义。解决入口处统一量纲。要么把打分矩阵线性映射到 0-100要么把评语云的Ex按同一标度重新设定。我现在的做法是把映射函数单独抽出来任何外部数据进模型之前先过一遍function s rescaleScore(s, lo, hi, targetLo, targetHi) s (s - lo) ./ (hi - lo) * (targetHi - targetLo) targetLo; end坑五换机器后 normrnd 报未定义。现象在自己电脑上跑得好好的代码拷到另一台机器上第一行就报错未定义与 double 类型的输入参数相对应的函数 normrnd。原因目标机器装的是基础版 MATLAB没有 Statistics and Machine Learning Toolbox。normrnd属于这个工具箱不是 MATLAB 核心函数。解决按 2.2 的写法全部替换成randn整份代码零工具箱依赖。这事我栽过不止一次后来养成了一个习惯交付 MATLAB 代码前先grep一遍normrnd、randsample、fitdist这几个常用但非核心的函数有就换掉。6. 二次开发把云模型接进自己的评价流程代码跑通只是第一步真正花时间的是把它改成能处理自己业务数据的样子。这里说两个改造方向加一个验证方法。第一个方向是批量入口。原始main_demo.m是给单组数据演示用的业务上往往是一个 Excel 里几十个待评对象、每个对象又有多期数据。我的做法是写一个runBatch.m把cloudWeight和compositeCloud包进循环输入改成table输出直接带对象 ID 和等级列。权重通常只需要针对指标体系算一次所以把cloudWeight提到循环外面循环里只算综合云和相似度速度能快好几倍。第二个方向是向量化forwardCloud。当N提到一万以上、又要给几十个指标画图时逐次循环会明显变慢。把三步抽样一次性抽完function [x, y] forwardCloudFast(Ex, En, He, N) % 向量化版本一次性生成所有随机数省掉循环开销 En_i En He * randn(N, 1); % 一次抽 N 个临时熵 x Ex abs(En_i) .* randn(N, 1); % 一次抽 N 个云滴 y exp(-(x - Ex).^2 ./ (2 * En_i.^2)); end注意En_i也必须抽满N个不能只抽一个然后广播——那就退化成固定标准差的普通正态分布了画出来的云没有“毛边”。这是改写初始化时最容易犯的错误。最后是验证方法也是我最看重的一条。云模型的正向和逆向是一对互逆操作改完代码之后用闭环自检确认参数没被改坏% 闭环自检正向展开再逆向收回参数误差应小于 5% Ex0 70; En0 8; He0 1.5; N 20000; % He 是三阶小量需要大样本才收得准 [x, ~] forwardCloud(Ex0, En0, He0, N); [Ex1, En1, He1] backwardCloud(x); err abs([Ex1-Ex0, En1-En0, He1-He0]) ./ [Ex0, En0, He0]Ex和En的相对误差一般能压到 1% 以内He会大一些N20000时通常在 5% 到 10%。如果He的误差超过 20%八成是抽样的地方漏了abs或者En_i没抽满N个。这个自检跑一遍不到两秒比我事后对着云图猜哪里出错快得多。从那以后我每次动完云模型的参数或抽样逻辑都强制走一遍这个闭环跑不过就不往下改如果改动涉及权重部分我还会用同一组样例数据前后对比权重向量偏差超过 0.02 就回去看代码。分享的这套操作习惯希望帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询