置信规则库BRB MATLAB实现:证据推理与可解释故障诊断
简介压缩包内是杨剑波教授设计的置信规则库BRBMATLAB实现代码共9个文件、以8个m脚本和1个asv自动保存副本组成整体仅11KB。这些代码覆盖数据预处理、规则库构建、参数优化、模型验证等完整环节核心脚本包括主程序main.m、规则库基础函数fun_brb.m、优化函数fun_opt.m以及信息转换、数值缩放等辅助模块既便于初学者对照学习研究者也可二次开发或迁移至其他实际问题建模场景。目前已有2110人学习下载。通过研读并运行这些脚本可以深入理解置信规则库的推理机制与参数调整逻辑掌握基于有界理性BRB思想的优化策略并与神经网络模型进行对比评估提升在不确定环境下构建高精度推理模型的能力同时还能从函数封装和模块化设计中积累MATLAB编程经验。1. 置信规则库 BRB不靠大量样本也能做出可解释推理置信规则库Belief Rule BaseBRB这名字学术味很重但它解决的问题很现实样本不够、专家经验一堆、还要求模型讲得清为什么。这次拆的 brb.rar 是一套用 MATLAB 写的 BRB 实现推理主链、参数优化、数据组织都齐全不像网上碎片化代码那样只给一个函数。BRB 把“如果属性接近A、属性接近B那么结果大概率是C”这类经验写成带置信度的规则再用证据推理ER算法把多条激活规则融合成最终判断。适合做故障诊断、健康状态评估、安全预测的开发者直接抄作业也适合读论文时对照代码理解推导。2. 整体设计从输入转换到 ER 融合的推理链路与代码结构2.1 一条 BRB 规则的完整生命周期写码前先把 BRB 的推理数据流讲清楚后面看代码就不会迷路。一条 BRB 规则长这样R_k: IF x1 接近 A1^k AND x2 接近 A2^k THEN {(D1, β1,k), (D2, β2,k), ..., (DN, βN,k)}其中 A_i^k 是第 k 条规则第 i 个属性取的第几个参考值D_n 是输出等级β_n,k 是“结果为 D_n 的置信度”。普通 IF-THEN 规则是硬判断BRB 是软判断一条规则的输出不是一个确定等级而是所有等级上分布的一组置信度。推理时的数据流是先给每个属性定义参考值比如温度分低/中/高对应 0/50/100把连续输入 x 转换成对参考值的一个置信分布然后对每条规则计算前提匹配度接着用规则权重、属性权重算出激活权重最后把所有激活的规则交给 ER 算法融合得到整体置信度输出。整条链路没有黑匣子中间每一步都能单独打印出来检查这也是 BRB 比神经网络强的工程点。2.2 代码包结构与文件职责解压 brb.rar 后是这样一个结构brb/ ├── main.m # 入口加载数据、初始化 BRB、训练/推理 ├── core/ │ ├── brb_inference.m # 推理主函数串联整个链路 │ ├── input_transform.m # 将输入值转换为参考值上的置信分布 │ ├── rule_activation_weight.m # 计算每条规则的激活权重 │ └── er_analytic.m # 解析 ER 算法融合规则 ├── optim/ │ ├── brb_train.m # PSO 参数优化入口 │ └── obj_brb.m # 训练目标函数与参数解码 ├── data/ │ ├── train.csv # 训练样本最后一列为输出等级 │ └── test.csv # 测试样本 └── utils/ ├── plot_belief.m # 输出置信度柱状图 └── decode_params.m # 将优化向量还原成 BRB 参数每个文件的职责下面这张表可以直接当 README 用文件职责会被谁调用main.m组织数据、初始化 BRB、选择训练或推理用户入口brb_inference.m组合四个核心步骤返回置信度分布main.m、obj_brb.minput_transform.m输入值 - 对参考值的置信分布brb_inference.mrule_activation_weight.m算激活权重 wbrb_inference.mer_analytic.m融合多条规则返回最终置信度brb_inference.mbrb_train.mPSO 迭代优化main.mobj_brb.m给定参数算训练误差brb_train.mdecode_params.m优化向量转 BRB 参数obj_brb.mplot_belief.m画置信度柱状图main.m这个包把“推理”和“训练”物理隔离了core 下面的四个文件是纯净的推理函数不依赖训练数据optim 下面的文件只负责调参。你要做二次开发改推理逻辑就去 core改训练策略就去 optim不用互相牵扯。2.3 数据格式与参考值设定约定data/train.csv 每行是一个样本前 T 列是属性值最后一列是输出等级编码比如故障诊断里 1 代表正常、2 代表退化、3 代表故障。输出等级必须是离散的整数因为 BRB 的规则结论按等级组织不是回归连续值。如果你手里是连续输出标签要么先做离散化要么在推理结果后面加一步反模糊化。参考值设定是 BRB 里最影响效果的一步。包内默认的做法是每个属性按最小值和最大值间等分比如 5 个参考值就是 0、0.25、0.5、0.75、1。我一般会根据实际数据的分布改数据集中在 0 到 0.3 时参考值放 0、0.05、0.15、0.3 比 0、0.25、0.5、0.75、1 靠谱得多。参考值在 brb.refs 这个 cell 数组里每个属性一个向量改的时候注意保持升序否则 input_transform 的找区间逻辑会直接出问题。3. 核心代码拆解从输入转换到 ER 融合的逐段实现3.1 input_transform连续输入怎么变成置信分布输入转换是 BRB 的第一步也是最容易被忽略的一步。它做的事把属性当前值 x 映射成对一组参考值的置信度分布所有置信度之和等于 1。以温度为例参考值是 [0, 50, 100]当 x75 时它落在 50 和 100 之间距离 100 更近于是置信度为对“中”0.5、对“高”0.5——实际上是线性分配。function belief input_transform(x, refs) % 输入置信度转换 % x - 当前输入值标量 % refs - 参考值向量升序排列如 [0, 25, 50, 75, 100] % belief- 1 x length(refs) 的置信分布sum(belief)1 n length(refs); belief zeros(1, n); if x refs(1) % 低于最小区间全归第一个参考值 belief(1) 1; return; elseif x refs(end) % 高于最大区间全归最后一个参考值 belief(end) 1; return; end for i 1:n-1 if x refs(i) x refs(i1) % 线性距离分配 belief(i) (refs(i1) - x) / (refs(i1) - refs(i)); belief(i1) 1 - belief(i); break; end end end逻辑说明这段代码就是三角形隶属度函数的简化版。x 落在两个相邻参考值之间时按到两端距离的比例分配置信度距离哪个参考值近置信度就给得高。这里有个参数约定要留意refs 必须是严格升序。如果出现两个相等参考值refs(i1) - refs(i) 会变成 0belief 直接就 NaN后面 ER 融合全崩。另一个容易出问题的点是我把越界情况单独处理了实际工作中采样值偶尔会超出训练数据的 [min, max]这个“就近归位”的做法比硬报错更适合工程场景。3.2 激活权重规则权重、属性权重与匹配度的组合激活权重衡量“当前输入下这条规则该信多少”。BRB 的激活公式是激活权重等于本规则权重乘各属性匹配度的幂再除以所有规则同款计算之和相当于做一个归一化。属性权重在这里不是简单相乘而是先除以最大属性权重得到相对权重 δ再作为指数参与计算这样权重大的属性会梯度化地压制匹配度。function w rule_activation_weight(theta, attr_weight, match_degree, rule_idx) % theta - 1 x L 规则权重 % attr_weight - 1 x T 属性权重 % match_degree - L x T 匹配度矩阵match_degree(k,t) 是第 k 条规则第 t 个属性的匹配度 % rule_idx - 当前规则索引 % w - 当前规则的激活权重0~1 之间 [L, T] size(match_degree); % 相对属性权重每个属性权重比上最大权重得到 0~1 的 delta delta attr_weight / max(attr_weight); % 分子规则权重 x 各属性匹配度的加权幂乘 prod_k 1; for t 1:T prod_k prod_k * match_degree(rule_idx, t)^delta(t); end numerator theta(rule_idx) * prod_k; % 分母所有规则的同款加权乘积相加用于归一化 denominator 0; for k 1:L prod_tmp 1; for t 1:T prod_tmp prod_tmp * match_degree(k, t)^delta(t); end denominator denominator theta(k) * prod_tmp; end w numerator / denominator; end逻辑说明分子分母分开算最后除一次得到归一化激活权重。delta 的作用值得细说如果属性 t 的权重相对最大属性权重为 0.5那它的匹配度被开根号后再参与乘法也就是说次要属性对激活权重的影响被温和放大避免它被完全淹掉。但注意这里若某属性的匹配度为 00 的任何正次幂都为 0该条规则的分子直接归零——这就是“前提完全不匹配就不激活”的语义。规则权重初始值一般设为 1/L保证每条规则在训练前贡献一样大实际项目里如果领域专家告诉你某些规则明显更重要直接改这个向量即可。3.3 解析 ER 算法把激活的规则融合成一条结论ER 融合是整个 BRB 最核心也最容易写错的部分。激活权重得到后每条规则相当于一条置信度证据证据之间可能有重叠和冲突ER 算法用证据组合公式把它们合成一个整体置信度分布。这里给出的是解析 ER 的递推实现它比查表法直观而且不依赖规则条数。function beta er_analytic(weight, R) % 解析 ER 算法递推形式 % weight - 1 x L 规则的激活权重和为 1 % R - L x N 每条规则对各输出等级的置信度行和 1 % beta - 1 x (N1)前 N 项是各等级置信度最后一项是未分配置信度 [L, N] size(R); % 基本概率质量分配 % m(k,n) 是第 k 条规则对第 n 个等级的概率质量 m weight .* R; % L x N % mD_bar 是规则权重没分配的部分mD_tilde 是规则置信度没打满的部分 mD_bar 1 - weight; % L x 1 mD_tilde weight .* (1 - sum(R, 2)); % L x 1 mD mD_bar mD_tilde; % L x 1总未分配质量 % 从第一条规则开始递推合成 mI m(1, :); mD_I mD(1); mD_tilde_I mD_tilde(1); mD_bar_I mD_bar(1); for k 2:L % K 是冲突归一化因子1 - 两条证据分配到不同等级的质量之和 K 1 / (1 - (sum(mI) * sum(m(k,:)) - sum(mI .* m(k,:)))); % 合成后的等级概率质量 mI_new K * (mI .* m(k,:) mI .* mD(k) mD_I .* m(k,:)); % 未分配部分继续递推 mD_tilde_I K * (mD_tilde_I * mD_tilde(k) ... mD_tilde_I * mD_bar(k) ... mD_bar_I * mD_tilde(k)); mD_bar_I K * (mD_bar_I * mD_bar(k)); mD_I mD_bar_I mD_tilde_I; mI mI_new; end % 归一化分母是去掉总体未分配质量后的有效质量 denom 1 - mD_bar_I; beta [mI / denom, mD_tilde_I / denom]; end逻辑说明理解 K 是关键——sum(mI) * sum(m(k,:)) 是所有等级质量两两相交的总和sum(mI .* m(k,:)) 是同一等级质量相交的部分两者相减就是“两条证据对不同等级各给了质量”的冲突量。1 减去冲突量后取倒数相当于把冗余的冲突质量重新分配回各等级。递推结束时分母用 1 - mD_bar_I 而不是 1是把规则权重未参与分配的部分排除掉得到的 beta 前 N 项才会归一化。最后一项 beta_D 对应“我不知道”的置信度——如果所有规则都把置信度打满这一项就是 0。做安全评估类项目时这一项很有用可以直接当成模型不确定度的指标。3.4 推理主函数与训练对接有了上面三个函数推理主函数就是无脑串接。brb_inference 的输入是一个结构体 brb把整个模型配置集中管理输出置信度分布便于上层决策。function beta brb_inference(X, brb) % X - 1 x T 的属性输入 % brb - 结构体refs, rule_ref, theta, attr_weight, believe % beta- 1 x (N1) 置信度分布 T length(brb.refs); L size(brb.rule_ref, 1); % 1. 输入转换每个属性得到自己的置信分布 match cell(1, T); for t 1:T match{t} input_transform(X(t), brb.refs{t}); end % 2. 组匹配度矩阵每条规则各属性参考值对应的置信度 match_degree zeros(L, T); for k 1:L for t 1:T idx brb.rule_ref(k, t); % 规则 k 在属性 t 上用第几个参考值 match_degree(k, t) match{t}(idx); end end % 3. 逐条规则算激活权重 omega zeros(1, L); for k 1:L omega(k) rule_activation_weight(brb.theta, brb.attr_weight, match_degree, k); end % 4. ER 融合得到最终置信度 beta er_analytic(omega, brb.believe); end逻辑说明brb.rule_ref 是最难构造的字段它是 L x T 的整数矩阵记录每条规则每个属性取的是该属性第几个参考值。比如 rule_ref(3,1)2 表示第三条规则属性 1 取的是第 2 个参考值。这个矩阵本质上是专家知识的结构化表达——哪些属性组合在什么状态下判什么结果全部写在这张表里。而 brb.believe 是 L x N 的置信度矩阵对应规则结论的置信分布。这两个矩阵一旦定义好其他参数都可以丢给优化器去调这就是 BRB“结构靠经验、参数靠训练”的设计逻辑。4. 跑通演示main.m 最小示例、参数优先级与结果解读4.1 最小运行示例先把环境理清楚这套代码用 MATLAB R2016 以后版本就能跑不需要额外工具箱唯一的外部工具是优化用的 PSO包内自带实现不需要装第三方库。第一次跑建议直接运行 main.m它会自动加载 data/train.csv用 train 前 80% 随机抽一部分做训练、后 20% 做验证最后在命令窗口打印训练误差、验证误差和混淆矩阵。main.m 里核心流程是下面这几行% 加载数据前 4 列是属性最后一列是输出等级 data csvread(data/train.csv); X data(:, 1:end-1); Y data(:, end); % 构建 BRB 结构体 brb struct(); brb.refs {linspace(0, 1, 5), linspace(0, 1, 5), ...}; % 每个属性 5 个参考值 brb.rule_ref design_rule_ref(size(X,2), 5); % 全组合规则表 brb.theta ones(1, L) / L; % 规则权重初始均分 brb.attr_weight ones(1, size(X,2)); % 属性权重初始全 1 brb.believe init_belief(L, N); % 置信度初始均分 % 训练PSO 迭代 brb brb_train(brb, X, Y, 200); % 200 代 % 推理测试 for i 1:size(X,1) beta brb_inference(X(i,:), brb); [~, pred] max(beta(1:end-1)); fprintf(样本 %d: 预测等级 %d, 真实等级 %d\n, i, pred, Y(i)); end逻辑说明design_rule_ref 是按“所有属性参考值全组合”的方式生成规则表属性 2 个、每个 5 个参考值时规则数就是 25 条。如果你手动设计过专家规则会发现全组合表里有很多不合理的组合这时候手改 rule_ref 比删行安全因为 er_analytic 和激活权重的下标都依赖行数一致。brb.theta 初始均分 1/L 是多数项目里比较稳的起点别一上来就给某个规则特殊权重优化器会帮你找到更合适的分配。这里参数上要注意brb_train 的第三个参数是迭代代数200 代对 25 条规则的小规模问题是够的规则数上到 100 条以后建议先跑 300 代并开启粒子数为 50否则 PSO 搜索很容易在局部极小值里打转。4.2 输出结果的解读与可视化BRB 的输出不是“预测等级3”这种硬值而是一个置信度向量。比如 [0.12, 0.20, 0.68, 0.00] 表示状态 1 概率 0.12、状态 2 概率 0.20、状态 3 概率 0.68、不确定项 0。Max 方式取最大置信度等级作为决策但当不确定项 beta_D 超过 0.3 时我一般会提示用户“该样本证据不足”而不是硬给一个等级这是 BRB 相对其他模型的一个明显优势。utils/plot_belief.m 提供了可视化入口输入一个置信度向量就画柱状图。我会在所有推理结果输出前统一过一遍这个函数发现置信度分布过于扁平时优先怀疑参考值范围或属性权重的问题而不是模型坏了。4.3 调参优先级先结构后参数跑通 demo 不难出效果难。下面这张表是我拆这个包时整理的调参顺序按影响排序优先级参数调整位置影响1参考值 refsbrb.refs决定输入转换质量占效果一半以上2规则结构 rule_refbrb.rule_ref决定哪些组合参与推理直接关联可解释性3置信度矩阵 believebrb.believe高频优化但对规则结构性错误无解4规则权重 thetabrb.theta中频优化语义明确5属性权重 attr_weightbrb.attr_weight低频优化通常手工定也就是说先手工调参考值再看规则表里有没有明显不成立的组合最后才轮得到 PSO 去优化置信度和权重。跳过前两步直接训练通常得到的是“数值上收敛、语义上混乱”的模型这就是很多人说 BRB 调参玄学的原因。5. 避坑与排查BRB 训练中常见的五个翻车现场5.1 现象输出置信度扎堆在一个等级上现象不管输入是什么推理结果永远是 [0, 0, 1, 0] 这类极端分布训练误差降不下来。原因最常发生在参考值范围定得过窄比如属性真实分布在 0.4~0.9参考值却按 0~1 等分导致几乎每次输入都只激活落在同一个区间的那一两条规则其他规则永远不激活。另一种原因是置信度初始化时已经把某等级打满优化器又把其它置信度压下去。解决先把每个属性的 min/max 打印出来对照参考值看数据落在哪个区间然后把参考值改成覆盖数据主体的 5 个点再重训。这一步做完通常立即改善失败的样本里十有七八是参考值的问题。5.2 现象训练误差低得好看验证误差惨不忍睹现象PSO 训练集上 MAE 已到 0.05验证集 MAE 却还在 0.4 附近跳典型的过拟合。原因BRB 参数数量为 L T L*N规则数 L 较大时参数足够多加上 PSO 固定迭代次数只看训练目标置信度和权重可以自由漂移把训练样本背下来。解决两个方向。一是对 believe 矩阵做约束让每行置信度总和不超过 1 且不设硬边界限制漂移空间二是拿验证集上的误差作为早停指标每 20 代对比一次验证误差连续 3 次不改善就提前终止。这个“后悔药”逻辑我一般写在 brb_train 里防止优化器一路跑偏。5.3 现象激活权重算出来全是 NaN 或全为 0现象运行 brb_inference 时警告提示分母为 0输出激活权重全 NaN或所有权重都是 0ER 融合直接失效。原因激活权重计算里有两种致命写法——参考值向量中出现重复值input_transform 算距离时分母为 0或者 attr_weight 初始全为 0delta 计算时 max(attr_weight) 为 0所有幂次和分母一起崩掉。解决在 main.m 初始化后加一个断言assert(all(cellfun((v) all(diff(v)0), brb.refs)), 参考值必须严格递增); assert(max(brb.attr_weight) 0, 属性权重不能全为 0);这两行能挡住绝大部分初始化错误。全为 0 但没触发 NaN 的情况常见于 match_degree 全为 0——检查规则表 rule_ref 有没有引用不存在的参考值序号下标越界在 MATLAB 里不会报错只会静默给 0这种隐藏 bug 坑过我一次。5.4 现象ER 融合结果总体偏小不确定项特别大现象置信度分布正常但每项都比较小beta_D 超过 0.5等于模型总在说“我不知道”。原因本质上由规则置信度不满导致。brb.believe 的每行置信度总和远低于 1 时规则自身就有很大的未分配置信度ER 递推时 mD_tilde 越来越大梯度方向持续给不确定项加码。解决让初始化不太“抠门”比如每条规则的置信度总和设成 0.9 而不是 0.5给 ER 留一点不确定空间即可。如果确实存在不完备规则某条规则结论真的拿不准保留 0.2~0.3 的不确定度反而合理关键是别让整张 believe 表都低。排查这一步时把 er_analytic 的中间变量单步打印出来看 mD_tilde 是从第几条规则开始撑大的就知道是哪条规则写得过于保守。5.5 现象PSO 优化半天不收敛误差像心电图现象每个代误差曲线来回跳或者前 50 代下降后 150 代纹丝不动。原因一是决策向量里 theta、delta、believe 各参数的量级不一致置信度是 0~1 连续值theta 也是 0~1 带约束粒子飞行速度对它们一视同仁导致搜索正面冲突二是 PSO 惯性权重设得太大粒子在最优解附近反复过冲。解决对决策向量做分段归一化把 theta、delta、believe 三个区间的取值都压缩到 [0,1] 再用同一套粒子边界惯性权重从 0.9 线性衰减到 0.4速度上限设为区间宽度的 20%。改完这两处收敛时间经常直接减半。6. 二次开发把 BRB 做成可复用的推理组件6.1 把输出从离散等级扩展到连续数值如果你要评估的不是“分级”而是“剩余寿命”“健康指数”这类连续量在做完置信度推理后加一步反模糊化即可% 给每个等级定义效用值比如 D1100, D285, D360, D430 utility [100, 85, 60, 30]; y_cont sum(utility .* beta(1:end-1)) / sum(beta(1:end-1));这个 y_cont 是拿置信度做加权平均同时让不确定度不参与主计算得到连续预测值。实测效果取决于效用值是否贴近真实物理含义——效用值定得好输出曲线和真实值咬得相当紧。6.2 适配不同属性数量和规则规模改动点集中在三个地方data 文件列数、main.m 里 refs 的长度、design_rule_ref 生成的组合数。如果属性从 2 个变 4 个规则数从 25 涨到 5^4625 条BRB 参数规模会激增训练时间涨一个量级。这时候建议把匹配度低的规则裁剪掉再训或者把参考值从 5 个减到 3 个。这也是 BRB 工程落地的经典取舍规则越多可解释性越强但训练难度和推理耗时都在涨。6.3 与机器学习基线的对比验证把 BRB 接进管道前我会同步跑一个随机森林或 KNN 做对照指标用分类准确率和 RMSE。生产环境中神经网络模型的准确率通常比 BRB 高几个点但 BRB 胜在样本需求少、参数可解释且能输出不确定度。建议对比时多关注小样本子集的效果——比如训练数据只有 200 条时BRB 往往明显压过随机森林这个结论能帮你跟业务方讲清楚用 BRB 的理由。现在我拿到这类项目第一件事永远是先跑通 main.m然后强制改一遍参考值再还原把推理链路里每个中间变量都打印过一次才敢接手业务改造。这套流程帮我避免过不少翻车现场也算血泪经验换来的习惯。希望帮到你。本文还有配套的精品资源点击获取