简介面向认知无线电与频谱感知方向的研究者和通信专业学生这份压缩包提供了传统频谱感知算法的Matlab仿真实现用于对比能量检测、匹配滤波检测、循环平稳特征检测在不同信噪比条件下的检测性能。资源共包含3个m脚本文件整体仅3KB代码精简聚焦三个脚本与三种算法一一对应便于直接运行、修改阈值或信噪比参数并观察误检率与漏检率的变化趋势仿真中通常以误检率和漏检率作为评价指标误检率对应无信号时误判为有信号漏检率对应有信号时未能检出更低的两个指标意味着更好的感知性能。已有723人学习下载是理解频谱感知基础算法原理与适用场景的实用参考。实际应用中能量检测结构简单但低信噪比下易出现虚警匹配滤波检测性能较好却依赖已知的信号模板循环平稳特征检测能捕捉信号的周期结构但计算开销较大。借助该资源读者既能获得可复现的仿真框架也能结合结果分析这些算法的权衡取舍为认知无线电课程实验、算法比较或科研复现提供便利。1. 传统频谱感知算法性能分析为什么弱信号下20行能量检测比神经网络还稳我之前在某个频谱监测Demo里就吃过这个亏模型调好了指标好看了一换到-15dB的弱信号环境检测率直接崩到比一个20行的能量检测还低。后来把经典算法逐个拉出来做性能分析才发现问题出在基线上——不是新方法不好而是我根本没用对评价口径。传统频谱感知算法性能分析这个方向要解决的就是这件事把能量检测、匹配滤波检测、循环平稳检测这些老牌算法在检测概率、虚警概率和信噪比门限上的表现摸透用可控的仿真把每个算法的工作边界画出来。适合要实际布频谱监测、认知无线电或者做算法对比的开发者也适合那些想出新方法但还缺一套站得住脚的基线的研究者。2. 三类传统算法先立住能量检测、匹配滤波和循环平稳检测的原理与边界这一章先把三种最常出现在性能分析里的算法讲清楚。重点不是背公式而是明确它们的适用边界。离开边界谈性能基本就是玄学。2.1 能量检测实现成本最低但噪声不确定性是它的天花板能量检测的思路朴素到可以一句话讲完对接收信号求平均功率然后把平均功率和门限比。信号来了功率变大信号没来只有噪声功率。假设接收信号是复基带采样序列 r[n]统计量写成 T 1/N Σ|r[n]|²。在只有噪声的假设H0下这个统计量围绕噪声功率波动在有信号的假设H1下统计量抬高一个与信噪比有关的量。门限怎么定是能量检测里最需要抠的细节。常见做法有两种一种是高斯近似当采样点足够多时把能量统计量按高斯分布处理用目标虚警概率反解正态分位数另一种是精确卡方形式对复高斯噪声统计量 2N·T/σ² 服从自由度 2N 的中心卡方分布用卡方逆函数算门限。我一般用后者尤其是在采样点数只有一两千的时候高斯近似的门限会偏乐观。能量检测最大的优势是它不需要主用户信号的任何先验信息调制方式、符号率、波形统统不知道也能干活。但它的天花板很明确噪声不确定性。射频前端的增益漂移、温度变化、邻道干扰都会让实际噪声功率偏离标称值一旦噪声功率往下偏门限相对偏高检测概率掉得厉害往上偏虚警概率压不住。更麻烦的是当信噪比低于某个“信噪比墙”之后无论把采样时间拉多长检测性能都没法继续提升。后面做性能分析时会反复踩到这一点。2.2 匹配滤波检测性能上界需要完整先验现实中很难落地匹配滤波的思路是既然主用户信号的波形我完全知道那我直接把接收信号和本地模板做相关。统计量写成 T |Σ r[n]·s*[n]|其中 s[n] 是已知的信号模板。在加性高斯白噪声信道下匹配滤波是 Neyman-Pearson 意义上的最优检测给定虚警概率它的检测概率是三类算法里最高的。所以在传统频谱感知性能分析里它几乎总是被当作“理论上界”和“理想基准”来用。代价同样明显它要求知道主用户信号的调制方式、脉冲成型、载波频率、符号定时几乎全套先验。实际场景里只有当主用户是一个协议固定的系统比如有固定导频的播控信号匹配滤波才有落地机会。在通用的频谱感知模型里它更常见的身份是性能上界而不是可部署方案。做性能分析时我会把匹配滤波的结果画在曲线簇的最左上角同时标注清楚这是理想化结果别拿它当可达到的工程目标。2.3 循环平稳检测用计算量换鲁棒性的折中方案循环平稳检测利用的是调制信号的统计参数随时间周期变化这个内在特性。BPSK、QAM 这类数字调制信号它们的循环自相关函数会在符号速率整数倍对应的循环频率处出现谱峰而平稳噪声没有这个特性在所有非零循环频率处都不产生贡献。实现上常见做法是计算接收信号的延迟相关积再在目标循环频率处取傅里叶系数把这个系数的模作为检测统计量。这个算法最大的价值是对噪声不确定性天然免疫因为噪声在非零循环频率上没有能量聚集。能量检测在噪声功率漂移时会翻车它不会。代价也摆在那里计算复杂度高观测时间长循环频率需要估计。如果主用户信号完全未知能量检测做不了的时候它可以顶一顶如果不缺算力又想对抗噪声不确定性它通常是最稳的选择。三种算法放到一张表里看先验要求、计算量、低信噪比表现和主要劣势会清楚很多。算法先验要求计算复杂度低SNR表现主要劣势能量检测无最低O(N)中等受噪声不确定性限制存在SNR墙鲁棒性差匹配滤波完整波形先验低O(N)最好理论最优先验通常不可得循环平稳需估计循环频率高O(N log N)以上较好算得慢、观测时间长选型建议只有一条主线要压成本和快速出结果上能量检测要做公平基线和验证上界用匹配滤波要对抗噪声不确定性且不缺算力选循环平稳。抛开场景谈算法优劣没有意义。3. 性能分析的评价口径检测概率、虚警概率与ROC曲线的仿真约定这一章回答“性能分析到底分析什么”的问题。评价口径不先定下来后面所有曲线都没有可比性拿出去也是浪费。3.1 三个指标和一个曲线先把评价口径定下来频谱感知里的性能核心是三个量检测概率 Pd、虚警概率 Pf以及两者之间的权衡曲线 ROC。Pd 是主用户信号存在时算法正确报“占用”的概率Pf 是只有噪声时算法瞎报“占用”的概率。门限调低什么都容易被判成“有信号”Pd 会高但 Pf 也会高门限调高Pf 降下来Pd 也跟着掉。ROC 就是把这个权衡画出来横轴是 Pf纵轴是 Pd曲线越往左上角越好。和普通数字通信检测不一样频谱感知更关心低信噪比区间的表现。通信里常在固定误比特率目标下做对比频谱感知则通常固定 Pf 目标例如 0.01然后看不同 SNR 下 Pd 的下降速度或者固定一个 SNR把门限从紧到松扫一遍画出整条 ROC。我在做性能分析时会两种口径都出固定 Pf 扫 SNR看检测能力随信噪比退化的程度固定 SNR 扫门限看算法有没有真正把虚警压下来。只给一条 ROC 不给对应 SNR等于没给结果。3.2 蒙特卡洛仿真框架多少样本、多少信噪比才算数检测概率和虚警概率很难用闭式公式算全性能分析基本都靠蒙特卡洛仿真估计。框架是三到四层循环外层扫 SNR中层跑蒙特卡洛内层依次生成信号、加噪声、算统计量、和门限比较。蒙特卡洛次数 M 直接决定估计误差。Pd 的估计是伯努利均值标准差是 sqrt(Pd(1-Pd)/M)。M 取 500误差可能到四五个百分点画出的曲线毛躁不堪M 取 5000 到 10000误差能压到 1 个百分点以内。我自己的习惯是快速验证逻辑用 2000正式出图前把 M 提到 10000。SNR 扫描范围也有讲究。传统感知算法的研究价值集中在-20dB 到 0dB 这段。低于-20dB连理论上界也基本失灵曲线糊成一团高于 0dB能量检测都能做到接近 1看不出区分度。步长 2dB 够用1dB 图更顺滑但仿真时间几乎翻倍。采样点数 N 一般取 1000 到 10000它和观测时间捆绑也决定后面的频率分辨率。最后一件容易被忽略的事是固定随机数种子。不固定的话每跑一次结果都小幅飘动算法间对比就无从谈起。3.3 噪声不确定性建模这是传统算法性能分析的灵魂参数我在第2章提过噪声不确定性现在把它量化。实际接收机里的噪声功率不会正好等于标称值工程上用一个不确定性因子描述标称噪声功率是 σ²实际噪声功率可能在 σ² 除以 β 到 σ² 乘以 β 之间浮动β 由噪声不确定度换算。不确定度 1dB 对应的 β 大约是 1.26。很多性能分析资料根本没有这一步直接把噪声功率设为常量能量检测在“理想噪声”假设下会显得过于能打结论失真得离谱。正确的建模方法是这样的每次蒙特卡洛循环里先从一个范围内均匀抽取一个偏移量单位是 dB再叠加到标称噪声功率上生成实际噪声样本。注意门限计算必须用标称噪声功率因为接收机在检测时并不知道当前实际的噪声功率漂移到了哪里。仿真时实际噪声功率用漂移后的值门限用标称值这才是真实闭环。这一点我会在后面反复强调它是传统频谱感知性能分析里最容易翻车的地方。4. 把性能分析在MATLAB中跑通最小复现代码与参数设置这一章直接上可复现代码按“信号源—检测器—蒙特卡洛骨架”三步走。环境是 MATLAB脚本结构足够清晰改成 Octave 也基本不需要动。4.1 信号源模型BPSK调制与AWGN信道生成先定义仿真参数块。所有关键量都集中在这里改参数不用在脚本里到处翻。rng(42); % 固定随机数种子保证可复现 N 4096; % 单次感知采样点数 fs 1e6; % 采样率 1MHz T_sym 10e-6; % 符号周期 10us M 5000; % 蒙特卡洛次数 SNR_vec -20:2:0; % 信噪比扫描范围单位dB Pf_target 0.01; % 目标虚警概率 noise_uncert_db 1.0; % 噪声不确定性单位dB % BPSK 基带符号直接用复基带等效模型省去载波调制与下变频环节 bits 2 * randi([0 1], 1, N) - 1; % 取值 -1 或 1 sig bits; % 这个序列同时兼任匹配滤波的本地模板 sig_energy sum(abs(sig).^2); % 信号能量后面推算噪声功率用参数说明N 取 4096 是让后续运算都落在 2 的幂上跑得快想模拟更长观测窗口可以拉到 8192但蒙特卡洛循环时间会线性上涨。SNR_vec 从-20dB 到 0dB、步长 2dB覆盖传统算法最敏感的区域。noise_uncert_db 先设 1dB这是工程上比较常见的噪声不确定度设为 0 就是理想噪声用于对照实验。接下来生成含噪接收信号。下面以单次实验为例真实扫描在第 4.3 节包进循环。snr_demo -10; % 演示用信噪比扫描时会逐个替换 signal_power sig_energy / N; noise_var_nominal signal_power / (10^(snr_demo/10)); % 标称噪声功率 % 噪声不确定性本次实验均匀抽取一个偏移接收机不知道这个值 unc_db (2*rand-1) * noise_uncert_db; % 区间 [-U, U] dB noise_var_actual noise_var_nominal * 10^(unc_db/10); % 实际噪声功率 % 复AWGN噪声叠加到信号上 noise sqrt(noise_var_actual/2) * (randn(1,N) 1j*randn(1,N)); rx sig noise; % 复基带接收信号逻辑说明噪声功率由目标 SNR 反推把信号功率和噪声功率绑在一起。噪声不确定性每次抽取一个偏移量生成实际噪声这个偏移量对接收机不可见因为接收机手里只有标称噪声功率。我特意用了两个变量名noise_var_nominal 和 noise_var_actual就是为了在代码层面逼自己把这条边界焊死后面门限计算只能碰前者。4.2 三种检测器的统计量与门限计算第一种是能量检测。统计量直接用平均功率门限用卡方精确形式适合 N 不算特别大的场景。T_ed mean(abs(rx).^2); % 平均功率统计量 % 复AWGN下2*N*T/sigma^2 服从自由度 2N 的中心卡方分布 gamma_ed noise_var_nominal * chi2inv(1-Pf_target, 2*N) / (2*N); detect_ed T_ed gamma_ed;逻辑说明chi2inv(1-Pf_target, 2N) 是一个静态值理论上可以放在蒙特卡洛循环外先算好省去重复调用。卡方精确形式在 N 只有几千时比高斯近似准这是我一直用它做门限的原因。第二种是匹配滤波检测。前提是接收机存有主信号的无噪复本。T_mf abs(sum(rx .* conj(sig))); % 相关统计量sig 同时充当无噪模板 % 相关结果的模在H0下服从瑞利分布反解虚警概率得到门限 gamma_mf sqrt(-noise_var_nominal * N * log(Pf_target)); detect_mf T_mf gamma_mf;逻辑说明这里直接用无噪信号 sig 做模板相关统计量的模在纯噪声下服从瑞利分布所以门限按瑞利尾概率反解。模板一旦混入噪声相关增益会虚高第5章会专门讲这个坑。可以对比的是很多旧代码用高斯近似门限在 Pf 较小的时候偏差不小瑞利形式更稳。第三种是循环平稳检测给一个可运行的最小实现统计量是延迟相关积在循环频率处的傅里叶系数。alpha 1 / T_sym; % BPSK符号速率对应循环频率单位Hz D round(fs * T_sym); % 延迟量一个符号周期对应的采样点数 delayed rx(1:N-D) .* conj(rx(1D:N)); % 延迟相关积 T_cyclo abs(mean(delayed .* exp(-1j*2*pi*alpha*(0:N-D-1)/fs))); % 门限噪声在非零循环频率上没有谱峰但有限快拍下残差不为零 % 工程近似取3倍标准误正式实验用纯噪声样本分位数标定 gamma_cyclo 3 * std(delayed) / sqrt(N-D); detect_cyclo T_cyclo gamma_cyclo;逻辑说明BPSK 的循环平稳特性来自符号周期alpha 取 1/T_sym 能在谱相关里看到峰。门限用当前帧残差标准差估计是快速原型做法gamma_cyclo 那个 3 是调节系数决定虚警概率大小需要根据目标 Pf 在 2 到 4 之间扫。注意这个门限对 SNR 有隐含依赖正式出图前一定要用纯噪声样本单独标定否则第5章第5条的坑等着你。4.3 扫SNR跑蒙特卡洛生成ROC曲线的骨架代码把上面的检测器包成两层循环外层扫 SNR内层跑 M 次蒙特卡洛分别统计 H1 下检测成功次数和 H0 下误报次数从而算出 Pd 和 Pf。Pd_ed zeros(numel(SNR_vec), 1); Pd_mf zeros(numel(SNR_vec), 1); Pd_cyclo zeros(numel(SNR_vec), 1); for si 1:numel(SNR_vec) snr SNR_vec(si); signal_power sig_energy / N; noise_var_nominal signal_power / (10^(snr/10)); gamma_ed noise_var_nominal * chi2inv(1-Pf_target, 2*N) / (2*N); gamma_mf sqrt(-noise_var_nominal * N * log(Pf_target)); det_ed_cnt 0; det_mf_cnt 0; det_cyclo_cnt 0; for mc 1:M unc_db (2*rand-1) * noise_uncert_db; noise_var_actual noise_var_nominal * 10^(unc_db/10); noise sqrt(noise_var_actual/2) * (randn(1,N) 1j*randn(1,N)); rx sig noise; if mean(abs(rx).^2) gamma_ed det_ed_cnt det_ed_cnt 1; end if abs(sum(rx .* conj(sig))) gamma_mf det_mf_cnt det_mf_cnt 1; end % 循环平稳检测建议封装成子函数这里只列出计数逻辑 % if detector_cyclo(rx, alpha, D, fs) gamma_cyclo % det_cyclo_cnt det_cyclo_cnt 1; % end end Pd_ed(si) det_ed_cnt / M; Pd_mf(si) det_mf_cnt / M; Pd_cyclo(si) det_cyclo_cnt / M; end figure; plot(SNR_vec, Pd_ed, -o, SNR_vec, Pd_mf, -s, SNR_vec, Pd_cyclo, -^); grid on; xlabel(SNR / dB); ylabel(Pd); legend(能量检测,匹配滤波,循环平稳);逻辑说明门限计算必须放在 SNR 循环内因为不同 SNR 下标称噪声功率不同门限随之变化。三种检测器吃完全相同的噪声样本和信号样本曲线才有可比性这就是公平基线的底线。出的图是 Pd 随 SNR 变化的曲线想要 ROC 曲线的话把门限对 Pf_target 的依赖换成一组扫描系数外层再套一层门限循环即可。注意循环平稳检测的门限 gamma_cyclo 在当前代码里只是工程近似正式做性能分析前请用纯噪声样本跑一段 H0 数据用分位数把门限标到目标 Pf再进蒙特卡洛循环。5. 传统频谱感知性能分析避坑复现时最常遇到的五个常见问题这一章写血泪经验。几乎每个坑我都见过同行踩过按“现象—原因—解决”列出来照着排就行。5.1 现象低SNR下能量检测的检测概率反而高于理论值第一次跑出图的人大概率会高兴以为自己找到了能量检测的改进版。先别高兴。我见过 A 同学把实际噪声方差直接拿来算门限门限跟随实际噪声功率每轮漂移虚警被“顺带”校正掉了检测概率自然虚高。原因就是把接收机实际面对的噪声功率和接收机用于判决的标称噪声功率搞混了。解决门限只能用标称噪声功率实际功率只用于生成样本。代码里两个变量名分清楚这条边界就不会破。5.2 现象三种算法ROC曲线几乎重合能量检测被“美化”在理想噪声下跑三种算法中等 SNR 区域重合不少看起来能量检测性价比逆天。这不是真实场景的结论。原因很简单没有把噪声不确定性建模进去能量检测最致命的短板被抹掉了。解决把 noise_uncert_db 从 0 改成 1dB 重新跑你会看到能量检测的 Pd 曲线明显右移而循环平稳检测几乎不动。这才是传统频谱感知性能分析该有的样子。很多论文里能量检测“意外能打”多半是噪声模型太干净。5.3 现象ROC曲线毛刺多、不成形反复跑结果对不上有人 M 取 500 就急着出图曲线像锯齿有人不固定随机数种子同一组参数跑两次相差几个百分点于是怀疑检测器实现有 bug。原因就是蒙特卡洛方差过大和随机过程不可复现两个问题叠加。解决M 提到 5000 以上脚本开头写 rng(42) 固定种子。如果这两条都做了曲线还毛再怀疑检测器实现。注意固定种子只固定了随机序列循环里的 rand 调用位置动了序列照样错位还是会产生隐式相关性。5.4 现象匹配滤波的检测概率超过理论上界匹配滤波已经是理论上界比它还高只能说明数据泄漏了。最常见的根源是生成信号和本地模板用了同一个随机数组模板直接等于含噪样本或者模板里混入了一部分实际噪声。解决模板必须是无噪复本信号和噪声要独立生成。正确顺序是先生成 sig 并把它存为模板再独立生成 noise 叠加成 rx最后绝对不要用 rx 去当模板。这条坑很难自查因为结果曲线看起来好得离谱我每次都会先怀疑它。5.5 现象循环平稳检测的虚警率不受控Pf跑到0.5以上现象是纯噪声场景下检测器也大量报警虚警完全失去控制。原因多半是循环频率 alpha 没对准延迟相关积里残留了大量直流分量或者谱泄漏把噪声功率带到了目标循环频率。解决先用纯噪声样本扫一遍 alpha画出统计量分布确认目标 alpha 处噪声残差明显小于信号峰值再把门限系数调高到 4 以上或者用纯噪声样本的分位数直接标定门限。循环平稳检测不是拿来就能跑的必须先做一次噪声标定再谈性能。6. 把性能分析用起来用基线验证新算法有没有真实增益性能和复现都做通了接下来是这套东西最有价值的使用方式验证你自己提出的新算法是不是真的有所提升。我自己有一条固定的验证路径。第一步和最优传统基线比。匹配滤波是理论上界能量检测是最低工程基线和实用底线把新算法的 Pd-SNR 曲线夹在它们之间看位置。如果新算法比匹配滤波还好先检查模板、随机种子和噪声数据是不是泄漏了而不是先庆祝。这个习惯帮我挡掉过至少两次“新算法超越上界”的假结果。第二步加噪声不确定性压力测试。把 noise_uncert_db 从 0 逐步提到 1.5dB观察新算法的 Pd 曲线右移幅度。传统能量检测在 0.5dB 不确定性下就明显退化新算法如果仍然能维持右移不超过 1 到 2dB才算是真的鲁棒。这一步可以在第 4.3 节的代码外再套一层噪声不确定性循环出来的结果是一张热图比单条曲线更有说服力。第三步坚持同种子公平对比。让新算法和三种传统算法吃完全相同的噪声样本、相同的信号生成参数、相同的观测时长。这是公平对比的底线也是验收时最容易被挑的毛病。我习惯把信号生成、噪声生成、统计量计算全部抽成公共函数新算法只替换统计量那一层其他一概不动。这样对比协议不会跑偏结果也经得起复现。最后说一个习惯每次跑完实验把噪声不确定性、蒙特卡洛次数、随机种子、采样点数这四样参数写进图表文件名里。准备复现材料时会发现这几个参数比算法公式本身更能定位问题。这个习惯我用了很多年帮我避开了不少“当时明明跑出来了现在怎么不对”的尴尬。希望帮到你。本文还有配套的精品资源点击获取