
简介面向无线通信与深度学习交叉领域研究者的自动调制识别项目聚焦5G/6G中OFDM与OTFS调制信号的分类任务。资源提供了CNN与Transformer两种主流特征提取网络并包含高斯信道下OFDM六种调制方式BPSK至256QAM的大规模仿真数据集生成脚本覆盖-10dB到20dB宽信噪比范围可支撑调制识别模型的训练、验证与对比分析。压缩包共7个文件以Python脚本为主模型、数据集、训练工具配合说明文档整体仅11KB代码结构清晰易于二次开发。已有659人学习下载。读者可基于这些脚本快速构建完整实验流程包括数据生成、模型搭建、训练与评估尤其适合电力、通信等方向本科高年级或研究生作为入门深度调制识别的实战参考。1. 项目概述与整体设计思路1.1 自动调制识别到底在解决什么问题平时我们接收一段无线信号如果对方用的是调频广播解调时直接走FM鉴频如果是Wi-Fi或者4G/5G解调链路是协议栈定好的。但有一种场景比较特殊——非合作通信。你收到一段信号不知道对方用了什么调制方式可能是QPSK可能是16QAM也可能是别的这时候就需要自动调制识别Automatic Modulation Recognition, AMR来当“第一道工序”先把调制类型认出来后续才能选择合适的解调方式。这个需求在频谱监测、认知无线电、电磁频谱管理、无线电爱好者的信号分析工具里都很常见。比如我在做频谱监管类项目时经常需要扫描一段频段找到异常信号后先判断它是模拟调制还是数字调制是窄带还是宽带再决定下一步怎么处理。传统做法是靠专家特征加分类器比如提取高阶累积量、循环平稳特征再喂给SVM或者决策树。这类方法在信噪比高的时候效果还行但一旦信号淹没在噪声里或者多径衰落严重手工特征就很难稳定工作了。1.2 为什么选择深度学习路线深度学习方案的核心思路是让网络直接从原始IQ采样数据里学习特征省去人工设计特征的过程。I路和Q路信号本质上就是复数的实部和虚部深度学习可以把它们当作两通道的时序数据来建模也可以把128个IQ样本重排成二维图用图像分类的思路来做。这一点在行业里已经被OShea等人2016年的工作验证过了——他们发布的RML2016.10a数据集几乎成了这个方向的标配基准。我的直观感受是CNN类模型在高信噪比下能做到接近完美在中等信噪比下明显优于传统特征方法。而且深度模型的泛化能力更强换个频段、换套信道条件传统特征工程可能需要重新调参深度学习模型稍微做点数据增强就能扛住。当然也不是无脑上深度学习。这个任务有个特殊性调制识别的类别之间存在天然混淆比如16QAM和32QAM在高阶QAM家族里星座点接近AM-DSB和AM-SSB也容易误判。传统方法可以通过域知识刻意设计区分特征而纯数据驱动的模型需要足够多的样本才能学会这些细微差异。所以整个项目的关键不在“模型多复杂”而在数据、增强策略和评估方式是否对路。1.3 技术栈与数据集选型我用的技术栈是Python加PyTorch数据处理依赖NumPy和SciPy可视化用Matplotlib。选PyTorch而不是TensorFlow主要是调试方便torchinfo可以直观看到每层输出尺寸和参数量对网络结构设计阶段很有帮助。如果你习惯TensorFlow/Keras完全没问题的这个任务对框架没有特殊要求。数据方面首选还是公开的RML2016.10a数据集。它包含11种调制方式8种数字调制BPSK、QPSK、8PSK、CPFSK、PAM4、16QAM、32QAM、GFSK和3种模拟调制AM-DSB、AM-SSB、WBFM信噪比从-20dB到30dB步进2dB共26个信噪比档位。每个样本是128个复数采样点根因上是用GNU Radio仿真生成的真实波形带一定的信道损伤和频偏比纯理想AWGN仿真更接近实际。建议如果你是第一次做这个方向不要急着自己搭仿真平台生成信号先用公开数据集把流程跑通再去扩展定制数据集。2. 数据准备与预处理要点2.1 理解IQ数据的结构RML2016.10a的样本在读取时是一个2, 128的数组第一行是I路同相分量第二行是Q路正交分量本质上是完整复数信号的实部和虚部。你在预处理阶段要做的事就是把这种原生表示转换成网络方便学习的格式。我见过不少人第一次拿到数据时试图把IQ数据转成频谱图或者星座图再送进网络这其实是绕了远路。深度学习模型最大的优势就是能从原始数据中直接学习特征。我实测下来的结论是直接输入归一化后的IQ序列效果不输给任何花哨的变换而且少了很多工程复杂度。数据读取之后的第一件事是检查样本统计特性。这个数据集的信号在仿真时已经做过归一化但在自己的采集场景中不同接收机增益会导致幅度差异很大。我的习惯是做一个全局的幅度归一化把训练集中所有样本的IQ分量合并计算标准差然后所有样本除以这个标量。注意一定不能逐个样本归一化那样会把信号的绝对幅度信息全部抹掉——而幅度里恰恰含有调制类型的线索比如PAM4和QPSK的平均幅度就有区别。2.2 数据增强的工程实现数据增强是这个项目里收益最高的技巧之一。IQ信号本身有复数域的对称性所以可以对原始样本做以下几种变换而不改变调制类别IQ交换把I路和Q路互换等价于对信号做共轭星座图沿实轴翻转。符号翻转对I路或Q路取负等价于星座图沿虚轴或实轴翻转。两者组合产生4种等价变换。但要注意任意角度的旋转不能随便做。QPSK转90度之后还是QPSK只是相位基准变了但8PSK如果转了22.5度类别其实没变但判决边界变了模型反而可能学歪。我在实验中只在训练集上使用IQ交换和符号翻转测试集保持原样。另外还有一个非常实用的增强方向加轻微噪声和频偏。在仿真数据集上可以再叠加高斯噪声来模拟更低信噪比的情况但我建议在数据集本身信噪比档位够多的情况下就不用画蛇添足了重点还是把已有的每个信噪比档位的样本用好。2.3 数据划分与防止数据泄漏数据泄漏是这类项目最经典的坑。如果你先做了数据增强再把增强后的数据划分成训练集和验证集那么同一条原始样本和它的变换副本会同时出现在两个集合里验证集就形同虚设了。正确流程是先把原始数据按样本随机划分为训练集和验证集我常用8:2然后再只在训练集上做数据增强和归一化参数计算。验证集保持原始形态只做同一种归一化处理。RML2016.10a一共约22万条样本每个信噪比档位大约2000条按8:2划分后训练集约17.6万条增强4倍后约70万条这个量级对训练一个中小型CNN完全够用。3. 模型构建与训练实战3.1 基准模型选哪个更靠谱在模型选型上这个任务有几条成熟路线一维CNN直接处理IQ时序、二维CNN把IQ排列成图像、LSTM/GRU按时间步建模、CNN加BiLSTM混合模型。我最推荐的入门基线是“一维CNN加全连接分类头”别上来就搞很深的网络。原因有三个第一128个采样点的序列长度不算长深层网络容易过拟合不如浅层网络加适当宽度来得实在第二信号调制模式本质上是局部波形特征和相位跳变模式一维卷积核天然匹配这种特征提取需求第三训练速度快可以在几分钟内跑完一个实验方便快速迭代。如果你想让模型更强一点可以换成残差结构或者加一个注意力模块。但我实测下来在RML2016.10a这个数据集上一个轻量级CNN加BiLSTM的混合模型已经能取得非常接近SOTA的效果而参数量只有主流大模型的十分之一不到。对于实际部署来说简单模型带来的推理延迟优势非常明显。3.2 网络结构设计与参数量控制下面这个结构是我反复调试后比较稳定的一个轻量级基线直接用PyTorch实现import torch.nn as nn class LightAMRCNN(nn.Module): def __init__(self, num_classes11, num_snr26): super().__init__() self.features nn.Sequential( nn.Conv1d(2, 64, kernel_size3, padding1), nn.BatchNorm1d(64), nn.ReLU(inplaceTrue), nn.MaxPool1d(2), # 128 - 64 nn.Conv1d(64, 128, kernel_size3, padding1), nn.BatchNorm1d(128), nn.ReLU(inplaceTrue), nn.MaxPool1d(2), # 64 - 32 nn.Conv1d(128, 256, kernel_size3, padding1), nn.BatchNorm1d(256), nn.ReLU(inplaceTrue), nn.AdaptiveAvgPool1d(1), # 32 - 1 ) self.head nn.Sequential( nn.Flatten(), nn.Linear(256, 128), nn.ReLU(inplaceTrue), nn.Dropout(0.5), nn.Linear(128, num_classes) ) def forward(self, x): return self.head(self.features(x))这个模型把输入当作2, 128的一维时序2对应IQ两路128是采样点数。第一层卷积核大小为3相当于在时间维度上滑动提取相邻采样点之间的相位、幅度变化模式。三层卷积逐步从64个通道增加到256个通道最后一层用自适应平均池化把整个序列压缩成一个256维的向量再接全连接层分类。参数量算下来只有约32万每个样本推理在CPU上也是毫秒级。BatchNorm层在这个任务里很重要因为IQ信号的分布受信噪比影响较大BatchNorm可以显著稳定训练过程。Dropout放在全连接层因为全连接层的参数量占大头最容易过拟合。3.3 训练策略与调参经验训练参数我习惯这样设置优化器Adam初始学习率0.001批次大小256损失函数交叉熵学习率调度ReduceLROnPlateaupatience5factor0.5训练轮数30轮左右配合早停一个关键心得是学习率不能太大。这个任务的类别数量不多但类别间相似度很高学习率过大会让模型在训练初期就陷入误区把相似的调制类型混在一起。如果发现训练Loss下降很快但验证准确率上不去多半是学习率问题调低0.0003再试。数据加载器部分我习惯把信噪比标签也传给损失函数做加权但实际训练时发现RML2016.10a每个SNR下的样本量是均衡的所以直接用普通的交叉熵就够了。如果你在自采数据集上训练各类别样本量可能差异很大建议加上类别权重。4. 实验评估与问题排查实录4.1 用混淆矩阵看模型“怎么错”训练完成后光看整体准确率是不够的。必须画混淆矩阵尤其是按信噪比分组统计的混淆矩阵。我跑完基线模型后测试集整体准确率大约在92%左右。但看混淆矩阵就发现了很多细节AM-DSB和AM-SSB之间误判率很高原因是仿真中SSB信号经过滤波后其实保留了部分对边带残迹模型很难区分。QPSK和8PSK在中低信噪比下容易混淆两者都是相位调制区别只在相位跳变粒度。16QAM和32QAM在2dB以下容易误判星座点密集时噪声会把边缘点“推”到相邻位置。这个分析告诉我们与其盲目堆模型复杂度不如针对混淆严重的类别做定向数据增强。比如对AM-DSB样本做额外的SSB滤波变换或者对QPSK/8PSK样本做小角度相位扰动往往能带来实实在在的准确率提升。4.2 信噪比维度上的表现分析另外一个比较重要的评估维度是按SNR统计准确率。RML2016.10a里信噪比从-20dB到30dB我会在测试时按每个SNR档位计算准确率然后画一条“SNR-准确率曲线”。同样的模型在10dB以上准确率基本是99%以上在0dB附近掉到80%左右-10dB以下基本就只有30%-40%接近瞎猜。这个现象整体符合预期因为信噪比越低信号特征被噪声覆盖得越严重。但要注意的是如果模型在-20dB到-10dB区间的准确率明显高于理论水平要警惕是否发生了数据泄漏或者模型学到了某些和信噪比无关的伪特征。我在实际项目中还遇到过一种情况模型在低信噪比下对特定类别出现“系统性偏好”比如几乎所有样本都被预测成WBFM。排查后发现是训练集里WBFM样本的平均幅度略高于其他类别模型学会了“按幅度猜”。这个问题在自采数据里更容易出现解决方法是做更严谨的幅度归一化或者用对抗验证的方法检查训练集和测试集分布差异。4.3 部署落地要考虑的工程问题模型在实验环境里跑通只是第一步实际部署时还有几个工程细节值得注意。第一个是推理输入的格式兼容。如果接收机输出的是复数数据需要先拆成I/Q两路再转成浮点张量这一步的耗时很容易被忽略但在高吞吐场景下反而可能是瓶颈。建议用NumPy的向量化操作一次性处理一批数据不要用Python循环逐样本转换。第二个是模型量化和压缩。这个轻量模型参数只有32万直接部署完全没有问题。如果要在嵌入式设备上跑可以考虑PyTorch的torch.quantization转成INT8实测精度损失在1-2个百分点以内但推理速度能提升3到5倍。第三个是类别映射的维护。实际业务中你不需要识别所有11种调制方式可能只需要区分“跳频信号”“定频信号”“扩频信号”三大类那就需要自定义输出类别和对应关系。我建议把类别列表写在配置文件中不要写死在代码里方便后面扩展。4.4 典型故障排查速查表症状可能原因排查思路训练Loss不下降学习率过高 / 数据归一化错误调低学习率到0.0003检查是否逐样本归一化了验证准确率远低于训练数据泄漏 / 过拟合检查增强是否只用于训练集适当增加Dropout低信噪比下模型“过于聪明”归一化参数泄漏确认归一化参数只从训练集计算某个类别准确率异常低类别样本不均 / 特征混淆查看混淆矩阵针对该类别做额外增强推理速度不达标模型过大 / 预处理瓶颈先减通道数再考虑量化最后检查数据处理写在最后的实操体会自己动手做这个项目最有价值的收获不是最终把准确率刷到了多少而是理解了一个道理深度学习不是“把数据扔进黑盒”而是要在数据准备、特征分布、评估方式上花大量心思。我一开始也踩过“模型结构越复杂效果越好”的误区换了好几种大模型后效果还不如轻量CNN加合理的数据增强。后来想明白了调制识别的核心是先弄懂信号本身的物理结构和混淆机理再让网络去拟合。最后再分享一个小技巧训练过程中把每个SNR档位的验证准确率周期性打印出来而不是只看总准确率。这个方法能在早期就发现模型是否对某些信噪比区间有系统性失效省去很多盲目调参的时间。这个项目后续如果要扩展可以往两个方向走一是加入更多调制类型和真实信道数据让模型更贴近实战二是尝试半监督或者自监督预训练把大量无标注的采集数据利用起来。这两个方向我都试了一部分后面有机会再展开细聊。本文还有配套的精品资源点击获取