简介:模式识别课程的Bayes分类器设计实验报告,面向需要完成同类实验或理解贝叶斯决策理论的学生。报告围绕最小错误率与最小风险两种贝叶斯分类器展开,完整给出了实验原理、后验概率与条件风险的计算公式、基于MATLAB的实现代码、后验概率与分类结果示意图,以及两种决策方式的对比分析。内容覆盖正常与异常两类细胞识别场景,先验概率分别设为0.9和0.1,类条件概率服从N(-2,0.25)与N(2,4),通过24个观察值演示完整分类流程。资源为1个doc文档,大小173KB,文字、公式与代码相互对照,便于直接参考仿写或用于实验报告撰写。目前已有934人学习下载,适合模式识别初学者快速掌握Bayes分类器设计的关键步骤与编程实现。
1. 贝叶斯分类器实验:从后验概率到风险决策的完整推导
做模式识别的实验,最容易被忽视的就是“先验概率”这三个字。这份实验报告的第一部分给出了一个非常经典的细胞识别场景:正常细胞先验概率0.9、异常细胞0.1,类条件概率分别服从 N(-2, 0.25) 和 N(2, 4)。如果只看似然函数,-3.9 附近的样本点明显更靠近正常类的分布中心,但加上先验之后,后验概率的形态会发生偏移,甚至反转。这正是贝叶斯决策与直觉判断的分水岭:它不直接比较似然,而是比较融合了先验和损失的后验风险。本实验从最小错误率贝叶斯分类器入手,再引入最小风险决策,最后叠加 Fisher 线性判别,适合刚接触模式识别的读者理清决策理论的主线,也适合考研或复试前快速回顾贝叶斯框架的完整链路。
2. 贝叶斯决策的理论骨架:先验、似然与后验的三角关系
2.1 为什么最小错误率准则等价于最大后验概率
贝叶斯决策的核心不是“猜”,而是“在已知信息下做最优选择”。假设有两类 ω1(正常)和 ω2(异常),先验概率 P(ω1)=0.9、P(ω2)=0.1,类条件概率密度 p(x|ω1) 和 p(x|ω2) 已知。对于观测值 x,后验概率由贝叶斯公式给出:
P(ωi|x) = p(x|ωi) · P(ωi) / Σ(p(x|ωj) · P(ωj))
如果目标是最小化错误率,那么决策规则就是比较 P(ω1|x) 和 P(ω2|x),哪边大就判哪边。之所以这个规则能最小化错误率,是因为对任意样本 x,判错的概率就是 1 - max(P(ω1|x), P(ω2|x)),选择后验最大的类别等价于对该样本取最小错误概率。整体错误率是对所有 x 的积分,逐点最优自然全局最优。
实验中正常类方差只有 0.25,分布非常集中;异常类方差为 4,分布平坦。仅凭这两条曲线去分类,边界大概在两类概率密度相等的位置。但先验 0.9 对 0.1 的悬殊差距会把边界向异常类方向推,直观上看就是“宁可把可疑样本判成正常,因为正常类本就占绝大多数”。这就是贝叶斯决策相对于最大似然分类的本质差异。
2.2 0-1 损失函数如何退化为最小错误率
最小风险贝叶斯决策是更一般的框架,损失函数 λ(αi|ωj) 表示真实类别为 ωj 时采取决策 αi 所付出的代价。当损失函数取如下形式:
- λ(α1|ω1)=0,λ(α1|ω2)=1
- λ(α2|ω1)=1,λ(α2|ω2)=0
即“判对不损失,判错损失为 1”,此时条件风险 R(αi|x) 等于该决策的错误概率。对每个样本选择条件风险最小的决策,恰好等价于选择后验概率最大的类别。因此,最小错误率贝叶斯决策是 0-1 损失下的最小风险贝叶斯决策,它是后者的特例,而非并列的另一种方法。
2.3 实验数据的分布假设与参数设定
实验中的类条件概率被假设为正态分布 N(-2, 0.25) 和 N(2, 4)。这里有个容易被忽略的细节:MATLAB 的normpdf(x, mu, sigma)第三个参数是标准差 σ 而不是方差 σ²。因此:
| 类别 | 均值 μ | 标准差 σ | 方差 σ² |
|---|---|---|---|
| 正常 ω1 | -2 | 0.5 | 0.25 |
| 异常 ω2 | 2 | 2 | 4 |
如果直接把“0.25”当作第三个参数传入normpdf,整条后验概率曲线都会变形,分类边界也会跟着偏移。这个参数陷阱在实际工程中同样常见,尤其是从论文公式转换为代码时,方差与标准差的混淆是高频 bug。
3. 最小错误率贝叶斯分类器的 MATLAB 实现与验证
3.1 主程序:后验概率计算与判决逻辑
实验给出的完整实现可以分为三个层次:先构建后验概率计算的核心逻辑,再对未知样本做判决,最后画图可视化。下面把代码按可复用的方式整理,保留原始实验的结构,补充注释和模块化思路。
% 最小错误率贝叶斯分类器 % 参数设置 x = [-3.9847, -3.5549, -1.2401, -0.9780, -0.7932, -2.8531, ... -2.7605, -3.7287, -3.5414, -2.2692, -3.4549, -3.0752, ... -3.9934, 2.8792, -0.9780, 0.7932, 1.1882, 3.0682, ... -1.5799, -1.4885, -0.7431, -0.4221, -1.1186, 4.2532]; pw1 = 0.9; % 正常类先验概率 pw2 = 0.1; % 异常类先验概率 % 正态分布参数: 均值 e, 标准差 a e1 = -2; a1 = 0.5; % 正常类 N(-2, 0.25) e2 = 2; a2 = 2; % 异常类 N(2, 4) m = numel(x); % 待测样本个数 pw1_x = zeros(1, m); % 存放各样本属于正常类的后验概率 pw2_x = zeros(1, m); % 存放各样本属于异常类的后验概率 result = zeros(1, m); % 判决结果: 0 正常, 1 异常 for i = 1:m % 分别计算似然 l1 = normpdf(x(i), e1, a1); l2 = normpdf(x(i), e2, a2); % 贝叶斯公式计算后验概率 pw1_x(i) = pw1 * l1 / (pw1 * l1 + pw2 * l2); pw2_x(i) = pw2 * l2 / (pw1 * l1 + pw2 * l2); % 最小错误率判决: 比较后验概率 if pw1_x(i) > pw2_x(i) result(i) = 0; % 判为正常 else result(i) = 1; % 判为异常 end end % 输出判决结果 disp('最小错误率贝叶斯判决结果:'); disp(result);这段代码中normpdf是 MATLAB 自带的正态概率密度函数,传入均值和标准差。后验概率的分母对两类是相同的,所以理论上可以直接比较分子pw * normpdf(...),但保留分母更直观,也方便调试时检查概率是否归一化。判决阈值是 0.5 的后验概率,因为二分类问题中P(ω1|x) > P(ω2|x)等价于P(ω1|x) > 0.5。
3.2 后验概率曲线的绘制与样本标注
画图部分的核心是生成一组连续的自变量[-5:0.05:5],计算每个点上的后验概率并绘制两条曲线,同时在曲线下方标注每个样本的判决结果。
% 生成绘图用的连续样本点 a = -5:0.05:5; n = numel(a); pw1_plot = zeros(1, n); pw2_plot = zeros(1, n); for j = 1:n l1 = normpdf(a(j), e1, a1); l2 = normpdf(a(j), e2, a2); pw1_plot(j) = pw1 * l1 / (pw1 * l1 + pw2 * l2); pw2_plot(j) = pw2 * l2 / (pw1 * l1 + pw2 * l2); end % 绘图: 后验概率曲线 + 样本标记 figure(1); hold on; plot(a, pw1_plot, 'b-', 'LineWidth', 1.5); % 正常类后验概率 plot(a, pw2_plot, 'r--', 'LineWidth', 1.5); % 异常类后验概率 for k = 1:m if result(k) == 0 plot(x(k), -0.1, 'b*', 'MarkerSize', 8); % 正常细胞用星号 else plot(x(k), -0.1, 'rp', 'MarkerSize', 8); % 异常细胞用五角星 end end legend('P(\omega_1|x)', 'P(\omega_2|x)', '正常细胞', '异常细胞', 'Location', 'Best'); xlabel('样本细胞的观察值'); ylabel('后验概率'); title('最小错误率贝叶斯判决: 后验概率分布曲线'); grid on; hold off;画图时把样本点画在 y=-0.1 的位置,不影响后验概率曲线的显示范围,又能直观看出每个样本被分到了哪一侧。图中两条后验概率曲线的交点就是决策边界,边界左侧判正常、右侧判异常。由于正常类先验高且方差小,曲线在 -2 附近非常尖,后验概率迅速逼近 1,而异常类曲线相对平坦。
3.3 实验结果解读与分类结果分析
本实验数据下,分类结果应当为:
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 0 0 0 1 0 1前 13 个样本全部为负值且靠近 -3 附近,被正确判为正常细胞。第 14 个样本 2.8792 远离正常类分布中心,被判为异常。但注意 -3.9934 和 -3.9847 这两个样本,它们的观察值在 -4 附近,距离正常类中心 -2 约 4 个标准差,似然值非常低,不过由于异常类在该区域的似然更低,加上 0.9 的先验权重,最终后验概率仍是正常类占优。
这个结论在最小错误率框架下是正确的,但也是很多初学者觉得“反直觉”的地方:一个明显偏离正常类均值的样本,为什么还会被判成正常?答案在风险不对称:异常类先验只有 0.1,其分布在 -4 附近的概率密度极低,两者相乘后仍然小于正常类。这说明贝叶斯决策对“极端样本”的处理依赖于完整的概率模型,而不是简单的距离判断。
4. 最小风险贝叶斯决策:当损失不对称时
4.1 风险矩阵的工程含义与设定
最小错误率准则假设所有错误代价相同,但真实场景中往往不是这样。在细胞识别中,把异常细胞漏判为正常(假阴性)可能导致病情延误,风险远高于把正常细胞误判为异常(假阳性)。这份实验的风险决策表如下:
| 决策 \ 真实状态 | 正常 ω1 | 异常 ω2 |
|---|---|---|
| 判为正常 α1 | 0 | 2 |
| 判为异常 α2 | 4 | 0 |
其中行代表决策,列代表真实状态。λ(α1|ω2)=2 表示把异常细胞误判为正常的损失是 2;λ(α2|ω1)=4 表示把正常细胞误判为异常的损失是 4。注意:实验设定“误判正常为异常”的代价反而更高,这在教学场景中是刻意构造的对比,用来展示风险矩阵如何改变决策边界。
条件风险计算公式对二分类问题可以写成:
R(α1|x) = λ(α1|ω1) · P(ω1|x) + λ(α1|ω2) · P(ω2|x)
R(α2|x) = λ(α2|ω1) · P(ω1|x) + λ(α2|ω2) · P(ω2|x)
当 R(α1|x) < R(α2|x) 时判为正常,反之判为异常。由于 λ(α1|ω1)=λ(α2|ω2)=0,风险表达式可以化简为:
R(α1|x) = 2 · P(ω2|x)
R(α2|x) = 4 · P(ω1|x)
判决条件 R(α1|x) < R(α2|x) 等价于 P(ω2|x) < 2 · P(ω1|x)。这意味着异常类的后验概率需要达到正常类的两倍,才会被判决为异常。相比最小错误率决策的阈值 0.5,风险决策相当于把判决阈值抬高到了约 2/3。
4.2 最小风险分类器的 MATLAB 程序与曲线绘制
% 最小风险贝叶斯分类器 function [R1_x, R2_x, result] = danger(x, pw1, pw2) % 输入: % x - 待测样本向量 % pw1 - 正常类先验概率 % pw2 - 异常类先验概率 % 输出: % R1_x - 判为正常细胞的条件风险 % R2_x - 判为异常细胞的条件风险 % result- 判决结果: 0 正常, 1 异常 m = numel(x); R1_x = zeros(1, m); R2_x = zeros(1, m); result = zeros(1, m); % 分布参数 e1 = -2; a1 = 0.5; e2 = 2; a2 = 2; % 风险决策表 r11 = 0; % 正常判正常, 损失 0 r12 = 2; % 异常判正常, 损失 2 r21 = 4; % 正常判异常, 损失 4 r22 = 0; % 异常判异常, 损失 0 for i = 1:m % 计算后验概率 l1 = normpdf(x(i), e1, a1); l2 = normpdf(x(i), e2, a2); denom = pw1 * l1 + pw2 * l2; p1 = pw1 * l1 / denom; p2 = pw2 * l2 / denom; % 计算条件风险 R1_x(i) = r11 * p1 + r12 * p2; R2_x(i) = r21 * p1 + r22 * p2; % 最小风险判决 if R1_x(i) < R2_x(i) result(i) = 0; % 判为正常细胞 else result(i) = 1; % 判为异常细胞 end end end这个函数的设计亮点在于把“后验概率计算”和“风险累积”解耦。后验概率是数据驱动部分,风险矩阵是业务驱动部分。替换风险矩阵时不需要动概率计算的代码,工程上便于维护。调用时传入数据和先验即可:
% 调用最小风险贝叶斯分类器 x = [-3.9847, -3.5549, -1.2401, -0.9780, -0.7932, -2.8531, ... -2.7605, -3.7287, -3.5414, -2.2692, -3.4549, -3.0752, ... -3.9934, 2.8792, -0.9780, 0.7932, 1.1882, 3.0682, ... -1.5799, -1.4885, -0.7431, -0.4221, -1.1186, 4.2532]; pw1 = 0.9; pw2 = 0.1; [R1_x, R2_x, result] = danger(x, pw1, pw2); disp('最小风险贝叶斯判决结果:'); disp(result);4.3 两种判决的差异来源:阈值偏移与样本翻转
同一批样本,最小错误率判决结果为 13 个正常、11 个异常,最小风险判决结果为 15 个正常、9 个异常。具体来看,-3.9934 和 -3.9847 两个样本发生了翻转,从“正常”变为“异常”。这个翻转的根源在于这两个样本点的后验概率差距极小,处于决策边界附近的敏感区域。
把判决条件改写为风险比较的形式更容易看出端倪:
- 最小错误率判决条件:P(ω1|x) > P(ω2|x),即后验比值大于 1
- 最小风险判决条件:P(ω2|x) < (r21 - r11) / (r12 - r22) · P(ω1|x) = 2 · P(ω1|x)
风险决策相当于在似然比上乘了一个阈值因子。当 r21=4、r12=2 时,阈值因子是 2,意味着异常类后验需要超过正常类后验的两倍才会被判为异常。这就是为什么某些样本在最小错误率下被归为正常,在最小风险下却被翻转。
实际工程中选择风险矩阵时,一般会从业务损失出发估算误报和漏报的成本,再反推决策阈值。比如在工业质检中,漏检导致的客户投诉成本可能远大于误检导致的返工成本,这时风险矩阵中的 r21(正常判异常)可以设小、r12(异常判正常)设大,分类器自然倾向多报异常。风险矩阵的本质是把决策调整到业务最关心的错误类型上。
5. 从贝叶斯到 Fisher:线性判别函数的另一种路径
5.1 Fisher 准则的数学动机与与贝叶斯的联系
贝叶斯分类器需要知道类条件概率密度,这在低维且分布形式已知时很优雅,但实际数据往往维数高、分布复杂。Fisher 线性判别是另一条路线:不估计密度,而是寻找一个投影方向 W,使投影后的一维数据类间均值差尽量大、类内散度尽量小。
Fisher 准则函数定义为:
J(W) = |m1' - m2'|² / (s1'² + s2'²)
其中 m1'、m2' 是投影后两类的均值,s1'²、s2'² 是投影后两类的类内散度。最优投影方向由下式给出:
W* = Sw⁻¹ · (m1 - m2)
Sw 是类内离散度矩阵,m1、m2 是原始空间中的类均值向量。这个解的本质是白化后的均值差方向,直观理解:先用 Sw⁻¹ 消除各类内部的协方差结构影响,再沿均值差方向投影。
Fisher 与贝叶斯的关系在于:当两类都服从正态分布且协方差矩阵相等时,Fisher 投影方向与贝叶斯决策边界的方向一致。差别在于贝叶斯直接给出概率输出和风险度量,Fisher 只给出判别函数值和阈值,不提供概率解释。实验中的数据是三维的,每类 36 个样本,分布形式未知,这正是 Fisher 的用武之地。
5.2 三维数据的 Fisher 判别实现
实验中的 w1 和 w2 各有 36 个三维样本点,存放在 x1-x3 和 x4-x6 六个一维数组中。下面给出完整的 MATLAB 实现,包括样本均值、类内散度矩阵、Fisher 投影方向的计算和分类判决。
function fisher_demo() % 第一类样本: x1, x2, x3 为三维坐标 % 数据从实验中读取, 这里列出主要逻辑 x1 = [0.2331 1.5207 0.6499 0.7757 1.0524 1.1974 0.2908 0.2518 ... 0.6682 0.5622 0.9023 0.1333 -0.5431 0.9407 -0.2126 0.0507 ... -0.0810 0.7315 0.3345 1.0650 -0.0247 0.1043 0.3122 0.6655 ... 0.5838 1.1653 1.2653 0.8137 -0.3399 0.5152 0.7226 -0.2015 ... 0.4070 -0.1717 -1.0573 -0.2099]; x2 = [2.3385 2.1946 1.6730 1.6365 1.7844 2.0155 2.0681 2.1213 ... 2.4797 1.5118 1.9692 1.8340 1.8704 2.2948 1.7714 2.3939 ... 1.5648 1.9329 2.2027 2.4568 1.7523 1.6991 2.4883 1.7259 ... 2.0466 2.0226 2.3757 1.7987 2.0828 2.0798 1.9449 2.3801 ... 2.2373 2.1614 1.9235 2.2604]; x3 = [0.5338 0.8514 1.0831 0.4164 1.1176 0.5536 0.6071 0.4439 ... 0.4928 0.5901 1.0927 1.0756 1.0072 0.4272 0.4353 0.9869 ... 0.4841 1.0992 1.0299 0.7127 1.0124 0.4576 0.8544 1.1275 ... 0.7705 0.4129 1.0085 0.7676 0.8418 0.8784 0.9751 0.7840 ... 0.4158 1.0315 0.7533 0.9548]; % 第二类样本: x4, x5, x6 x4 = [1.4010 1.2301 2.0814 1.1655 1.3740 1.1829 1.7632 1.9739 ... 2.4152 2.5890 2.8472 1.9539 1.2500 1.2864 1.2614 2.0071 ... 2.1831 1.7909 1.3322 1.1466 1.7087 1.5920 2.9353 1.4664 ... 2.9313 1.8349 1.8340 2.5096 2.7198 2.3148 2.0353 2.6030 ... 1.2327 2.1465 1.5673 2.9414]; x5 = [1.0298 0.9611 0.9154 1.4901 0.8200 0.9399 1.1405 1.0678 ... 0.8050 1.2889 1.4601 1.4334 0.7091 1.2942 1.3744 0.9387 ... 1.2266 1.1833 0.8798 0.5592 0.5150 0.9983 0.9120 0.7126 ... 1.2833 1.1029 1.2680 0.7140 1.2446 1.3392 1.1808 0.5503 ... 1.4708 1.1435 0.7679 1.1288]; x6 = [0.6210 1.3656 0.5498 0.6708 0.8932 1.4342 0.9508 0.7324 ... 0.5784 1.4943 1.0915 0.7644 1.2159 1.3049 1.1408 0.9398 ... 0.6197 0.6603 1.3928 1.4084 0.6909 0.8400 0.5381 1.3729 ... 0.7731 0.7319 1.3439 0.8142 0.9586 0.7379 0.7548 0.7393 ... 0.6739 0.8651 1.3699 1.1458]; % 转成列向量 x1 = x1(:); x2 = x2(:); x3 = x3(:); x4 = x4(:); x5 = x5(:); x6 = x6(:); n = numel(x1); % 每类 36 个样本 % 第一类均值向量 m1 = [mean(x1); mean(x2); mean(x3)]; % 第一类类内离散度矩阵 S1 = zeros(3, 3); for i = 1:n v = [x1(i); x2(i); x3(i)] - m1; S1 = S1 + v * v'; end % 第二类均值向量 m2 = [mean(x4); mean(x5); mean(x6)]; % 第二类类内离散度矩阵 S2 = zeros(3, 3); for i = 1:n v = [x4(i); x5(i); x6(i)] - m2; S2 = S2 + v * v'; end % 总类内离散度 Sw = S1 + S2 Sw = S1 + S2; % 类间离散度矩阵 Sb = (m1 - m2)(m1 - m2)' Sb = (m1 - m2) * (m1 - m2)'; % 最优投影方向 W = Sw^-1 * (m1 - m2) W = Sw \ (m1 - m2); W = W / sqrt(sum(W.^2)); % 归一化为单位向量 % 投影到一维空间后计算两类均值 y1 = x1 * W(1) + x2 * W(2) + x3 * W(3); y2 = x4 * W(1) + x5 * W(2) + x6 * W(3); M1 = mean(y1); M2 = mean(y2); % 阈值 W0, 使用等先验假设下的中点公式 W0 = -(M1 + M2) / 2; % 对待测样本分类 A = [1, 1.5, 0.6; 1.2, 1.0, 0.55; 2.0, 0.9, 0.68; ... 1.2, 1.5, 0.89; 0.23, 2.33, 1.43]'; for k = 1:size(A, 2) y = W' * A(:, k) + W0; if y > 0 fprintf('样本 %d 判为第一类\n', k); else fprintf('样本 %d 判为第二类\n', k); end end % 可视化: 三维散点 + 投影方向 figure; plot3(x1, x2, x3, 'r*'); hold on; plot3(x4, x5, x6, 'bp'); W_show = 5 * W; line([-W_show(1), W_show(1)], [-W_show(2), W_show(2)], ... [-W_show(3), W_show(3)], 'Color', 'k', 'LineWidth', 1.5); xlabel('x1'); ylabel('x2'); zlabel('x3'); title('Fisher 线性判别投影方向'); legend('第一类', '第二类', '投影方向'); grid on; view([-37.5, 30]);代码中的Sw \ (m1 - m2)是 MATLAB 求解线性方程组的标准写法,等价于inv(Sw) * (m1 - m2),但数值稳定性更好。W 归一化不影响判别结果,因为判决时用的是W' * x + W0,同时缩放 W 和 W0 不会改变符号。实验中给出的最优 W 约为 (-0.0798, 0.2005, -0.0478),归一化后方向不变。
5.3 Fisher 判决参数的敏感性分析
Fisher 判别有两个关键参数容易踩坑。第一,Sw 是否可逆。如果样本数小于特征维数,Sw 奇异,Sw \ (m1 - m2)会给出错误结果或直接报错。常见做法是先用 PCA 降维到样本数以下,再执行 Fisher 判别。第二,阈值 W0 的选取。实验中使用两类均值的中点在投影空间作为阈值,这在两类先验相等时是最优的。如果先验不等,需要对阈值做偏移补偿:
W0 = -(M1 + M2) / 2 + (σ² / (M1 - M2)) · log(P(ω2) / P(ω1))
其中 σ² 是投影后两类的合并方差。实验里给出的近似公式包含了这个修正项,但当两类方差差异大时,简单取中点会引入偏差。实际使用中我一般会直接在投影空间用一维高斯拟合来确定阈值,或者干脆对投影后的数据跑一个一维贝叶斯分类器,这样比人为设定 W0 更鲁棒。
6. 边界条件与参数调优:让分类器从“能跑”到“可靠”
6.1 先验概率的估计误差如何影响决策边界
实验直接给定先验概率 0.9 和 0.1,但工程中先验通常需要从数据中估计。最常见的估计方法是统计训练集中各类别的样本占比,这在样本量足够大时偏差很小。但如果训练数据来自有偏采样(比如只在特定时段采集数据),样本占比并不能代表真实先验。此时可以用验证集上的混淆矩阵反推:先以 0.5/0.5 的先验训练分类器,统计误报率 FPR 和漏报率 TPR,再利用贝叶斯公式反解先验比值。这个技巧在类别不平衡问题中非常实用,相当于把先验从“拍脑袋”变成了“可校正的参数”。
6.2 正态分布假设不成立时的退化路径
本实验假设类条件概率是正态分布,但真实数据往往有偏态或多峰。一个典型弱点是:当某个类别的方差非常小(比如正常类 σ=0.5),远离均值的样本点似然值会急速衰减到接近零。此时后验概率的计算容易产生数值下溢。MATLAB 的normpdf在参数极端时会返回 0,导致 0/0 的 NaN 结果。工程上我一般会做两步防护:
% 数值稳定性处理: 在对数域计算后验概率 log_p1 = log(pw1) + log(normpdf(x(i), e1, a1)); log_p2 = log(pw2) + log(normpdf(x(i), e2, a2)); % 减去最大值再指数化, 避免下溢 max_log = max(log_p1, log_p2); p1 = exp(log_p1 - max_log) / (exp(log_p1 - max_log) + exp(log_p2 - max_log));对数域计算将乘法转为加法,并利用“减去最大值再指数化”的技巧把中间量控制在可表示范围内。这段代码直接替换实验中的后验概率计算部分,能在不改变结果的前提下大幅提升数值稳定性。
6.3 留一法验证分类器泛化能力
实验只报告了训练集上的分类结果,没有验证集。对于贝叶斯分类器,由于模型形式固定(正态分布参数已知),主要误差来源是先验估计偏差和分布假设错误。我建议在工程中至少用留一法(LOO-CV)做一轮验证:对每个样本,用剩余样本估计先验和分布参数,再对该样本做分类。对于本实验的 24 个样本,留一法最多迭代 24 次,计算量完全可以接受。如果留一法结果与训练集结果差异较大,说明模型对个别样本敏感,需要检查是否存在离群点或分布假设是否合理。
6.4 风险矩阵与 ROC 曲线的联动调参
最小风险贝叶斯决策中,风险矩阵的比值直接决定了分类器在 ROC 曲线上的工作点。回顾判决条件:
R(α1|x) < R(α2|x) ⟺ P(ω2|x) / P(ω1|x) < (r21 - r11) / (r12 - r22)
这意味着风险比值就是后验概率比值的阈值。实验中的阈值是 2,对应 ROC 曲线上偏向“少报异常”的工作点。如果需要平衡误报和漏报,可以画出 ROC 曲线后用业务成本函数寻找最优阈值,再反推风险矩阵。这个思路把“设计风险矩阵”从拍脑袋变成了数据驱动:让业务方定下误报和漏报的代价比,代码层面自动换算成风险矩阵和判决阈值。
本文还有配套的精品资源,点击获取