ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

深度学习实战:基于时频图与跨窗口自注意力的干扰识别

深度学习实战:基于时频图与跨窗口自注意力的干扰识别 1. 为什么干扰识别必须换一条技术路线先说一个我自己的真实经历。去年做一套频谱监测系统外场测试时接收机某个频段底噪异常抬升通信链路误码率直接飙到不可用。当时用传统方法排查了很久能量检测能确认这个频段确实有异常能量注入但判断不了具体是什么干扰循环谱分析能看出一点周期特征可等我们把特征工程做完干扰早就换了参数和样式等于白忙活。最后把方案切到深度学习做干扰识别一个晚上训出模型第二天在实测数据上一跑之前识别不出的三种干扰样式全部给出置信度排序问题定位时间从以天计缩短到分钟级。这个项目做下来我最大的感受是干扰识别不是新问题但传统方法把识别拆成了特征设计和分类器两步而特征设计这一步严重依赖专家经验每遇到一种新干扰样式都要重新设计特征换一个参数组合可能就得重来。深度学习把两步合并成一次端到端的学习只要数据覆盖到位模型会自己从信号里归纳出区分性线索不需要人先验地告诉它扫频干扰应该在时频图上表现为斜线这类规则。这篇文章我打算把整个项目的链路拆开讲清楚从数据生成、模型选型、训练调参到真实环境部署的坑全部覆盖。适合两类读者一类是做频谱监测、通信抗干扰、电子对抗相关方向的工程师正在评估这个方向怎么落地另一类是学了一段时间深度学习想找一个有明确应用价值的实战项目来练手的同学。文章里没有太多复杂的数学推导但我会把每个关键决策背后的理由说透包括那些论文里不会写、踩了坑才明白的细节。1.1 传统干扰识别的三板斧到底卡在哪传统方案里能量检测是最基础的做法思路是设定一个功率门限超过门限就判定有干扰。它只回答有没有的问题回答不了是什么。循环平稳特征分析比能量检测进了一步它利用通信信号和干扰在循环谱上的差异来做区分对周期性的通信信号确实有效但扫频干扰、宽带阻塞这类非平稳干扰几乎没有稳定的循环频率特征效果大打折扣。匹配滤波或模板匹配的思路更直接先把各种已知干扰的波形存成模板然后拿接收信号做相关运算问题是真实对抗场景里干扰的参数带宽、扫频速率、驻留时间、重复周期全在动态变化你根本没法穷举所有模板。这三板斧有个共通的隐含假设我得提前知道干扰大概长什么样。而深度学习的核心区别在于它不要求你先验定义干扰而是从大量样本中自动寻找区分性特征。我用一个类比来理解这件事传统方法像是给机器写一本图文并茂的《鸟类图鉴》要求它每看到一只鸟就去翻图鉴比对深度学习方法则是带机器去看成千上万只鸟的照片让它自己总结出翅膀形状喙的长度羽毛颜色这些组合规律遇到没见过的种类也能根据规律做出判断。1.2 深度学习方案的定位不是替代是组合很多同行问我上深度学习是不是意味着把传统方法全扔掉。我的答案是没必要两者完全可以组合使用。一个比较实用的分工是传统方法在前端做快速检测用能量检测或简单的频谱特征判断当前频段有没有异常计算量小、延迟低适合常开一旦检测到异常再触发深度学习模型做精细分类判断具体的干扰类型和参数范围。这样既能控制整体功耗和计算开销又能在关键时刻发挥深度学习在高精度分类上的优势。在我们这个项目里前端保留了一个基于能量检测的触发模块后端跑的是深度分类模型。实测下来深度学习单模型对已知干扰类型的分类准确率能做到95%以上但对有没有干扰这种二分类问题简单门限检测反而更稳——深度模型对微弱的底噪抬升不敏感容易漏检。所以别迷信单一技术路线最稳的方案通常是传统方法和深度模型各管一段。2. 干扰类型与数据集构建先把敌人定义清楚模型再强喂进去的数据不行也白搭。干扰识别模型本质上是个分类器它的性能上限是由训练数据的信息量决定的而不是由网络结构决定的。我在这个项目里花在数据上的时间几乎和模型调优一样多因为干扰类型、信号表示方式、信噪比覆盖范围这几个决策直接影响模型能不能真正落地。2.1 常见的干扰类型与信号特征先梳理一下我们考虑过的干扰类型。不同场景下干扰样式差别很大但大体可以归成以下几类干扰类型时域特征频域/时频特征识别难度单音连续波干扰固定频率正弦波频域单根谱线低多音干扰多个固定频率正弦叠加多根离散谱线低线性扫频干扰频率随时间线性变化时频图上呈现斜线中宽带阻塞干扰大带宽噪声压制时频图上平坦宽带低部分频带干扰覆盖部分信号带宽频域局部凸起中脉冲干扰短时突发、高功率宽带但不连续较高梳状谱干扰多根等间隔谱线频域呈梳齿状中看起来类型不少但真正的难点在于同一类干扰的参数变化。同样是扫频干扰扫频速率从1MHz/ms变到50MHz/ms在时频图上的斜率完全不同同样是部分频带干扰带宽占比从10%到80%频谱形态差异也很大。如果训练集里只有固定参数模型学到的其实是针对单一参数模板的记忆而不是对这类干扰的抽象理解。所以在生成数据时必须把每个类型的关键参数都随机化覆盖足够宽的范围。2.2 信号表示方式怎么选IQ序列、时频图还是星座图深度学习模型吃的是张量原始信号不能直接送进去得先决定用哪种表示方式。我试过三种实际体验差别很大。第一种是直接用IQ序列I路和Q路采样点拼接成两通道序列输入1D-CNN或Transformer。这是信息无损的表示方式模型理论上能利用时域波形里的全部信息但问题是序列长度长计算开销大而且对低信噪比场景特别不友好。信噪比一旦降到5dB以下信号完全淹没在噪声里纯时域波形上肉眼看不出任何结构模型学起来很吃力。第二种是时频图用短时傅里叶变换STFT把一维信号变成二维的时间-频率-能量图像然后输入2D-CNN。这是我在实际项目里最推荐的方式。原因很直观很多干扰类型的判别特征在时频域里一目了然比如扫频干扰是斜线、宽带阻塞是整块矩形、脉冲干扰是断续的短竖条。模型把时频图当成图像处理等于把人类专家的视觉经验直接编码进了输入特征学习难度大大降低。我们在低信噪比条件0dB附近下对比过时频图输入的准确率比IQ序列输入高出将近10个百分点。第三种是星座图把IQ样本映射到复数平面。这个方式在调制识别里很常用因为PSK、QAM等调制方式的星座点分布差异明显。但用在干扰识别上效果一般因为绝大多数干扰是宽带的、非恒包络的在星座图上形态混乱区分度很差。我个人的结论是干扰识别任务优先选时频图如果以后想往端到端实时处理方向走再考虑IQ序列加Transformer的组合。2.3 数据生成与划分策略一个可以抄的流程数据集构建这件事我整理成一套可以直接复用的流程每一步都有明确的配置参考。第一步是信号仿真。用接收信号模型接收信号 通信信号 干扰信号 噪声。通信信号可以用QPSK、16QAM等常见调制方式生成速率、滚降系数、多径信道参数都做随机化。干扰信号按2.1里的类型逐一实现每类干扰的参数服从随机分布。第二步是信噪比覆盖。不能只在某个固定信噪比下生成数据要在-15dB到15dB范围内按1dB步进覆盖。低信噪比的样本对模型识别能力的影响很大如果训练集里所有样本都是高信噪比模型在真实环境里会直接崩溃。第三步是时频图参数选择。STFT的窗长影响频率分辨率和时间分辨率的平衡我们用的窗长是256个采样点重叠率75%得到的时频图尺寸大约在224x224附近方便后续直接套用图像分类的成熟结构。第四步是训练集、验证集、测试集的划分。这里有个容易犯的错不能按样本随机划分必须按干扰参数来分层。我见过不少人直接把所有样本混合后随机切分结果同一个扫频速率参数的样本同时出现在训练集和测试集里测试集准确率虚高得离谱。正确做法是先确定一组参数范围用于测试确保测试集里的扫频速率、带宽占比、信噪比等参数不落在训练集的覆盖范围内这样才能真实评估模型的泛化能力。下面是数据生成的核心伪代码可以作为一个基线参考# 数据生成伪代码 for snr in range(-15, 16, 1): for jamm_type in [single_tone, sweep, barrage, partial_band, pulse, comb]: for sample_idx in range(samples_per_condition): sig generate_signal(modulationrandom.choice([qpsk, 16qam]), snrsnr) jam generate_jammer(typejamm_type, paramssample_random_params(jamm_type)) rx sig jam awgn(snr) tf_img stft(rx, window_len256, overlap0.75) save_sample(tf_img, jamm_type)我在实际项目里每种干扰类型生成5000到8000个样本总样本量大约4万张时频图这个规模对工业界项目够用不需要几十万级别的数据。关键是类型均衡和参数覆盖度而不是单纯堆数量。3. 模型选型实战从1D-CNN到跨窗口自注意力模型选型这个问题我见过两种极端做法。一种是上来就上很大的预训练模型不管三七二十一直接微调另一种是只敢用最简单的LeNet生怕模型复杂了跑不动。这两种都不对正确做法是从输入表示和干扰特征出发先定基线再逐步升级。3.1 选型的出发点先看输入再看干扰最后看算力我们的输入是时频图所以第一直觉是选图像分类模型这是合理的。但要额外考虑干扰识别的特殊性时频图和高清照片有本质区别它的语义是稀疏的大部分区域是噪声底只有少数区域有结构信息而且这些结构往往横跨很大的时间或频率范围。比如扫频干扰的斜线贯穿整张图如果模型只会看局部小块很容易把一段斜线误判成噪声。所以选型时要特别关注模型的感受野和全局建模能力。算力约束也必须提前想清楚。如果目标是部署到边缘设备上做实时监测参数量超过20M的模型基本不用考虑如果是在服务器上离线分析模型规模可以放宽。我们的目标平台是工控机加一张中端GPU推理时延要求小于50毫秒这个约束直接决定了后面所有的模型设计。3.2 几个基线模型的实际表现我按复杂度从低到高跑了几个模型做对比这里给出一个直观的结论。最简单的方案是1D-CNN直接吃IQ序列结构上就是三四层卷积加池化参数量只有几百万推理极快但在信噪比低于0dB时准确率掉得很厉害。换到2D-CNN吃时频图后准确率明显提升这也再次印证了时频图表示的优势。再把2D-CNN的卷积层加深到ResNet-18的规模高信噪比下能到97%左右但低信噪比下的提升比较有限说明单纯加深网络不能解决特征不够显著的问题——这个问题要靠扩大模型感知范围来解决。LSTM和GRU这类循环模型我也试过把时频图按时间轴切成帧序列送进去。效果中规中矩而且训练收敛慢、时序长度长了还容易遗忘前文信息后来就放弃了。3.3 跨窗口自注意力为什么它适合干扰识别这个项目里我认为最值得分享的模型设计是引入了跨窗口自注意力机制。先说动机。干扰信号有两个显著的特点一是局部强相关比如宽带阻塞干扰在相邻时间、相邻频率上能量分布连续二是全局有结构扫频干扰的斜线、跳频干扰的频点切换模式都需要整张图才能确认。CNN擅长提取局部特征但感受野有限要靠堆积层数才能扩大视野标准的全局自注意力能完美建模全局依赖但直接在224x224的时频图上做多头注意力计算复杂度太高工程上跑不起。跨窗口自注意力正好在两者之间取了一个平衡它的核心做法是先把时频图划分成若干个固定大小的窗口比如7x7的小patch窗口内部用卷积或轻量注意力提取局部模式这一步的计算复杂度低然后设计一个窗口间的注意力模块让每个窗口聚合周围窗口的信息从而建模局部细节全局上下文。通俗地讲模型先看每一小块区域里有什么纹理结构再把这些小块串起来理解整幅图的结构相当于既拿放大镜看细节又拿全景地图看全貌。我基于这个思路实现了一个轻量版结构过程如下Patch Embedding把时频图切成7x7的patch每个patch经过一个卷积层映射成64维向量做位置编码。局部特征提取在每个窗口内部做一个轻量的自注意力或两层卷积捕获窗口内的纹理关系。跨窗口自注意力把每个窗口的池化特征作为token在窗口之间做多头自注意力让模型能够建模扫频斜线、跳频轨迹这类跨窗口的全局模式。分类头取全局平均池化后的特征接一个全连接分类层。这个结构的一个关键设计点是注意力头对频率轴的关注权重更大因为干扰的类型特征主要体现在频率分布上。实现时我把注意力权重加了一个频率方向的偏置项实际效果是低信噪比下的准确率又提升了一截。这个改动不大但收益明显。3.4 实测对比不同模型方案的数据说话在我们的测试集上覆盖-10dB到15dB信噪比干扰参数与训练集有差异几个方案的对比结果如下模型方案输入表示参数量高信噪比准确率低信噪比准确率(≤2dB)单张推理时延(GPU)1D-CNNIQ序列0.8M89.2%71.5%3msResNet-18时频图11.2M97.4%84.3%8msLSTM时频图帧序列2.1M91.8%76.9%12ms跨窗口自注意力时频图6.5M98.1%90.6%9ms从结果能看出跨窗口自注意力方案的优势主要集中在低信噪比区域高信噪比下各模型差距不大。这也符合预期信噪比高的时候干扰特征非常明显简单模型就能搞定信噪比低的时候干扰特征被噪声淹没必须靠全局结构信息来辅助判断这正是跨窗口注意力发挥作用的地方。4. 训练与调参低信噪比下的性能天花板在哪模型结构定下来之后真正折磨人的是训练环节。我在这块踩了不少坑尤其是干扰类型不平衡和低信噪比下的过拟合问题下面逐个说。4.1 损失函数和样本不平衡处理最初跑基线时我用的是标准交叉熵损失结果发现模型对某些类型识别效果好对脉冲干扰和部分频带干扰的召回率很低。看了训练集分布才意识到某些干扰类型在真实场景里出现频率低仿真时如果不加注意样本数天然偏少。类别不平衡直接导致模型偏向学样本量大的类别。解决办法分两步。第一步是在数据层面做了有控制的过采样对类别少的干扰多生成样本但不过分放大避免过拟合。第二步是把损失函数换成Focal Loss核心思想是对容易分类的样本降低权重把训练重心引导到难分类的样本上。我在实际项目里用了gamma2、alpha按类别频率反比设置效果立竿见影脉冲干扰的召回率从78%提升到89%。另外推荐使用标签平滑label smoothing。干扰识别任务里有些样本本身就处在模糊边界比如单音干扰和多音干扰当多音干扰的频点靠得很近时两者在时频图上几乎不可区分。交叉熵损失会逼着模型输出一个概率分布全部压到某个类上这既容易过拟合又在推理时给出不可靠的高置信度。标签平滑给正确标签的概率设定一个上限比如0.9剩余概率在其余类别间均匀分布模型会学得更稳。4.2 数据增强让模型在低信噪比下撑住低信噪比下模型性能崩最大的原因是训练数据里的噪声形态太单一。我们用的AWGN噪声是高斯白噪声但真实接收机的底噪里还有干扰信号本身的泄漏、带外杂散以及各种不理想特性单一噪声会使模型学到噪声的固定模式而不是干扰的本质特征。我在训练阶段做了三类增强。第一类是信噪比扰动对每个样本随机对信号和噪声的功率比做微调等效于生成连续信噪比区间的数据。第二类是频偏模拟给信号叠加一个随机大小的中心频率偏移模拟接收机晶振误差或信道频偏。第三类是Mixup增强按一定比例把两个不同干扰类型的样本混合标签也按比例混合模型被迫关注更鲁棒的特征而不是某个强特征就下结论。这里有一条经验Mixup对干扰识别的效果比图像分类还好因为干扰信号在时频图上往往是稀疏的混合后两个干扰的结构同时存在模型需要学会同时识别多个模式这在多干扰叠加的真实场景里非常有价值。4.3 训练策略细节优化器我直接用AdamW初始学习率3e-4配合Cosine退火调度。批量大小64训练50到60个epoch。这个配置在多个数据集上都很稳不需要过多调整。有两件容易忽略但影响很大的事。第一件是验证集的选择标准。我在2.3里强调过测试集要和训练集参数分布不重叠验证集同样要做到这一点否则你拿验证集调的阈值和早停点在真实场景里全不适用。第二件是保存最优模型时要按验证集低信噪比区间的准确率来选而不是看整体准确率。因为高信噪比样本占多数整体准确率容易掩盖低信噪比上的缺陷而低信噪比才是真实场景最难的部分。4.4 评估体系别只盯着一个准确率数字评估一项必须做扎实否则模型效果好不好全靠感觉很难发现问题。我用了三套评估手段。第一是混淆矩阵能直观看出哪些干扰类型之间容易混淆。比如我们发现脉冲干扰容易和宽带阻塞混淆原因是一个高功率窄脉冲在STFT后的频率展开很宽形态上接近宽带阻塞。针对这个混淆我们专门增加了更多中等脉冲宽度的训练样本混淆率显著下降。第二是信噪比-准确率曲线按1dB间隔统计各信噪比下的分类准确率画成曲线。这个曲线能直接回答模型在什么样的底噪环境下还能用也给系统设计提供依据如果发现某个信噪比以下准确率跌破80%系统就要考虑先做干扰抑制或信号增强预处理而不是盲目相信模型的输出。第三是每类干扰的精确率和召回率。在干扰识别场景里漏警把干扰判为无干扰和虚警把正常信号判为干扰代价不一样具体怎么权衡取决于业务。我们在判决阈值上做了调整把正常信号和干扰的分类阈值往上调宁可多报疑似干扰让运维人员看一眼也不要漏报道致通信链路长时间被干扰。5. 部署与落地从仿真到真实频谱环境的三个大坑模型在实验室里跑得再漂亮部署到真实环境才是真正的考试。这个阶段我们踩了三个大坑每个都差点让项目翻车写出来给大家提个醒。5.1 坑一仿真数据和实测数据之间的域偏移第一次拿着训好的模型去外场测结果非常难看准确率直接掉到60%左右比实验室低了二十多个百分点。排查后发现问题出在域偏移上仿真的信号都是理想的实测环境里接收机底噪高、有杂散、信号有多径衰落、天线增益不平坦这些因素综合起来让时频图的数据分布和训练集差了一大截。解决域偏移问题我用了两个办法。第一个是在仿真阶段加更多信道模型不只用AWGN还要加上频率选择性衰落、多径时延扩展、接收机非线性失真等让训练数据更逼近真实。第二个是收集真实的底噪数据做数据增强外场采集一段没有主动干扰的底噪把它叠加到仿真信号上相当于用真实噪声环境微调了数据分布。这一步做完实测准确率回到了85%以上。5.2 坑二实时性和算力约束我们的监测设备要求1秒之内完成一次检测和识别也就是说模型推理时延必须低于200毫秒。实验室的GPU服务器当然没问题但边缘设备上跑的模型要同时考虑功耗和价格。我们把6.5M参数的跨窗口自注意力模型做了一次轻量化压缩包括通道剪枝和INT8量化参数量降到2.3M单张推理时延从9ms降到3ms准确率只掉了不到1个百分点。如果是在更低算力的嵌入式设备上建议用深度可分离卷积替换标准卷积再把自注意力头数减半。这类压缩对干扰识别任务损失很小因为干扰特征相对粗粒度不需要极精细的高频细节。部署框架上我们最终用了ONNX Runtime加TensorRT的混合方案。PyTorch训练好的模型先导出为ONNX再到目标平台上转成TensorRT的engine文件。坑在于ONNX的算子兼容性如果模型里用了自定义的注意力偏置操作导出前需要把它改写成标准算子否则TensorRT转换会失败。这个改写的工程量不大但一旦失败排查起来很费时间建议训练时就尽量避免自定义算子。5.3 坑三未知干扰和开放集问题现实里最让人头疼的不是模型对已知干扰分类错而是它遇到了一个完全没见过的干扰类型却硬把它错分到某个已知类别里还给出很高的置信度。有一次外场出现了从未见过的梳状谱干扰模型把它判成了多音干扰置信度高达0.98差点误导我们做出错误的频谱决策。这个问题本质上是开放集识别问题。我们最后采用的方案是双阈值机制模型输出各类别概率后同时计算一个不确定性度量当最大类别的置信度低于第一阈值或者样本在特征空间中离训练类别的中心都太远时拒绝分类并标记为未知干扰。这样至少能保证系统不会给出一个自信的错误结论。后续我们还规划了在线增量更新机制用人工确认后的未知干扰样本滚动微调模型让系统在部署环境中持续进化。5.4 系统架构与运维建议最后说下完整的部署架构供参考。实时信号流经过前端触发检测后截取一段时域数据送到推理模块做STFT变换和模型推理输出结果连同原始频谱截图一起推送到监控平台。数据库中记录每一次识别结果的时频图和置信度定期梳理错误案例导出后回到训练流程重新迭代模型。这个闭环跑通之后系统会越用越准。一个容易忽略的点是模型的版本管理。干扰识别的业务场景里数据分布会不断变化模型必须能够回滚到上一版本。我们把每次训练产生的模型文件、数据版本、评测结果全部用git管理新模型上线前必须经过离线评测集的回归测试确保在旧场景上的能力不退化才允许灰度上线。6. 落地项目里的几条实在建议项目收尾阶段分享几条纯经验层面的东西希望能帮你少走一点弯路。第一不要上来就追最新最复杂的网络结构。先拿ResNet-18或者RepVGG这类成熟模型跑通全流程确认数据、评估、部署链路没有问题时再换更复杂的结构去榨性能。很多项目其实卡在数据质量上和你用什么模型关系不大。我们最开始用ResNet-18就已经解决了80%的问题跨窗口自注意力带来的收益在于把准确率从90%推到96%但前提是前面的数据链路已经足够扎实。第二数据生成脚本一定要做成可配置、可复现的。干扰参数、信噪比范围、随机种子全部用配置文件管理而不是散落在代码里。这个项目里我至少改了七八次数据生成策略每次改完都能用git回溯到之前的数据版本否则实验对比全是糊涂账。第三做这种识别类项目建议从一开始就同时维护两份测试集一份仿真测试集一份实测标注集。仿真测试集用来快速迭代模型实测标注集只在关键节点用防止把模型调到对仿真数据过拟合。定期在实测标注集上验证你才能知道自己离真实场景还有多远。第四也是最实际的一点给自己留缓冲时间。干扰识别模型的调优周期通常比预期长一倍尤其是各种域偏移和边界情况的处理非常耗费时间。技术方案再好也需要一个能支撑迭代的系统工程框架这是整个项目里性价比最高的一笔投入。
返回列表