简介:这是一份面向无线通信与机器学习交叉研究的轻量级代码工程,围绕 SCMA(稀疏码分多址)技术设计,适合通信工程、信号处理或深度学习方向的学生与研究者用于理解非正交多址接入及机器学习在物理层优化中的应用。压缩包共 9 个文件,核心为 6 个 MATLAB 脚本,分别覆盖码本生成、SCMA 编码、译码/解调、四二映射等关键流程,另附带 1 个 s 类型源文件、1 份 LICENSE 和 1 个 Markdown 说明文档;包体仅 6KB,结构紧凑,便于逐模块阅读和快速复现。该示例已有 226 人学习,对刚接触 SCMA 或想尝试 ML 辅助通信算法的人有直接参考价值。通过阅读代码与说明,学习者可以快速搭建一套 SCMA 收发链路仿真流程,理解码本与映射关系,也可在此框架上继续改进检测算法、引入机器学习模型以比较误码率或频谱效率变化。
1. 一个把SCMA从数学公式推成可执行工程的代码库
做无线物理层的人应该都有这种体会:SCMA相关的公开代码,绝大多数只给了稀疏扩频矩阵和消息传递算法(MPA)的仿真,想加一点学习类的改进,得自己从矩阵构造开始重写。SCMA-ML-master这个仓库正好补上这段空缺,它完整实现了从编码、叠层映射到四种检测算法的整条链路,其中ScmaDeML模块用梯度下降直接更新多用户码本和恢复矩阵,属于把机器学习思路落进物理层处理的典型做法。读完代码你会发现,所谓"ML"不是套个神经网络,而是在传统迭代检测框架里嵌入可学习的参数更新。对想跑通SCMA链路、又想在检测部分做学习类改进的研究生和工程师来说,这个工程很值得拆一遍。
2. SCMA链路是怎么串起来的:从CQI矩阵到多用户映射
2.1 传播模型文件里藏着系统设定的关键参数
channel.m是整条链路的起点,它定义了SCMA系统最基础的物理层参数。这个文件里最常见的设定是2个用户共用4个子载波、每个资源块上叠加两个用户信号,过载率150%。这里的核心数据结构是CQI信道质量指示矩阵,维度是子载波数乘用户数,表示每个子载波上每个用户的信道增益。这个矩阵的生成通常服从复高斯分布,再按用户位置做路径损耗修正,是后续所有检测算法都要引用的基础输入。需要留意的是,不同论文里对CQI矩阵的归一化方式差别很大,直接决定检测器输入信号的幅度范围,换数据集时必须统一重算。
2.2 编码与映射:four2two、scmaEncode、two2four一整套函数的设计思路
这组函数构成了发射端的完整流程。scmaEncode.m负责把二进制比特流映射到码本索引,four2two.m和two2four.m则是用户数据流和子载波符号之间的桥接。它们的核心逻辑可以拆成三步:
% 伪代码:SCMA发射端数据流 bits = randi([0 1], nBits, 1); % 生成随机比特 codedBits = encoder(bits); % 编码:four2two做比特-符号映射 symbols = codebook(:, codedBits); % 按索引查码本,得到发射符号 txSignal = reshape(symbols, nSubcarriers, nUsers); % two2four:整理成子载波×用户矩阵参数说明:nBits是每帧比特数,codebook是码本矩阵,每列对应一个用户的一个符号状态。four2two看名字也能猜出七成——把4维的比特组合压缩成2维的调制符号,用户数据在码域上稀疏叠加。two2four是它的逆过程,在接收端把解调后的符号恢复成比特序列。这样设计的好处是发射端和接收端共用同一套映射规则,后续换调制阶数时只需改这两个函数的映射表,不动主循环。
2.3 为什么是scmaDeML而不是MPA:一次迭代就是一次梯度下降
scmaDeML.m是整个仓库的价值所在。传统检测用MPA迭代交换外信息,复杂度随码本大小和用户数指数增长;这里的思路是把多用户检测建模成一个可微的优化问题,让用户码本和接收端的恢复矩阵共同参与梯度更新。每次迭代等价于在损失函数上走一步梯度下降,而这个损失函数就是当前检测符号与接收信号之间的均方误差。换句话说,MPA是在固定码本下做概率推理,scmaDeML是在干扰环境下做参数学习——两者都能逼近MAP检测,但后者天然兼容数据驱动改进。
3. 跑通主程序run_SCMA_ML:参数怎么设、曲线怎么看
3.1 主程序里需要先改的三个参数
run_SCMA_ML.m是入口脚本,但直接跑会遇到一堆维度不匹配问题。我第一次跑的时候在snr和nUsers上卡了半小时,原因是这两个参数要跟channel.m里的CQI矩阵维度严格对应。实操时先改这三处:
% run_SCMA_ML.m 参数区 snr = 0:2:14; % 信噪比扫描范围,单位dB nUsers = 2; % 用户数,必须与channel.m中的CQI矩阵列数一致 nSubcarriers = 4; % 子载波数,必须与CQI矩阵行数一致 nFrames = 10000; % 每信噪比点仿真帧数,调大曲线更平滑参数说明:snr定义横轴范围,0到14dB是SCMA仿真最常用的区间,低于0dB时四种检测器性能几乎重叠,高于14dB时ML检测的增益开始收敛;nFrames影响误码率曲线的置信度,追求速度时可降到1000,学术出图建议不低于5000。
3.2 接收端检测器实测对比:什么时候改用ML
主程序里依次对比了四种检测算法,其中传统接收端用scmaDetect.m里的MPA实现,而scmaDeML.m提供了一套完整的学习式检测链路。ML检测需要先进行码本预训练,训练数据就是发射端的符号序列和对应的接收信号,用梯度下降更新码本。实测下来,在2用户4子载波的配置下,两者对比如下:
| 检测方式 | 每帧平均迭代次数 | 相对复杂度 | 低信噪比增益 | 适用场景 |
|---|---|---|---|---|
| MPA | 6-10次因子图迭代 | 基准 | 无 | 实时性要求高的终端 |
| scmaDeML | 20-30次梯度下降 | 约3-5倍 | 比MPA低约1dB | 基站侧、离线训练场景 |
| 完整ML流程 | 需要预训练阶段 | 更高 | 明显优于MPA | 信道变化慢的场景 |
这里有个容易被忽视的细节:ML检测的增益主要来自对码本的在线微调。信道变化较快时,预训练得到的码本会失配,此时增加训练帧数比增大信噪比更有效。如果发现误码率曲线在中高信噪比出现平台期,优先检查码本是否收敛,而不是怀疑算法本身。
3.3 从README还原实验设计:哪些结果可以直接复现
README里没有承诺任何现成的性能图,但给了完整的文件依赖关系。我按run_SCMA_ML.m的调用顺序梳理过,整个工程是一条无外部依赖的纯MATLAB链路:channel生成信道 → scmaEncode发射 → 过高斯白噪声 → scmaDeML检测 → 算误码率。这意味着只要装好MATLAB就能直接复现,不需要额外的通信工具箱。复现时建议先用nFrames=1000跑通流程,确认无误码率曲线输出后再加大帧数做正式实验。如果出现维度错误,大多是two2four.m的输出没有按用户数重新整形,检查reshape时行数是否等于子载波数。
4. 四种检测算法并存:边界条件与工程排错
4.1 正交匹配追踪在稀疏检测里的角色
仓库把正交匹配追踪、消息传递和梯度学习放在同一张对比表里,并非只是凑数。在SCMA这种过载系统里,接收信号是多个用户稀疏符号的线性叠加,正交匹配追踪这类压缩感知算法天然适应这种结构。它的迭代过程是:先找与残差相关性最强的用户,再估计其符号并更新残差,重复直到满足稀疏度约束。在scmaOMP.m里实现时,有一个关键参数是稀疏度,即激活用户数——误设稀疏度会导致两种典型失败:稀疏度设大了,会把噪声分量当成有效信号;设小了,会漏检用户。调试时如果发现误码率曲线上翘,先检查这一步。
4.2 码本失配、收敛慢、维度不匹配:三个高频报错的排查路径
用这个仓库做二次开发时,我总结出三个最常踩的坑。第一个是码本失配:codebook.m生成的码本和run_SCMA_ML.m里传入的码本维度不一致,报错信息通常是Matrix dimensions must agree,排查时在scmaEncode.m入口加size断言即可。第二个是ML检测收敛慢:梯度下降的学习率在scmaDeML.m里默认值偏保守,信道条件好时会出现loss降得很慢,把学习率从0.01调到0.05能明显加快收敛,但调过头会导致loss震荡。第三个是信道矩阵不匹配:channel.m里的CQI矩阵如果忘了转置,检测端拿到的信道状态信息就是错的,表现是所有算法的误码率都比理论值高一个数量级,而且曲线之间没有区分度。
4.3 把ML检测换成支持向量机分类视角的做法
仓库的ML实现是梯度下降,但如果想验证"分类器能否直接做SCMA检测",可以做一个替换实验:把每个接收符号向量当成特征,把对应的联合用户符号当作标签,训练一个多分类器。特征维度等于子载波数乘以复数维度(一般是8维实向量),标签数等于码本状态数的乘积。这个改造在scmaDeML.m的基础上改动不大,主要把梯度更新换成分类器训练即可。注意支持向量机在高维稀疏特征上的泛化能力有限,用户数超过4个后性能会明显下降,这恰好反过来说明梯度方式在SCMA场景的适用边界。
# 检查MATLAB脚本依赖关系的命令行技巧 grep -oE "[a-zA-Z_]+\.[mM]" run_SCMA_ML.m | sort -u # 输出示例:channel.m codebook.m scmaDeML.m scmaEncode.m scmaDetect.m two2four.m four2two.m这条命令用于快速理清入口脚本的调用关系,避免漏复制函数文件。grep -oE提取所有.m后缀的引用,sort -u去重后得到完整的依赖清单。部署到其他机器时,对照这份清单拷贝文件即可保证运行环境完整。
5. 一份可以拿去做对照实验的检测性能清单
拿这个仓库做毕业论文或小论文的基线,我建议把代码、运行条件和结果整理成下面这类可复现清单,省去二轮补实验的麻烦。
# 环境信息:MATLAB R2023a及以上,无需额外工具箱 # 核心脚本:run_SCMA_ML.m(主入口)、channel.m(信道生成)、scmaDeML.m(ML检测) # 运行命令:直接运行 run_SCMA_ML,等待误码率曲线打印我的做法是:先在2用户4子载波配置下跑完四种检测器,记录各方法的误码率曲线和每帧耗时,再在4用户6子载波的过载配置下重复一次,对比ML检测的增益变化。多数情况下,低载配置下MPA和ML差距不大,高载配置下ML的误码率优势会拉到1到2个dB。如果只想验证仓库本身可用,把nFrames减到500,确认scmaDeML的误码率能随信噪比单调下降即可。扩展实验时,建议在channel.m里添加一个莱斯信道分支,用同一套检测器对比高斯信道和莱斯信道下的性能差,这是审稿人常问的问题。修改channel.m时记得同步更新run_SCMA_ML.m里的信道参数数组,避免信道模型与检测器输入不一致。更进一步的技巧是用tic/toc统计四种检测器的单帧执行时间,做成复杂度对比表,这个仓库的代码本身就支持,不需要额外改动,直接在主循环外包一层计时即可。若你要把ML检测结果写入日志,用dlmwrite在循环内追加输出即可。运行完成后对照误码率曲线,确认ML检测没有在高信噪比区出现错误平层,就说明整个工程已经跑通。
本文还有配套的精品资源,点击获取