ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

基于Q-learning的水声通信自适应调制仿真与MATLAB实现

基于Q-learning的水声通信自适应调制仿真与MATLAB实现 我最近在调一套水声通信物理层仿真的时候被固定调制方式坑得很惨信道信噪比从18dB掉到6dB只用了不到两秒固定用16QAM误码率直接爆炸用BPSK又白白浪费大半带宽。后来我把Q-learning强化学习接进去让发送端根据信道状态实时决定调制方式MATLAB里跑通之后效果非常明显。这篇文章就把整套基于Q-learning的水声通信自适应调制仿真思路、代码框架和调参经验完整写出来给正在做水声通信、自适应传输或者算法仿真验证的朋友一个可直接参考的起点。这套仿真的核心逻辑并不复杂把信道环境看成一个马尔可夫决策过程Q-learning智能体通过不断试错学习“在什么信道状态下选择什么调制方式”的最优策略。真正让人头大的反而不是强化学习本身而是状态空间怎么离散化、奖励函数怎么设计、水声信道怎么在MATLAB里建模这几个衔接问题。下面我按照从问题到实现的顺序逐步拆解。1. 水声信道的“变脸”特性固定调制方案在水下为什么行不通在做自适应调制之前先得搞清楚一个基础问题水声信道和平时做的无线电信道到底差在哪为什么固定调制在水下场景特别吃亏。只有把这个问题想透了后面设计状态空间和动作空间时才有依据不至于把无线电信道那套经验直接搬过来用。1.1 水声信道与无线电信道的三个本质差异水声通信的传播媒介是海水声波在水下的传播特性和电磁波在自由空间的传播特性完全是两回事。我这里总结了几个对调制方式选择影响最大的差异点。第一个是时变性强得离谱。海面波浪起伏、海流涌动、收发节点之间的相对运动都会造成多普勒扩展信道冲激响应在毫秒级到秒级的时间尺度上持续变化。无线电信道虽然也时变但大多数场景下相干时间比数据帧长得多水声信道却经常出现“这个帧传完信道已经完全变样”的情况。第二个是多径效应特别严重。声波在海面、海底之间反复反射到达接收端的信号是多个不同时延、不同增益路径的叠加时延扩展可以达到几十甚至上百毫秒。这个数值比无线电信道大好几个数量级直接导致频率选择性衰落非常明显符号间干扰ISI极其严重。第三个是可用带宽极窄。水声通信的可用频段通常在几kHz到几十kHz之间载波频率低带宽受限严重。这意味着频谱效率极其宝贵不能像无线通信那样靠宽带换取性能冗余必须把每个符号的传输效率压榨到极致。1.2 固定调制的两难困境固定调制方式本质上是在“吞吐量”和“可靠性”之间做了静态妥协。你固定用QPSK信道好的时候明明可以上16QAM提升一倍吞吐量却用不上信道差到4dB的时候QPSK的误码率又会飙升到无法接受的程度。我在仿真里做过一个很直观的对比同样的水声信道参数下固定BPSK在高信噪比时有效吞吐量只有自适应方案的40%左右固定16QAM则在信道恶化时误码率比目标值高出两三个数量级。这种“要么浪费信道、要么丢失数据”的困境根源在于调制阶数一旦定下来就不会随信道变化而改变。水声信道还有一个很关键的特征信道状态在时间上有明显的连续性。上一秒的信噪比高下一秒大概率也不会突然掉到谷底上一秒多径严重下一秒也会维持类似的环境特征。这种时间相关性正好是强化学习这类序列决策方法发挥优势的舞台因为智能体可以根据历史状态的变化趋势提前做出调制切换的预判而不是等信道已经恶化了才被动反应。2. 把调制选择问题重写成Q-learning能处理的马尔可夫决策框架Q-learning本身解决的是一个离散时间、离散状态、离散动作的序贯决策问题。要把“水声通信自适应调制”这个物理问题塞进Q-learning的框架里关键是把三个东西设计清楚状态空间怎么定义、动作空间怎么定义、奖励函数怎么定义。这一步做错了后面全是白搭比调参重要得多。2.1 状态空间设计信道状态怎么“数字化”给智能体状态是智能体做决策的全部依据。在水声通信接收端最容易获得的信道质量指标是瞬时信噪比SNR估计这是反映信道当前好坏最直接的观测量。如果接收端做了信道估计还可以把信道估计的归一化均方误差NMSE或者时延扩展特征加入状态让智能体“感知”到更丰富的信道环境信息。不过在Q-learning的经典表格实现里有一个硬性约束状态必须是离散且有限的。连续变化的SNR值没法直接用来查Q-table必须先做离散化映射。我的做法是把仿真关心的SNR范围划分为若干档位每个档位对应一个状态编号。比如把0到30dB分成15个状态每个状态代表2dB的SNR区间。这里要特别注意边界处理。SNR低于最低门限或者高于最高门限时状态编号要钳位到边界值否则查表会越界。这个细节看起来不起眼但实际跑仿真时SNR剧烈波动很容易触发越界错误后面我会专门说这个坑。2.2 动作空间设计候选调制方式集合怎么定动作空间就是智能体每个时隙能选的调制方式集合。我用的候选集合是{BPSK, QPSK, 8PSK, 16QAM}这四种阶数从低到高排序。选择这四个的原因是它们在水声通信里都有实际应用场景BPSK和QPSK鲁棒性好适合低信噪比8PSK和16QAM频谱效率高适合信道质量好的时候。动作空间的粒度需要斟酌。只放BPSK和QPSK两种切换太粗糙中间有不少信道状态下两种都不够优加64QAM也不太合适因为水声信道带宽窄、整体信噪比普遍偏低64QAM在绝大多数情况下都用不上只会拖慢学习速度。四个动作是一个在仿真复杂度和策略精细度之间的较好平衡点。顺带说一下动作的排序有讲究。Q-learning在探索阶段会随机尝试各种动作如果把动作顺序打乱虽然不影响最终收敛结果但会让训练曲线看起来更乱不方便观察学习过程。我建议按调制阶数从低到高固定编号这样后期分析Q-table的时候一目了然。2.3 奖励函数吞吐量、误码率和切换开销怎么权衡奖励函数是整个Q-learning设计里最需要动脑筋的部分因为智能体学到的策略好坏完全由奖励塑造。如果奖励设计不当智能体学出来的策略可能看起来奖励很高实际通信性能却很拉胯。我采用的奖励形式是一个加权组合核心公式如下reward throughput_eff - lambda * ber_penalty - tau * switching_penalty其中throughput_eff是当前调制方式对应的归一化频谱效率BPSK为1QPSK为28PSK为316QAM为4这个数值直接反映选择高阶调制的收益。ber_penalty是误码率惩罚项如果实测误码率超过目标门限比如10^-3就产生一个较大的负惩罚数值上可以让误码率超标量乘以一个放大系数。switching_penalty是切换惩罚项如果当前动作和上一时隙动作不一致就给予一个小幅负惩罚目的是抑制频繁切换调制方式带来的系统开销。lambda和tau两个权重系数需要手工调整。lambda取大了智能体会过度保守死守低阶调制取小了误码率会超限。tau的作用相对次要但也不能设为0否则智能体会在每个时隙之间来回切换实际系统里频繁切换调制方式的信令开销和同步负担是很重的。我在仿真里采用的初值是lambda2、tau0.1后面会根据结果微调具体调节方法在后面有专门的调试章节。3. MATLAB仿真框架水声信道建模与Q-learning交互回环框架搭建是整个仿真的地基。Q-learning算法本身只有十几行核心代码真正复杂的是把水声信道模型、通信收发流程和强化学习训练循环在MATLAB里组织成一个完整可跑的仿真系统。我这里的做法不是去调完整的Bellhop射线模型因为算法验证阶段更重要的是快速迭代和观察规律参数化信道模型反而更灵活。3.1 水声信道的参数化仿真模型水声信道最显著的特征是多径。我的仿真里构建了一个包含直射路径加若干反射路径的信道脉冲响应模型每条路径有独立的时延和增益路径增益随时间按一定规律随机缓慢变化。这样既保留了多径信道最核心的物理特征又不需要调用复杂的工具箱就能在MATLAB里快速跑起来。信噪比的变化我采用了分段式的仿真方式信道状态在某段时间内保持平稳然后跳变到另一个状态模拟水声信道“相对平稳突发恶化”的变化特点。这样更容易观察Q-learning智能体对信道突变的响应行为也对训练收敛更有利。如果让SNR每个时隙都随机跳变智能体几乎学不到任何有效的时序规律。噪声模型方面接收端叠加高斯白噪声是起步阶段最合理的选择。虽然水声信道还有环境噪声、船舶噪声等有色噪声成分但算法验证阶段先用AWGN把自适应调制的核心逻辑验证清楚再逐步替换更复杂的噪声模型这是比较稳妥的技术路径。3.2 Q-learning主循环每个时隙发生了什么整个仿真主循环按离散时隙进行每个时隙代表一次完整的“决策-传输-反馈-学习”周期。我把流程拆成六个步骤接收端根据当前帧的信道估计结果计算状态特征当前SNR等并映射为离散状态编号。发送端根据状态编号和当前Q-table采用ε-greedy策略选择调制方式。发送端生成数据帧并调制经过多径信道传输。接收端完成信道估计、解调和误码率统计。根据实际误码率和是否切换调制方式计算奖励值。观察下一个时隙的信道状态用Q-learning更新公式更新Q值。这个闭环结构是强化学习应用于实际系统的标准形式。要特别强调的是状态转移是环境自然发生的智能体无法控制——发送端能做的只是根据当前观测选择动作然后从结果反馈中不断修正自己的策略。3.3 Q-table更新公式最核心的那一行代码Q-learning的更新公式非常简洁就是这一行Q(s,a) Q(s,a) alpha * [r gamma * max(Q(s,a)) - Q(s,a)]这个公式的含义值得仔细理解。中括号里的部分叫做时序差分误差它表示“实际得到的奖励加上对未来收益的估计与之前对当前状态动作价值的估计之间的差距”。智能体的学习过程本质上就是不断缩小这个差距让Q值估计越来越准确。公式里的alpha是学习率控制每一步更新对Q值的修正幅度gamma是折扣因子控制未来奖励对当前决策的重要程度。这两个参数的具体取值对仿真结果影响很大我后面会拿一组测试数据专门说明。4. MATLAB关键代码实现与参数调试记录理论框架讲完接下来是真正能跑起来的代码。我会把状态离散化、动作选择、Q值更新和训练主循环这几段核心代码完整贴出来然后针对每个关键参数给出选型理由和实测表现这样大家既能直接照着用也知道出了问题该从哪下手排查。4.1 状态离散化连续SNR到状态编号的映射% 状态离散化参数 snr_min 0; % SNR下限 snr_max 30; % SNR上限 N_state 15; % 状态数量 % 将当前SNR映射到状态编号 function idx snr_to_state(snr, snr_min, snr_max, N_state) idx floor((snr - snr_min) / (snr_max - snr_min) * N_state) 1; idx max(1, min(N_state, idx)); % 边界钳位防止越界 end这段代码的关键在于最后的钳位操作。SNR低于0dB时floor计算出来可能是0或负数这会导致后续Q-table查表越界报错SNR超过30dB时又会超过状态总数上限。如果不做钳位处理仿真跑到信道恶化或极佳的时刻就会突然中断这种问题定位起来特别费时间。状态数量N_state的选择也要谨慎。15个状态对应每个状态2dB的粒度既能区分信道质量差异又保证每个状态在训练过程中能够被访问足够多次。如果状态太少智能体无法区分细微的信道差异状态太多每个状态平均访问次数下降Q值估计方差变大。4.2 ε-greedy动作选择与Q值更新% 参数初始化 alpha 0.1; % 学习率 gamma 0.9; % 折扣因子 epsilon 0.9; % 初始探索率 epsilon_min 0.05; % 最低探索率 epsilon_decay 0.995; % 每回合衰减系数 N_action 4; % 动作数: BPSK/QPSK/8PSK/16QAM Q_table zeros(N_state, N_action); % Q-table初始化 % 每个时隙的动作选择 if rand epsilon action randi([1, N_action]); % 探索随机选动作 else [~, action] max(Q_table(state_idx, :)); % 利用选Q值最大的动作 end % 与环境交互后得到reward和next_state_idx % Q值更新 Q_table(state_idx, action) Q_table(state_idx, action) ... alpha * (reward gamma * max(Q_table(next_state_idx, :)) - Q_table(state_idx, action));这段代码是Q-learning的本体逻辑非常直接。需要留意的是max(Q_table(next_state_idx, :))这一项——它取的是下一状态下所有动作中最大的Q值这体现了Q-learning“总是假设未来会采取最优策略”的乐观估计特点。这也是Q-learning的一个固有特性它容易高估Q值在某些场景下可能因此学到次优策略。对于调制选择这种动作数不多、奖励相对稳定的问题高估影响不大但如果你后面换用连续状态空间就需要考虑Double Q-learning这类改进算法。4.3 参数选型从实测角度看学习率、折扣因子和探索率我在调试过程中记录了几组不同参数组合下的收敛表现这里整理成一个表格供参考。参数组合学习率α折扣因子γ收敛速度最终策略稳定性备注组合A0.30.5快差来回波动γ太小不考虑未来收益组合B0.10.9中等好策略稳定推荐的基准组合组合C0.50.9中等中等Q值震荡α过大导致过冲组合D0.050.99慢好但太久适合信道变化更复杂的长训练我的推荐起始组合是alpha0.1、gamma0.9。gamma取0.9的原因是水声信道状态有较强的时间相关性当前决策不仅影响当下还影响后续多个时隙的通信效率所以未来奖励需要被纳入考量。alpha取0.1是为了保证Q值估计的稳定性避免单一异常样本对策略造成过大冲击。探索率epsilon的衰减也很关键。初始值0.9意味着前期的动作90%是随机的这是为了让智能体尽可能遍历各种状态动作组合随着训练推进epsilon指数衰减到0.05附近让智能体更多利用已经学到的经验。衰减速度需要控制衰减太快某些状态动作对没被充分探索学到的是次优策略衰减太慢训练后期还在大量随机摸索策略始终不够稳定。我用的每次迭代乘0.995的指数衰减在1000回合左右基本收敛到epsilon最小值。5. 仿真结果解读Q-table收敛、误码率与吞吐量的三重验证参数调好、代码跑通之后下一步就是把仿真数据拿出来做系统分析。判断一套自适应调制方案到底行不行不能只看训练曲线好不好看要看三个维度的表现Q-table是否真正收敛到稳定策略、误码率是否满足通信要求、有效吞吐量是否比固定调制有明显提升。5.1 怎么判断Q-table已经收敛最直接的判据是训练过程中每回合累计奖励曲线是否趋于平稳。如果训练日志里的累计奖励从大幅波动逐渐变成围绕某个值小幅震荡说明智能体的策略已经基本稳定。这个“小幅震荡”的幅度通常小于平均奖励的5%如果震荡幅度一直降不下来优先检查学习率是不是偏大了。第二个判据是决策表是否稳定。把Q-table中每个状态下最大Q值对应的动作提取出来画成一个“状态-最优调制方式”对照表观察相邻几个训练阶段的对照表是否一致。我实测下来大约600回合约之后这张表就不再变化说明策略已经收敛到稳定解。我在一次典型训练里得到的最优策略表大致是这样的状态编号SNR范围(dB)最优调制方式1-30-6BPSK4-66-12QPSK7-1012-208PSK11-1520-3016QAM这个结果非常符合通信基本原理——信噪比低时用低阶调制保证链路不中断信噪比高时用高阶调制提升吞吐量。看到这个表时基本可以确定Q-learning学到了正确的东西而不是在瞎碰。5.2 与固定调制方案的误码率和吞吐量对比为了验证自适应调制的实际增益我在同样的水声信道条件下分别跑了固定BPSK、固定16QAM和Q-learning自适应调制三种方案统计平均误码率和有效吞吐量。方案平均误码率有效吞吐量(bps/Hz)说明固定BPSK0.00080.9误码率达标但吞吐量低固定16QAM0.0373.2吞吐量高但误码率严重超标Q-learning自适应0.00152.8吞吐量接近16QAM误码率达标这里有个关键指标——有效吞吐量。如果直接统计传输速率16QAM肯定最高但误码率3.7%意味着大量数据包需要重传实际有效吞吐量会大幅缩水。Q-learning自适应的平均调制阶数大约在2.8左右接近8PSK但误码率被控制在0.15%以内不需要频繁重传综合下来的有效吞吐量远超固定16QAM方案。这也是自适应调制最核心的价值用“感知信道并调整策略”换取的可靠性和效率兼得。5.3 信道快速波动场景下Q-learning的优势我额外设计了一组对比实验让信道在短时间内经历“高SNR-低SNR-高SNR”的剧烈波动。传统SNR门限查表法也能实现自适应但它只看当前瞬时SNR不考虑信道变化的趋势在门限附近会发生频繁的调制方式抖动。Q-learning学到的策略天然带有“惯性”。因为状态转移本身包含了时间维度的信息智能体学到的是“在类似状态下过去哪个动作带来过最好回报”所以当SNR在门限附近波动时如果频繁切换的惩罚足够有效智能体倾向于选择一个折中的调制方式先稳住而不是无序地上下跳变。实测中信噪比剧烈波动场景下Q-learning的调制切换次数比门限查表法减少了约35%误码率亦明显更低。这说明Q-learning不仅学到了一张静态的门限表还在一定程度上学会了“什么时候该切换、什么时候该稳住”。6. 踩坑记录状态粒度、惩罚系数和仿真时长这些细节决定成败最后这部分是我最想分享的。Q-learning水声通信自适应的整体框架并不复杂但我在实际调试过程中踩了不少坑有些问题虽然代码层面就一两处改动排查却花了好几天。把这些经验写出来能帮大家少走很多弯路。6.1 状态离散化粒度不是越细越好我最初把SNR从0到30dB分成了30个状态相当于每1dB一个状态想着这样“分辨率高决策更精细”。结果训练了2000回合Q-table还没完全收敛特别是高SNR区域那些状态每个访问次数很少Q值估计方差特别大最优动作在相邻状态之间跳来跳去。后来我把状态数改成15个每个状态对应2dB范围训练速度明显提升策略也稳定了。原因很简单Q-learning用表格存储Q值每个状态都需要足够的采样次数才能得到准确的Q值估计。状态分得太细训练数据被稀释效果反而变差。这个取舍在表格型方法里是固有矛盾如果你的应用场景真的需要精细区分那可能就该考虑DQN这类用神经网络泛化连续状态的方案了。6.2 BER惩罚系数lambda的“躺平”陷阱这是我觉得最有价值的一个调试经验。刚开始我设lambda5结果训练完发现智能体不管信道状态多好都选BPSK。原因特别好理解16QAM在高SNR下误码率虽然低但偶尔一次深衰落导致的误码惩罚直接被放大5倍累加起来期望奖励反而比BPSK低。智能体挨了几次打之后学乖了干脆永远选最保守的BPSK这就是“过度惩罚导致策略躺平”。发现问题后我把lambda从5降到2智能体才逐渐愿意在信道好的时候尝试高阶调制。这个经验告诉我惩罚系数的设置必须配合动作空间的收益量级来考虑。可以先算一下最坏情况下惩罚值是多少再和最高调制方式对应的收益值对比——只有惩罚比收益高一个合理倍数通常是1.5到3倍时智能体才会有“有条件地冒险升级”的动力。6.3 帧长与统计精度的关系仿真里每个时隙发送的数据量太小时误码率统计噪声会很大一个时隙偶尔错的比特数量对误码率的影响能翻好几倍导致奖励信号忽高忽低Q-learning很难学到稳定的规律。我刚开始每个时隙只发200个符号误码率统计结果波动剧烈训练曲线完全没法看。后来我把每个时隙的符号数提高到2000个误码率统计趋于稳定奖励信号平滑了很多训练收敛速度也有了显著提升。这个问题的本质是“样本量不足导致的估计方差大”和统计学里的中心极限定理一个道理。如果你的仿真环境允许尽量增加每个时隙的比特数或符号数让反馈信号稳定可靠这比调任何超参数都管用。6.4 后续扩展思路从Q-learning到更复杂的决策算法这个仿真框架跑通之后往多个方向扩展都是顺理成章的。如果SNR之外还想加入多径时延、信道估计误差等更多状态特征状态空间会迅速膨胀表格型Q-learning的存储和采样压力都会超标这时可以换成深度Q网络DQN把状态特征直接作为神经网络输入用函数逼近替代表格查值。还可以引入Double Q-learning解决Q值高估问题或者用多智能体框架让发送端和接收端协同学习各自的策略。另外强化学习在水声通信中的应用也不止自适应调制这一处功率分配、路由选择、MAC协议参数自适应、中继协作调度这些场景都可以套用类似的“状态-动作-奖励”建模框架。我的体会是先把Q-learning在水声自适应调制这个相对简单的场景里完整跑通一遍把状态设计、奖励塑造、参数调优这套方法论掌握扎实面对更复杂的问题时自然就有清晰的思路了。如果你正准备做类似的水声通信仿真我的建议是先把信道模型和通信收发流程调到足够稳定然后再接Q-learning模块——两个系统分开调试能省下大量排错时间。等基础版本跑通之后再把信道模型往Bellhop射线追踪这类更真实的模型切换观察算法在更接近实际环境下的表现那种情况下得到的仿真结论才更有工程参考价值。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进