
简介作业1贝叶斯检验与信号检测作业资源包面向电子信息、统计决策及IT相关方向学生适用于需要理解贝叶斯决策理论并完成N次观测下信号检测实践的场景。资源以贝叶斯公式为核心系统呈现先验概率、似然函数与后验概率的更新过程并结合代价矩阵分析误警与漏检的不同后果引导读者在N次独立观测中累积证据、权衡风险进而设计使总期望损失最小的检验策略同时涉及大数定律、累积和与停时准则等拓展方法。配套的Python脚本实现了贝叶斯检验与信号检测的关键算法流程Word实验报告则记录了假设检验公式推导、似然比计算、阈值设定、结果分析与结论总结可帮助读者将理论落地为可运行、可验证的课程作业方案。压缩包共2个文件含1个py源码和1个docx文档整体大小179KB内容精炼、结构清晰兼顾代码实现与理论记录。目前已有261人学习下载适合作为信号检测与统计决策入门作业的完整样例。1. 贝叶斯检验在信号检测里解决什么问题当你在雷达屏幕上找目标、在解调器里判 0/1、在脑电数据里挑诱发电位核心问题其实是同一个眼前这一串观测值到底来自“信号叠加噪声”还是“只有噪声”信号检测理论把这个决策写成二元假设检验而贝叶斯检验是其中把“先验知识”与“代价”都纳入判决的最直接方案也因此成为许多课程作业的常客。初学者往往以为信号检测就是拿一个固定阈值跟采样值比大小。贝叶斯检验的真正价值在于它告诉你阈值不是拍脑袋定的而是由先验概率和两类错误的代价共同决定换一组代价判决门限就跟着移动。这篇文章从判决门限的推导讲起用 Python 完成一次从模拟信号、贝叶斯检测器到 ROC 曲线调优的完整实验最后把蒙特卡洛验证和阈值搜索写成一个可以直接搬走的脚本。适合正在写作业、准备信号检测课程实验或者手头恰好有二元检测问题想快速落地的工程师。2. 从似然比到判决门限把贝叶斯检验写成可计算的规则2.1 信号检测的两类错误虚警与漏检先把假设写清楚。设观测为xH0 表示“无信号”H1 表示“有信号”。检测器根据x输出D0或D1于是会出现两类错误当 H0 为真却判成D1称为虚警当 H1 为真却判成D0称为漏检。工程里这对错误的价值往往不对等——雷达漏报一个目标可能造成事故而空警报只是浪费操作员注意力。贝叶斯检验不回避这种不对等它显式引入代价矩阵。用 Cij 表示 Hj 为真时判决为 Di 的代价构成一张 2×2 表判决 \ 假设H0 为真H1 为真判为 D0C00C01判为 D1C10C11一般令正确判决代价为 0虚警和漏检代价为正。真正要最小化的量是平均风险R P0 * [C00 * P(D0|H0) C10 * P(D1|H0)] P1 * [C01 * P(D0|H1) C11 * P(D1|H1)]其中 P0、P1 是 H0、H1 的先验概率。信号检测课程里常见的“最小错误概率准则”就是令 C00C110C10C011此时风险退化为分类错误率。但贝叶斯框架允许代价不对称这在实际场景里远比单纯最小错误率更贴近需求。2.2 似然比检验为什么是贝叶斯判决的骨架对每个观测x我们要比较“判 D1”和“判 D0”哪边带来的期望代价更低。给定x后H0 和 H1 的后验概率由贝叶斯公式给出P(H1|x) P1 * f1(x) / f(x)P(H0|x) P0 * f0(x) / f(x)其中 f0(x)、f1(x) 是两种假设下的似然概率密度。判决 D1 的条件是选择 D1 后仍处在 H0 状态的期望代价小于选择 D0 的。整理后得到一个非常干净的判据Λ(x) f1(x) / f0(x) η这个 Λ(x) 就叫似然比η 是判决门限。判决规则是观测样本的似然比超过 η 就判“有信号”否则判“无信号”。所有基于后验概率最小风险的判决最终都会化简成同一种形式差别只在门限 η 怎么取。2.3 判决门限由先验和代价联合决定把代价和先验代入后验代价比较可以得到门限的闭式表达式η P0 * (C10 - C00) / [P1 * (C01 - C11)]当正确判决代价为 0且虚警与漏检代价都为 1 时η P0 / P1。如果 P0 和 P1 相等门限就是 1此时判决完全由似然比是否大于 1 决定。如果“有信号”很罕见比如 P00.9P10.1那么门限变成 9。这意味着观测证据必须非常强才能把先验压下去。在信号检测里这个门限还会继续变形。H0 是零均值高斯噪声H1 是幅度为 s 的直流信号叠加同方差高斯噪声时对似然比取对数不等式会变成对采样值 x 的某个线性阈值。这个过程不需要任何奇技淫巧步骒就是“写出两个高斯密度、相除、取对数、整理”。手动推一遍对数似然比比翻十页教材更容易理解为什么很多通信接收机里判决门限是一个与信噪比相关的常数。3. 用 Python 做一次完整的贝叶斯信号检测实验3.1 生成观测样本实验从仿真数据开始。考虑最简单但很有代表性的模型H0 下x ~ N(0, σ²)H1 下x ~ N(s, σ²)。先验概率设 P00.7、P10.3这样后续能看出先验对门限的影响。生成样本时注意按先验比例分配标签再打乱顺序。import numpy as np rng np.random.default_rng(42) s 1.0 # 信号幅度 sigma 1.0 # 噪声标准差 P0, P1 0.7, 0.3 # 先验概率 N 1000 n0 int(N * P0) n1 N - n0 x0 rng.normal(0, sigma, n0) # H0 样本 x1 rng.normal(s, sigma, n1) # H1 样本 obs np.concatenate([x0, x1]) labels np.concatenate([np.zeros(n0), np.ones(n1)]) perm rng.permutation(N) obs obs[perm] labels labels[perm]用固定随机种子是为了让结果可重现调参时不会出现“这次过了下次不过”的情况。样本量取 1000 级别既能跑出稳定统计量又不会让后续蒙特卡洛循环太慢。这里刻意没有用 sklearn 的数据生成器因为自己控制噪声方差和先验比例才能直观看到参数变化对检测的影响。3.2 贝叶斯检测器的参数设定与实现检测器需要做的三件事计算每个样本的似然比计算门限 η然后比较判决。代价参数单独暴露出来方便做代价敏感实验。def bayes_detector(x, s, sigma, P0, P1, C101.0, C011.0): eta P0 * C10 / (P1 * C01) # 高斯似然比exp(-0.5*((x-s)/sigma)^2) / exp(-0.5*(x/sigma)^2) log_likelihood_ratio -0.5 * (((x - s) / sigma) ** 2 - (x / sigma) ** 2) return (log_likelihood_ratio np.log(eta)).astype(int)这里用对数似然比避免 exp 下溢。当 s 和 sigma 都接近 1、样本量不大时原始似然比也能算但写成对数形式更稳健数值范围更可控。门限 η 的计算中C10 是对虚警的惩罚C01 是对漏检的惩罚如果业务要求“绝对不能漏”就把 C01 调大门限会下降检测器更容易报“有信号”。3.3 用混淆矩阵验证检测结果对 1000 个样本跑一遍检测器统计四种结果的数量。pred bayes_detector(obs, s, sigma, P0, P1) tn np.sum((pred 0) (labels 0)) fp np.sum((pred 1) (labels 0)) fn np.sum((pred 0) (labels 1)) tp np.sum((pred 1) (labels 1)) print(fTN{tn} FP{fp} FN{fn} TP{tp}) print(f虚警率{fp/(fptn):.3f} 漏检率{fn/(fntp):.3f})一次典型运行可能得到虚警率 0.02、漏检率 0.51 这样的结果。漏检偏高不是 bug而是 P00.7、P10.3 的不对称先验造成检测器整体偏向保守只有证据很强的样本才敢判 H1。这时候可以把 C01 调大再跑漏检率会明显下降但虚警会抬头。一对矛盾指标开始显现这正是下一章要讨论的阈值权衡。4. 阈值与性能ROC 曲线、虚警概率和检测概率的权衡4.1 阈值变化对检测结果的直接影响继续沿用上一章的仿真数据但把门限作为自变量扫一遍。门限 η 很小的时候似然比很容易超过它检测器几乎把所有样本都判为 H1虚警率逼近 1漏检率逼近 0。门限 η 很大的时候判 H1 的条件苛刻虚警率降低漏检率升高。门限 log(η)虚警率检测概率(TPR)-2.00.840.980.00.370.840.80.090.551.60.010.21这个表说明一个关键点不存在“最好”的阈值只有“对当前场景最合适”的阈值。贝叶斯检验给出的门限是在给定先验和代价下的最优工作点如果你接受的先验或代价和真实环境不一致那它在 ROC 曲线上就不是你想要的位置。4.2 手动绘制 ROC 曲线并选择工作点ROC 曲线的横轴是虚警率FPR纵轴是检测概率TPR。它不依赖具体阈值可以把检测器在所有门限下的表现一次性画出来。这里不依赖 sklearn直接遍历阈值也能算顺便加深对曲线形状的理解。def compute_roc(scores, labels, n_thresh200): thr_list np.linspace(scores.min(), scores.max(), n_thresh) fpr_list, tpr_list [], [] for thr in thr_list: pred (scores thr).astype(int) tp np.sum((pred 1) (labels 1)) fp np.sum((pred 1) (labels 0)) tn np.sum((pred 0) (labels 0)) fn np.sum((pred 0) (labels 1)) fpr fp / (fp tn) if (fp tn) 0 else 0.0 tpr tp / (tp fn) if (tp fn) 0 else 0.0 fpr_list.append(fpr) tpr_list.append(tpr) return np.array(fpr_list), np.array(tpr_list), thr_list # 用对数似然比作为打分 x_all np.concatenate([x0, x1]) y_all np.concatenate([np.zeros(len(x0)), np.ones(len(x1))]) log_lr -0.5 * (((x_all - s) / sigma) ** 2 - (x_all / sigma) ** 2) fpr_arr, tpr_arr, thr_arr compute_roc(log_lr, y_all)ROC 曲线越靠近左上角说明检测器在所有门限下的综合性能越好。曲线下方的面积 AUC 可以压缩成一个数字但实际选工作点时还是要回到业务约束虚警率不能超过 0.05就在曲线上找纵坐标最高且横坐标不超过 0.05 的点再反查thr_arr对应的门限。很多工程师直接用 sklearn 的 roc_curve 三行出图但对阈值搜索来说自己实现这个循环反而更容易接进自动调参流程。4.3 最小错误率准则下的贝叶斯阈值贝叶斯阈值和 ROC 曲线之间有一个直接的几何关系。当 C00C110、C10C011 时门限 ηP0/P1把这个门限对应的 (FPR, TPR) 点标到 ROC 曲线上它正好是“最小错误率”工作点。换个角度理解ROC 曲线给出所有可能的区间贝叶斯检验给出其中某个特定点。如果先验概率估计不准工作点会沿着 ROC 曲线滑动。常见做法是把先验设成保守值比如对稀有事件让 P1 比历史频率略高一点来压低漏检风险。代价参数的设置也类似通常不是从论文里抄而是从业务损失反推一次漏检损失多少钱、一次虚警损失多少钱比值直接进 C01/C10。5. 蒙特卡洛验证与阈值自动搜索把贝叶斯检测用到实处5.1 用蒙特卡洛仿真验证理论错误率手推的错误概率公式只在模型假设完全成立时准确而仿真数据的有限样本误差会被混淆矩阵放大。更可靠的做法是把“生成数据 → 检测 → 统计错误率”重复几百次得到错误率的均值和方差。def run_mc_once(seed, N2000, s1.0, sigma1.0, P00.7, P10.3): rng np.random.default_rng(seed) n0 int(N * P0) n1 N - n0 x np.concatenate([rng.normal(0, sigma, n0), rng.normal(s, sigma, n1)]) y np.concatenate([np.zeros(n0), np.ones(n1)]) pred bayes_detector(x, s, sigma, P0, P1) err np.mean(pred ! y) return err errs [run_mc_once(seed) for seed in range(200)] print(f平均错误率{np.mean(errs):.3f} 标准差{np.std(errs):.3f})如果理论推导和仿真结果相差超过两个标准差先检查推导里的代价符号是否写反再检查样本生成时是否真的按先验比例分配了标签。蒙特卡洛仿真的意义不是“验收”而是逼你把每个概率假设都暴露在随机性面前。5.2 自动搜索满足虚警约束的阈值工程里更常见的需求不是最小化错误率而是“把虚警率压到某个值以下同时让检测概率尽量高”。这可以直接在 ROC 数据上做约束搜索def search_threshold_by_fpr(fpr_arr, tpr_arr, thr_arr, max_fpr0.05): valid np.where(fpr_arr max_fpr)[0] best_idx valid[np.argmax(tpr_arr[valid])] return thr_arr[best_idx], fpr_arr[best_idx], tpr_arr[best_idx] thr_best, fpr_best, tpr_best search_threshold_by_fpr( fpr_arr, tpr_arr, thr_arr, max_fpr0.05 ) print(f门限{thr_best:.3f} 虚警率{fpr_best:.3f} 检测概率{tpr_best:.3f})这段代码的业务含义是在 ROC 曲线上只保留虚警率不超标的点再从这些点里挑检测概率最大的。它没有改变检测器本身只是帮你找到了最适合当前约束的门限。实际使用时max_fpr应从业务方给定的指标里来而不是随便取 0.05。5.3 从“指定先验”到“让数据告诉先验”最后说一个能让检测器更贴近真实数据的小技巧。当先验概率 P1 无法从业务上估计或者环境发生了漂移时继续用固定先验会带来系统性偏差。常见做法是保留一截不参与测试的历史样本用最大似然估计粗算 P1 的频率再用这个估计值动态更新门限。这个思路在经验贝叶斯里叫“先验来自边缘分布”本质上就是让数据替你做判断。门限随先验更新后检测器也就从纯贝叶斯变成了带反馈的自适应检测系统。对一维高斯模型来说整个过程只需要改一行eta的计算当噪声不再是高斯、信号不再是加性直流时可以保留交叉验证法估算错误率门限则改为在自定义代价函数上用网格搜索。把先验从“指定”改成“从数据里估”之后整个检测器就从贝叶斯变成了经验贝叶斯这一步通常比换更复杂的噪声模型更能提升现场指标。本文还有配套的精品资源点击获取