
简介面向学习与应用云模型、需要快速完成权重计算或不确定性建模的高校学生、科研人员与工程实践者这份MATLAB代码包提供可直接运行的实现思路省去从零搭建基础函数的时间。压缩包共2个文件均为.m脚本整体约1KB体量轻便便于在MATLAB环境中查看、调用与二次修改适合作为课程实验、论文复现或算法验证的起点。已有1581人学习下载说明其在云模型相关练习中具有一定参考价值。代码围绕云模型的基本变换与权重处理展开读者可据此理解云滴生成、参数设置与结果计算流程并在此基础上替换数据、调整参数用于自己的评价、决策或赋权场景。整体结构精简适合已有MATLAB基础、希望快速上手云模型实现的读者参考使用。1. 云模型 matlab 代码包到底解决什么问题从定性评语到定量权重的落地路径手里有一组专家打分想把“很重要、重要、一般”这类评语变成能进 MATLAB 计算的权重又不想把不确定性一刀切掉云模型 matlab 代码包就是干这个的。它把定性评语转成期望 Ex、熵 En、超熵 He 三个数字特征再用正向云、逆向云和云模型权重计算把评语接进评价流程。这份代码适合两类人一类是刚开始做指标体系评价手里只有专家语言评语想把“权重”算得别太硬另一类是把云模型接进既有 MATLAB 工程需要一套能直接调用的函数而不是临时拼几行脚本。它不解决数据采集也不替代业务判断解决的是“评语怎么变成云参数、云参数怎么变成权重、权重怎么进综合评价”这条链路。2. 云模型三数字特征与正向云发生器先把 Ex、En、He 调明白云模型和模糊隶属度最容易混。模糊隶属度给定一个确定函数输入一个值就输出一个确定隶属度云模型不是这样它用随机实现去描述“定性概念在定量空间里的分布”。期望 Ex 是概念的中心熵 En 是概念覆盖的宽度超熵 He 是云滴厚度的离散程度。正向云发生器就是拿这三个参数生成云滴让你先看见这个“概念云”长什么样。在 MATLAB 里正向云发生器的核心只有几行先以 En 为期望、He 为标准差生成正态随机数 Enn再以 Ex 为期望、Enn 为标准差生成云滴 x最后算隶属度 mu。这里最容易被忽略的是 Enn 可能取到负值。负的 Enn 会让正态采样方向翻转云滴图看起来会“散成两团”。我一般直接取 abs(Enn)或者在生成后把过小的 Enn 截断保证云滴形状可解释。2.1 为什么云模型不是模糊隶属度模糊隶属度更像一张固定模板同一个输入永远得到同一个隶属度。云模型保留了随机性同一个输入每次生成的云滴隶属度会有细微差异差异大小由 He 控制。这个差异不是误差而是云模型表达“概念边界不清晰”的方式。做权重和评价时En 决定指标评语的分歧范围He 决定这个分歧本身有多不稳定。用云模型做权重常见做法是先把专家评语云化再用云参数的期望值归一化得到基础权重En 和 He 用来判断专家意见是否分散。这里要留个心眼只拿 Ex 归一化会丢掉不确定性信息权重看起来干净但专家分歧被藏起来了。后面做敏感性分析时En 大的指标权重波动会更明显这是正常现象不是代码算错。正向云发生器的调用顺序建议固定成forwardCloud(Ex, En, He, N)N 是云滴数。N 太小云滴图毛刺重N 太大画图和循环会拖慢。我一般自检用 3000 个云滴正式评价里用 1000 到 2000 个就够。下面这个函数可以直接建forwardCloud.mfunction [x, mu, drop] forwardCloud(Ex, En, He, N) % forwardCloud 正向云发生器 % Ex: 期望En: 熵He: 超熵N: 云滴数量 % x: 云滴位置mu: 隶属度drop: [x mu] 便于直接画图 if nargin 4 N 2000; end En abs(En); He abs(He); Enn randn(N, 1) .* He En; % 以 En 为期望、He 为标准差 Enn(abs(Enn) 1e-6) 1e-6; % 防止极端接近 0 x randn(N, 1) .* abs(Enn) Ex; % 云滴位置 mu exp(-((x - Ex).^2) ./ (2 * Enn.^2)); % 云滴隶属度 drop [x, mu]; end这段代码的逻辑是“两次正态采样”第一次采样决定这次云滴的宽度第二次采样决定云滴落在哪里。En控制云滴整体铺开的宽度He控制每次宽度本身的抖动。abs(Enn)和1e-6截断是血泪经验少了这两步偶尔会出现隶属度异常点。参数上Ex 按指标实际范围设En 一般取 Ex 的 1/6 到 1/3He 取 En 的 0.1 到 0.3具体要看评语粒度。2.2 正向云发生器代码与参数把函数建好后先别急着接权重跑一段自检脚本。下面这段可以放在main_demo.m开头用来确认云滴图是不是“中间厚、两边薄”的钟形雾化带rng(7); % 固定随机种子便于复现 Ex 0.70; En 0.08; He 0.015; N 3000; [x, mu, drop] forwardCloud(Ex, En, He, N); figure; scatter(drop(:,1), drop(:,2), 6, filled); xlabel(指标值); ylabel(隶属度); title(正向云滴图Ex0.70, En0.08, He0.015); grid on;运行后先看三件事。第一云滴最密的位置是否在 Ex 附近第二云滴横向铺开的范围是否覆盖你关心的评语区间第三云滴带有没有明显的断层或双峰。如果云滴全部挤在 Ex 附近大概率是 En 设小了如果云滴带太厚、上下边界糊成一片He 可能偏大如果云滴图出现两团检查 Enn 是否取了负值。参数没有唯一公式但可以按下面这张表先估一轮再画图微调参数含义常见取值调大后的现象Ex概念中心按指标归一化范围设如 0.2/0.5/0.8云滴整体平移En概念宽度Ex 的 1/6 到 1/3云滴横向铺开变宽He云滴厚度En 的 0.1 到 0.3云滴带变厚、边缘更雾N云滴数量1000 到 3000图更密计算更慢这张表只用于起步。真正调参时我会先把 En 定在“评语之间能分开、又不至于完全断裂”的位置再动 He。He 太大会让评价结果每次跑都差一点He 太小又会让云模型退化成普通隶属度函数。做权重时He 不是越大越好它只是告诉你专家意见的“厚度”。2.3 用云滴图反推参数是否合理云滴图是云模型的黑匣子窗口。做综合评价前我习惯对每个等级云各画一张图叠在一起看覆盖关系。比如“差、中、良、优”四个等级如果“中”和“良”的云滴带大面积重叠评价时一个实测值可能同时落进两个等级最后靠权重硬拉结果就会反直觉。这时候要么缩窄 En要么重新定义等级中心。还有一种情况是 Ex 间隔太小。四个等级 Ex 分别是 0.2、0.4、0.6、0.8En 却设成 0.2云滴带会连成一片。评价矩阵看起来每个等级都有隶属度最后排序却排不出差异。我一般让相邻等级 Ex 的间隔至少是 En 的 2 到 3 倍再看云滴图确认。这个比例不是标准只是工程上少翻车的起点。正向云发生器只负责“从参数到云滴”。如果你手里已经有专家打分下一步要走逆向云把样本反推成 Ex、En、He再进权重计算。正向和逆向的参数口径要一致正向里的 En 是宽度逆向估出来的 En 也应该能生成形状接近的云滴否则说明样本分布和假设不匹配后面权重再漂亮也不可信。3. 逆向云发生器与权重确定从专家打分到云模型权重逆向云发生器解决的是“手里有一批打分怎么反推云参数”。连续打分场景常用均值法Ex 取样本均值En 用平均绝对偏差乘 sqrt(pi/2) 估计He 用方差减 En 平方后开方。这个做法计算快适合样本量大于 30 的情况。样本少、分布偏、或者专家打分出现双峰时He 可能算出负数这不是 MATLAB 报错而是样本方差小于 En 平方说明这批数据不适合硬套单云模型。云模型权重有两条常见路线。第一条是连续打分每位专家给每个指标一个 0 到 100 的分先用逆向云得到每个指标的云参数再用 Ex 归一化得到基础权重En 和 He 用来标注分歧。第二条是语言评语专家从“极重要、很重要、重要、一般、不重要”里选一个每个评语对应一组云参数聚合后归一化。两条路线不冲突关键是输入口径要统一不能一部分指标用连续分、另一部分用语言评语最后权重尺度对不上。3.1 逆向云算法选择均值法、拟合法的边界均值法的代码短适合做第一版权重。下面这个backwardCloud.m可以直接用function [Ex, En, He] backwardCloud(x) % backwardCloud 逆向云发生器均值法 % x: 一列云滴样本通常是多位专家对同一指标的评分 x x(:); n numel(x); if n 3 error(样本量太少至少给 3 个评分再估云参数); end Ex mean(x); absDev mean(abs(x - Ex)); En sqrt(pi / 2) * absDev; % 平均绝对偏差估计熵 s2 var(x, 1); % 总体方差 He sqrt(max(s2 - En^2, 0)); % 防止方差不足导致负值 end这段代码里En用的是平均绝对偏差不是标准差。平均绝对偏差对极端打分没那么敏感专家里有一两个离群值时En 不会突然被拉得很大。He用max(...,0)截断是为了让后续权重计算不中断。截断不是万能药如果 He 经常被截成 0说明样本方差太小要么专家意见高度一致要么打分尺度太窄后者会让权重区分度变差。均值法之外还有拟合法和四阶矩法。拟合法的思路是用样本矩去匹配云参数代码更长适合研究型任务工程落地里均值法加云滴图检查已经够用。我的习惯是先用均值法跑一版把每个指标的 Ex、En、He 打到命令行重点看 En/Ex 的比值。比值超过 0.35 的指标我会回头查专家打分表看是不是评语理解不一致。这个阈值不是标准只是排查线索。样本量也要看。n 小于 10 时Ex 还能看En 和 He 的波动会很大n 在 30 以上参数才相对可解释。如果专家只有 5 位不要硬做很细的权重敏感性分析先把评语聚合粒度放粗或者把多个指标合并成一个维度减少单指标样本不足带来的抖动。3.2 云模型权重计算代码语言评语场景更适合用云标度。下面给一组常用的五级云标度Ex 从 9 到 1En 和 He 按评语粒度递减。这张表不是固定标准换行业时可以改 Ex但 En 和 He 的比例关系最好保持“越极端的评语En 略大、He 略小”避免极端评语反而更模糊。评语ExEnHe极重要9.01.50.30很重要7.01.20.25重要5.01.00.20一般3.00.80.15不重要1.00.60.10把评语序号矩阵和云标度表传进cloudWeightByScale.m就能得到权重和每个指标的聚合云参数function [w, P] cloudWeightByScale(scaleIndex, scaleCloud) % cloudWeightByScale 用云标度把专家语言评语转成权重 % scaleIndex: m x nm 位专家、n 个指标元素是评语行号 % scaleCloud: K x 3每行 [Ex En He] % w: 1 x n 权重P: n x 3 聚合后的指标云参数 [m, n] size(scaleIndex); if size(scaleCloud, 2) ~ 3 error(scaleCloud 必须是 K x 3 的矩阵); end if any(scaleIndex(:) 1) || any(scaleIndex(:) size(scaleCloud, 1)) error(scaleIndex 超出云标度行号范围); end P zeros(n, 3); for j 1:n idx scaleIndex(:, j); P(j, 1) mean(scaleCloud(idx, 1)); % 期望聚合 P(j, 2) mean(scaleCloud(idx, 2)); % 熵聚合 P(j, 3) mean(scaleCloud(idx, 3)); % 超熵聚合 end base P(:, 1); base(base 1e-9) 1e-9; w (base / sum(base)); % 转成行向量方便后续加权 end调用示例可以放在main_demo.m里。假设 5 位专家对 4 个指标给评语评语行号 1 到 5 分别对应“极重要”到“不重要”scaleCloud [ 9.0 1.5 0.30; 7.0 1.2 0.25; 5.0 1.0 0.20; 3.0 0.8 0.15; 1.0 0.6 0.10 ]; scaleIndex [ 2 2 3 4; 2 3 3 3; 1 2 4 4; 2 2 3 3; 2 3 4 4 ]; [w, P] cloudWeightByScale(scaleIndex, scaleCloud); disp(权重 w ); disp(w); disp(指标云参数 P ); disp(P);这段代码的逻辑是“先聚合云参数再按期望归一化”。P(:,1)是每个指标的综合期望P(:,2)是专家分歧宽度P(:,3)是分歧的离散程度。权重只用 Ex 归一化En 和 He 不直接进分母这样权重尺度不会因为某个指标分歧大而被压扁。要注意w转成了行向量因为后续评价矩阵通常按行放权重。如果指标期望出现 0代码里用1e-9兜底避免除零。这个兜底只防报错不解决业务问题。某个指标 Ex 为 0说明专家普遍认为它不重要应该考虑剔除或合并而不是让它带着极小权重留在模型里。3.3 权重归一化与一致性检查权重算出来后先做三件事。第一确认sum(w)等于 1误差在1e-9以内第二看最大权重和最小权重的比值如果超过 8说明指标重要性拉得很开评价结果容易被头部指标主导第三看每个指标的P(:,2)./P(:,1)这个比值越大专家分歧越明显。我一般把En/Ex 0.35的指标单独列出来回到原始评语表看是谁打了极端值。云模型权重不是判断矩阵不需要算 CR但专家意见一致性还是要看。一个指标 5 位专家里 4 位选“很重要”、1 位选“不重要”聚合后的 En 会明显变大权重却只被 Ex 拉低一点这种指标在敏感性分析里最容易翻车。还有一点权重归一化后不要立刻写进报告。先跑一次“权重替换测试”把最大权重指标和最小权重指标互换看综合评价排序是否完全反转。如果反转太剧烈说明评价模型对权重过敏要么增加指标、要么把权重分段、要么在报告里明确权重来源和不确定性。云模型给了你 En 和 He不用它们做检查等于把黑匣子又关上了。4. 云模型综合评价把权重接进评价矩阵权重只是半成品最终要落到“某个对象在某个等级上有多大的隶属度”。云模型综合评价的常见流程是先定义等级云比如“差、中、良、优”各一组 Ex、En、He再对每个对象的每个指标实测值计算它对各等级云的隶属度最后用权重加权得到综合隶属度向量按最大隶属度或加权等级分判定结果。这里最容易出错的是“实测值尺度”和“等级云尺度”不一致。指标实测值归一化到 0 到 1等级云却按 0 到 100 设隶属度会全部趋近于 0。我一般要求所有输入先归一化等级云的 Ex 也统一到 0 到 1。如果业务上必须用原始量纲就把等级云 Ex 同步换成原始量纲不要混用。4.1 评价集云化与隶属度矩阵生成等级云可以按行业习惯设。下面这组四等级云只用于演示Ex 分别落在 0.2、0.45、0.70、0.90En 控制相邻等级重叠程度He 控制评价结果的随机抖动等级ExEnHe差0.200.060.010中0.450.070.012良0.700.070.012优0.900.050.008单点对云的隶属度严格说不是一次确定的函数值。工程上常用做法是生成 K 次云滴取该点隶属度的均值降低单次随机带来的抖动。cloudMembership.m可以这样写function mu cloudMembership(x, Ex, En, He, K) % cloudMembership 计算单点 x 对一组云参数的隶属度 % x: 标量实测值Ex/En/He: 等级云参数K: 随机实现次数 if nargin 5 K 200; end En abs(En); He abs(He); Enn randn(K, 1) .* He En; Enn(abs(Enn) 1e-6) 1e-6; mu mean(exp(-((x - Ex).^2) ./ (2 * Enn.^2))); endK越大隶属度越接近期望值但循环也越慢。做单对象评价时 K 取 200 到 500 都行做批量敏感性分析时K 取 100 就能看出趋势。Enn的截断和正向云保持一致避免极端随机数把隶属度拉到 1 或 0。这个函数每次调用都会消耗随机数批量跑之前记得rng固定种子否则同一组数据两次评价结果会有细小差异。4.2 综合得分与等级判定有了权重和隶属度矩阵综合评价函数可以写成下面这样。输入X是 1×n 的归一化实测值W是 1×n 权重levelCloud是 L×3 的等级云参数function [B, score, grade] cloudEval(X, W, levelCloud, K) % cloudEval 云模型综合评价 % X: 1 x n 实测值已归一化W: 1 x n 权重 % levelCloud: L x 3 等级云参数K: 隶属度随机实现次数 if nargin 4 K 200; end X X(:); W W(:); n numel(X); if numel(W) ~ n error(权重长度和指标数量不一致); end L size(levelCloud, 1); mu zeros(L, n); for l 1:L for j 1:n mu(l, j) cloudMembership(X(j), levelCloud(l,1), ... levelCloud(l,2), levelCloud(l,3), K); end end B W * mu; % 1 x L 综合隶属度 B B / sum(B); % 归一化防止数值误差 levelScore 1:L; % 等级序号 score sum(B .* levelScore) / sum(B); [~, grade] max(B); end这段代码里mu是 L×n 的隶属度矩阵W * mu把每个指标的隶属度按权重合成。B是综合隶属度向量score用等级序号加权只适合做相对排序不适合直接解释成物理分数。grade取最大隶属度对应等级如果B里两个等级很接近不要硬判应该看B的分布或者回到原始指标查。4.3 一个可跑通的模拟项目X用一个虚构的“模拟项目X”把链路串起来4 个指标权重来自上一章的cloudWeightByScale实测值归一化后是[0.62 0.74 0.58 0.81]等级云用 4.1 的表。调用代码levelCloud [ 0.20 0.06 0.010; 0.45 0.07 0.012; 0.70 0.07 0.012; 0.90 0.05 0.008 ]; X [0.62 0.74 0.58 0.81]; rng(2024); % 评价里也有随机实现固定种子便于复现 [B, score, grade] cloudEval(X, w, levelCloud, 300); fprintf(综合隶属度 B [%s]\n, num2str(B, %.4f )); fprintf(等级分 score %.4f判定等级 grade %d\n, score, grade);跑完后不要只看grade。先看B是不是某个等级明显占优如果四个等级都在 0.25 附近说明指标值和等级云没有形成有效区分要么等级云 En 太宽要么指标归一化尺度不对。再看score和grade是否一致如果grade是 3 但score靠近 2说明“良”和“中”的边界很模糊报告里要写清楚不确定性。模拟项目X的价值是验证链路不是给真实业务下结论。换数据时只要保持X是行向量、W是行向量、levelCloud是 L×3函数就不用改。真正要改的是等级云定义和权重来源这两块一变评价结果会跟着变所以每次换业务场景都要重跑云滴图和权重一致性检查。5. 避坑与排查云模型 MATLAB 代码最常见的五类翻车云模型代码短但参数之间互相牵制翻车往往不是语法错误而是“能跑但结果不可解释”。下面五类问题是我在 MATLAB 工程里踩过的典型场景每条按现象、原因、解决写方便你对着命令行输出排查。5.1 云滴全挤在期望附近En 和 He 的量纲没跟 Ex 对齐现象正向云滴图里云滴几乎叠在 Ex 一条竖线上横向铺开很窄评价时所有实测值对等级云的隶属度都差不多。原因通常不是forwardCloud写错而是 En 相对 Ex 太小。比如 Ex 设 0.7En 却设 0.005云滴宽度只有期望的不到 1%图看起来像一根针。另一种情况是 Ex 用 0 到 100 的量纲En 却按 0 到 1 设云滴宽度被量纲差吞掉。解决先统一量纲所有指标归一化到 0 到 1或者等级云 Ex 同步换成 0 到 100。然后按 Ex 的 1/6 到 1/3 估 En画图看覆盖范围。He 先取 En 的 0.1 到 0.3不要一上来给 0.5。云滴图至少要能看出中间密、两边疏如果还是太窄把 En 调大一档再试。每次只动一个参数否则图变好了也不知道是谁的功劳。5.2 逆向云算出的 He 为负样本方差小于 En 平方现象调用backwardCloud后命令行打出He 0或者你自己改的版本出现负数后续权重计算报错或权重全被拉平。原因是对同一指标的专家打分太集中var(x,1)很小而En^2相对更大s2 - En^2变成负数。样本量少、打分只有两三个档位时尤其常见。解决代码里用max(s2 - En^2, 0)截断先让流程跑通然后回头看样本。如果 n 小于 10增加专家数量或合并指标如果打分集中在两个极端检查评语定义是不是有歧义。He 被截成 0 不是坏事它说明这批样本没有额外的超熵信息但不要用这组样本去支撑很细的敏感性分析。连续三次出现 He 为 0我会直接把这组指标标成“专家意见高度一致”在报告里单独说明。5.3 权重和为 1 但评价结果反直觉只看 Ex 归一化忽略 En 分歧现象sum(w)正好等于 1权重表看起来也合理但综合评价把某个明显较差的指标判成了“良”。原因是权重只用 Ex 归一化某个指标 Ex 很高但 En 也很大说明专家虽然认为它重要但意见分歧很宽。加权时它仍然拿走最大权重把其他指标压下去了。解决把P(:,2)./P(:,1)打出来En/Ex 超过 0.35 的指标单独检查原始评语。如果分歧来自一两个极端打分考虑用中位数或截尾均值重算 Ex如果分歧是业务本身造成的不要硬压权重应该在评价结果里给出区间或做敏感性分析。云模型权重不是越确定越好En 大是信息不是噪声但你要在报告里把它讲清楚。5.4 随机种子不同结果差异大单次云滴评价没有做平均现象同一组X、W、levelCloud第一次跑grade 3第二次跑grade 2score也跳。原因是cloudMembership内部用了randn每次调用都重新采样K 又设得小单次评价的随机抖动被放大。云模型本身有随机性但工程评价不能每次刷新都换结论。解决批量评价前固定rng并把cloudMembership的 K 提高到 200 以上如果还跳跑 20 次取B的均值和标准差报告里写“综合隶属度均值±标准差”。我一般会把rng放在脚本最前面而不是函数内部这样调用顺序变化时还能复现。不要用固定种子掩盖参数问题如果 20 次里等级判定变了 5 次以上说明等级云重叠太大回去调 En。5.5 MATLAB 函数名报错文件名、路径和函数名不一致现象命令行报“未定义函数或变量 forwardCloud”或者which forwardCloud返回空。代码明明在当前文件夹双击也能打开。原因是 MATLAB 只认路径上的函数文件文件名必须和函数名一致forwardCloud.m里第一行必须是function ... forwardCloud(...)。脚本和函数混在同一个文件里也会让调用方找不到函数。解决把每个函数单独存成.m文件文件名和函数名完全一致在main_demo.m开头加addpath(genpath(pwd))或者把cloud_model文件夹设为当前文件夹。用which -all forwardCloud检查有没有同名文件冲突。MATLAB 版本差异一般不影响randn、var这些基础函数但如果你用了新版本才有的参数换到旧版本会报错最省事的做法是保持函数接口只用基础语法。6. 进阶用法权重敏感性分析与 cloudCheck 自检脚本权重敏感性分析不用写得很复杂核心是“给权重加一点扰动看评价结果动不动”。下面这段代码在基础权重上做 ±10% 随机扰动跑 200 次统计等级分和等级判定的波动rng(2024); baseW w; nRun 200; scores zeros(nRun, 1); grades zeros(nRun, 1); for k 1:nRun w2 baseW .* (1 (rand(size(baseW)) - 0.5) * 0.2); w2 w2 / sum(w2); [~, s, g] cloudEval(X, w2, levelCloud, 150); scores(k) s; grades(k) g; end fprintf(等级分均值 %.4f标准差 %.4f\n, mean(scores), std(scores)); fprintf(等级判定为 3 的比例 %.2f\n, mean(grades 3));这段代码里0.2是扰动幅度对应 ±10%nRun是重复次数cloudEval内部的 K 降到 150 是为了控制总耗时。看结果时重点看两个数等级分标准差是否超过 0.15以及主等级判定比例是否低于 0.8。超过这两个线说明权重或等级云至少有一个太敏感报告里不能只给一个确定等级。我现在的习惯是每次把云模型接进 MATLAB 工程都先跑一遍自检画一张正向云滴图确认 En 和 He 没有量纲错位打一张逆向云参数表确认 He 没有被频繁截成 0再跑 200 次权重扰动确认等级判定不会来回跳。这三步不花多少时间但能挡住大部分“代码能跑、结论不能看”的问题。自检项看什么处理习惯正向云滴图是否中间密、两边疏En 太窄就调大He 太厚就调小逆向云参数He 是否为 0、En/Ex 是否过大样本少就补样本分歧大就回查评语权重敏感性等级分标准差、主等级比例标准差大就缩权重扰动或重定等级云从那以后我每次换业务数据都强制走一遍cloudCheck这三步不跳过云滴图也不把rng藏在函数里。云模型不是算出一个权重就完事它把不确定性摆在你面前用不用、怎么解释还是工程判断。希望帮到你。本文还有配套的精品资源点击获取