
简介这份资源是一篇面向通信工程、无线网络与人工智能交叉方向研究者的技术文档聚焦无蜂窝大规模MIMO场景下无人机辅助通信与资源调度难题适合具备一定强化学习与通信理论基础的研究生、科研人员及工程技术人员参考。压缩包内仅含1个docx文档约409KB内容围绕分布式MIMO与大规模MIMO融合架构展开系统梳理了无人机轨迹设计、AP功率分配、用户调度等核心问题。文档深入探讨了双动作马尔可夫决策过程、有限状态马尔可夫信道、深度Q网络、深度确定性策略梯度及多智能体强化学习等算法在无线资源管理中的具体应用并给出两跳协作机制下的建模与求解思路。目前已有226人学习读者可从中获取偏远地区、灾区、沙漠海洋及高速公路等场景的通信覆盖方案设计参考理解如何利用深度强化学习最大化用户可达速率与总吞吐量为相关课题研究或工程实践提供可借鉴的算法框架与问题建模方法。1. 无蜂窝大规模MIMO遇上无人机这套组合到底在解决什么问题地面基站越建越密边缘用户的速率却始终上不去这是很多人做无蜂窝大规模MIMO时最先撞上的墙。无蜂窝大规模MIMO的核心思路是把一堆接入点AP通过回传链路连到中央处理单元让多个AP同时服务同一个用户用协作增益换掉传统蜂窝的小区间干扰。理论上很美但真到部署阶段热点区域流量潮汐效应明显固定AP在低峰期闲置、高峰期又不够用这时候无人机辅助通信就成了一个很自然的补充手段——把空中节点当成可移动的AP按需飞到流量密集区顶上补容量。问题随之而来无人机往哪飞、飞多高、和哪些地面AP协作用户、功率怎么分配这些决策互相耦合用传统凸优化做每换一个场景就要重新推导一遍而且信道状态和用户位置一变离线算好的解直接失效。深度强化学习尤其是DQN这类值函数方法恰好适合这种「状态连续变化、动作离散可选、奖励延迟反馈」的调度问题。这套方案适合已经懂一点MIMO预编码、又想把手里的调度问题从「离线优化」升级到「在线决策」的工程师也适合做无人机通信仿真、想找一个能跑通的最小闭环的研究生。下面我按自己实际搭仿真的顺序把这条链路拆开讲清楚。2. 无蜂窝大规模MIMO与无人机辅助通信的建模要点先想清楚状态、动作、奖励2.1 为什么无蜂窝架构下无人机不能当成普通移动基站传统蜂窝里无人机基站服务自己小区内的用户其他小区干扰它建模时把干扰项一减就完事。无蜂窝架构不一样所有AP共享同一套导频和同一块时频资源用户接收到的信号是多个AP的叠加无人机作为其中一个AP加入后它的位置直接改变了整个协作簇的信道矩阵结构。换句话说无人机的动作不只是「服务谁」而是「以什么几何位置参与联合传输」。我一般会把上行导频传输和下行数据传输分开建模。上行阶段所有AP接收导频中央单元做信道估计下行阶段CPU根据估计结果算预编码再分发给各AP。无人机在这个流程里贡献的是它到用户的那条视距LoS分量这条分量随无人机位置变化非常剧烈所以状态里必须包含无人机三维坐标和用户分布否则DQN学出来的策略会退化成「悬停不动」。另一个容易忽略的点是回传容量。无蜂窝架构依赖AP到CPU的回传链路无人机走无线回传时带宽是有限的。如果状态里不体现回传负载智能体会倾向于把所有用户都塞给无人机导致回传拥塞仿真里表现为吞吐量不升反降。常见做法是在奖励函数里加一个回传惩罚项或者把回传队列长度放进状态向量。2.2 状态、动作、奖励的具体设计状态设计我通常用四组量拼成一个向量无人机当前位置3维、无人机剩余电量1维、各用户的位置和速率需求假设K个用户每个用户4维共4K维、以及当前各AP的负载M个APM维。如果用户数超过10个状态维度会迅速膨胀这时候要么做用户分簇要么用CNN提取空间特征DQN直接吃原始状态会很难收敛。动作空间要离散化。连续的位置控制对DQN不友好我一般把无人机的可移动范围切成网格比如水平方向7个档、垂直方向3个档加上「保持悬停」总共22个动作。功率分配如果也要学可以再乘一个功率档位但动作数会爆炸建议第一版先固定功率只学位置和调度。奖励函数是整套方案里最需要反复调的地方。我用的形式是# reward 计算示例 # rate_k: 第k个用户的瞬时速率 # backhaul_load: 无人机回传链路当前负载比例 # energy: 无人机剩余电量比例 # collision: 是否与地面AP覆盖冲突0/1 def compute_reward(rate_k, backhaul_load, energy, collision): # 速率项取对数平滑避免个别用户速率过高主导奖励 rate_term sum([np.log2(1 r) for r in rate_k]) # 回传惩罚负载超过0.8后惩罚急剧上升 backhaul_penalty 5.0 * max(0, backhaul_load - 0.8) # 电量惩罚低于20%时开始扣分 energy_penalty 3.0 * max(0, 0.2 - energy) # 冲突惩罚与地面AP覆盖重叠严重时扣分 collision_penalty 2.0 * collision return rate_term - backhaul_penalty - energy_penalty - collision_penalty这段奖励的逻辑是速率项用对数而不是线性是因为线性速率会让智能体只盯着信道最好的那个用户其他用户被饿死回传惩罚设0.8的阈值是留出20%的余量应对突发电量惩罚放在0.2以下是避免智能体过早返航导致服务中断。参数不是拍脑袋定的我一般会先跑几组不同权重看训练曲线里速率和惩罚项的比值再微调。提示奖励函数里的惩罚项系数不要一开始就设得很大否则智能体会学出「什么都不做」的保守策略因为任何动作都可能触发惩罚。先用小系数跑通再逐步加大。2.3 信道模型与仿真参数怎么设才不脱离实际信道模型我建议用概率视距模型而不是纯LoS或纯瑞利。无人机到地面用户的LoS概率是仰角的函数仰角越高LoS概率越大。具体形式常见做法是# 视距概率计算 # theta: 仰角度 # a, b: 环境参数城区一般取 a9.61, b0.16 def los_probability(theta, a9.61, b0.16): return 1.0 / (1.0 a * np.exp(-b * (theta - a)))这个公式里a和b决定了LoS概率随仰角变化的陡峭程度。城区环境a取9.61、b取0.16是比较常用的值郊区可以适当调小a。仰角theta由无人机高度和水平距离算出来所以无人机飞得越高LoS概率越大但路径损耗也越大这里存在一个最优高度DQN要学的就是这个权衡。仿真参数方面载波频率我一般用2GHz带宽20MHz地面AP数量设16个用户数设8到12个无人机发射功率设0.1W到1W可调。噪声功率谱密度取-174dBm/Hz。这些数值不是标准答案但能保证仿真结果在合理范围内不会出现速率高得离谱或者低得没法看的情况。3. 用DQN跑通无人机调度从环境封装到训练收敛的完整步骤3.1 环境封装把通信仿真写成gym风格接口DQN需要和环境的交互接口我习惯把通信仿真封装成gym风格的类核心是reset()和step()两个方法。reset()初始化无人机位置、用户分布和信道状态返回初始状态step(action)执行动作更新无人机位置和信道计算奖励返回(next_state, reward, done, info)。import numpy as np class UAVSchedulingEnv: def __init__(self, num_users10, num_aps16, grid_size7): self.num_users num_users self.num_aps num_aps self.grid_size grid_size self.action_space grid_size * 3 1 # 水平7档 x 垂直3档 悬停 self.state_dim 3 1 4 * num_users num_aps def reset(self): # 无人机初始位置区域中心高度100m self.uav_pos np.array([0.0, 0.0, 100.0]) # 用户随机分布 self.user_pos np.random.uniform(-500, 500, (self.num_users, 2)) self.user_pos np.hstack([self.user_pos, np.zeros((self.num_users, 1))]) # 电量初始100% self.energy 1.0 # AP负载初始为0 self.ap_load np.zeros(self.num_aps) return self._get_state() def step(self, action): # 解析动作水平档位、垂直档位、是否悬停 if action self.action_space - 1: pass # 悬停位置不变 else: h_idx action // 3 v_idx action % 3 # 水平移动步长50m垂直移动步长20m self.uav_pos[0] (h_idx - 3) * 50.0 self.uav_pos[1] (v_idx - 1) * 20.0 self.uav_pos[2] np.clip(self.uav_pos[2] (v_idx - 1) * 20.0, 50.0, 300.0) # 计算信道和速率 rate_k self._compute_rates() # 更新电量悬停耗电少移动耗电多 move_dist np.linalg.norm(self.uav_pos - self._last_pos) self.energy - 0.001 * move_dist 0.0005 self._last_pos self.uav_pos.copy() # 计算奖励 reward self._compute_reward(rate_k) done self.energy 0.05 return self._get_state(), reward, done, {}这段代码的关键在于动作解析和电量更新。动作空间设计成水平7档、垂直3档加悬停总共22个动作DQN的输出层维度就是22。电量消耗和移动距离挂钩这样智能体会学到「少动多悬停」的策略但悬停太久用户速率会下降形成权衡。_compute_rates()里做的是无蜂窝协作传输的速率计算需要用到预编码矩阵这部分我单独封装避免和环境逻辑混在一起。注意step()里一定要做边界裁剪无人机飞出区域或者高度超出范围时要么clip要么给惩罚否则训练初期智能体会疯狂撞墙浪费大量样本。3.2 DQN网络结构与关键超参数DQN的网络结构不用太深我一般用三层全连接输入层维度等于state_dim两个隐藏层各256个神经元激活函数用ReLU输出层维度等于动作数。经验回放池大小设10000batch size设64目标网络更新频率设每200步一次。import torch import torch.nn as nn class DQN(nn.Module): def __init__(self, state_dim, action_dim, hidden_dim256): super(DQN, self).__init__() self.net nn.Sequential( nn.Linear(state_dim, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, action_dim) ) def forward(self, x): return self.net(x) # 超参数 GAMMA 0.95 # 折扣因子 LR 1e-4 # 学习率 EPSILON_START 1.0 # 初始探索率 EPSILON_END 0.05 # 最终探索率 EPSILON_DECAY 5000 # 探索率衰减步数 TARGET_UPDATE 200 # 目标网络更新频率 MEMORY_SIZE 10000 # 经验回放池大小 BATCH_SIZE 64 # 批大小折扣因子GAMMA取0.95而不是0.99是因为无人机调度问题里当前动作对未来的影响衰减较快取太大智能体会过度关注远期奖励收敛变慢。学习率1e-4是DQN的常用值如果训练曲线震荡厉害可以降到5e-5。探索率从1.0线性衰减到0.05衰减步数5000这个值要根据总训练步数调整总步数10万的话5000步衰减完有点快可以设成20000。目标网络更新频率200步这个值影响训练稳定性。更新太频繁目标网络和在线网络太接近容易发散更新太慢目标滞后严重学习效率低。我一般先在200附近试看loss曲线如果loss震荡就加大到500。3.3 训练循环与收敛判断训练循环的核心是采样动作、执行、存经验、抽batch、算loss、反向传播、定期更新目标网络。import random from collections import deque memory deque(maxlenMEMORY_SIZE) policy_net DQN(state_dim, action_dim) target_net DQN(state_dim, action_dim) target_net.load_state_dict(policy_net.state_dict()) optimizer torch.optim.Adam(policy_net.parameters(), lrLR) def select_action(state, epsilon): if random.random() epsilon: return random.randrange(action_dim) with torch.no_grad(): return policy_net(state).argmax().item() def train_step(): if len(memory) BATCH_SIZE: return batch random.sample(memory, BATCH_SIZE) states, actions, rewards, next_states, dones zip(*batch) states torch.stack(states) actions torch.tensor(actions) rewards torch.tensor(rewards, dtypetorch.float32) next_states torch.stack(next_states) dones torch.tensor(dones, dtypetorch.float32) q_values policy_net(states).gather(1, actions.unsqueeze(1)).squeeze() with torch.no_grad(): next_q target_net(next_states).max(1)[0] target rewards GAMMA * next_q * (1 - dones) loss nn.MSELoss()(q_values, target) optimizer.zero_grad() loss.backward() optimizer.step()收敛判断不能只看reward曲线我一般同时看三个指标平均reward是否稳定上升并趋于平台、平均Q值是否发散、以及实际调度指标用户平均速率、回传负载是否改善。如果reward上升但用户速率没变说明智能体在钻奖励函数的空子比如一直悬停拿电量惩罚的低分但避免了大动作的惩罚这时候要回去改奖励。训练步数方面状态维度在50左右、动作22个的情况下我一般跑5万到10万步能看到明显收敛。如果跑20万步还在震荡大概率是状态设计有问题或者奖励函数里有相互矛盾的项。4. 避坑与排查无人机辅助无蜂窝MIMO调度里最容易翻车的5个地方4.1 现象训练初期reward直接崩到负无穷原因奖励函数里的惩罚项系数设得太大智能体第一次探索时触发了回传或电量惩罚Q值被拉到一个极大的负值后续所有动作的Q值都被这个负值主导网络输出饱和。解决把惩罚项系数先设成0.1倍跑通后再逐步加到目标值。另外检查状态归一化如果状态里有的维度是几百、有的是0.1网络第一层权重会被大数值维度主导建议所有状态维度都归一化到[-1, 1]或[0, 1]。4.2 现象智能体学会「悬停不动」拿保底奖励原因移动的惩罚电量消耗大于移动带来的速率增益智能体发现悬停能拿一个稳定的中等奖励移动反而可能触发惩罚。这是奖励函数设计里典型的「保守策略陷阱」。解决在奖励里加一个「速率增益」项只有速率超过基线时才给正奖励或者把电量惩罚改成只在电量低于阈值时才生效。另一个办法是给悬停动作加一个小的负奖励逼智能体动起来。4.3 现象仿真里速率很高但回传负载爆了原因状态里没有回传负载信息或者回传惩罚项系数太小智能体把所有用户都调度到无人机上地面AP闲置。无蜂窝架构的回传容量是硬约束忽略它会导致仿真结果不可信。解决把回传队列长度放进状态向量并在奖励里加一个硬约束回传负载超过0.9时直接给一个大的负奖励比如-10而不是线性惩罚。硬约束比软惩罚更能让智能体学会避开。4.4 现象换一组用户分布策略完全失效原因DQN过拟合到了训练时的用户分布状态里用户位置是绝对坐标网络学到的是「在某个坐标附近悬停」而不是「往用户密集区飞」。这是泛化能力不足的典型表现。解决状态里不要用绝对坐标改用相对坐标——无人机到用户质心的偏移量、用户分布的方差等统计量。另外训练时每轮reset都随机化用户分布不要用固定分布。4.5 现象训练loss震荡Q值越来越大原因目标网络更新太慢或者GAMMA设得太大导致目标Q值不断累积网络输出越来越大。DQN里Q值发散是常见问题尤其是奖励尺度没有归一化的时候。解决先把奖励归一化到[-1, 1]区间再检查GAMMA是否超过0.99。如果还震荡把目标网络更新频率从200降到100或者用软更新每次只更新目标网络参数的0.01倍。另外检查经验回放池里是否有大量高奖励样本导致batch内方差过大。5. 进阶技巧用优先经验回放和动作掩码把收敛速度提上来基础DQN跑通之后如果觉得收敛慢或者策略不够精细有两个改动性价比最高。第一个是优先经验回放Prioritized Experience Replay核心思想是让TD误差大的样本被采样概率更高因为那些样本包含更多「意外」信息。实现上不用改网络结构只改采样逻辑# 优先经验回放采样 # priorities: 每个样本的TD误差绝对值 # alpha: 优先级指数0表示均匀采样1表示完全按优先级 def sample_prioritized(memory, priorities, batch_size, alpha0.6): probs np.array(priorities) ** alpha probs / probs.sum() indices np.random.choice(len(memory), batch_size, pprobs) return [memory[i] for i in indices], indicesalpha取0.6是常用值兼顾探索和利用。采样后要更新对应样本的优先级新样本的优先级设成当前最大优先级保证每个样本至少被采样一次。这个改动一般能让收敛步数减少20%到30%代价是多了优先级维护的开销。第二个改动是动作掩码。无人机调度里有些动作是物理上不可行的比如电量低于10%时不能再往远处飞或者回传负载已满时不能再接入新用户。与其让智能体通过惩罚慢慢学不如直接在动作选择时把这些动作的Q值设成负无穷# 动作掩码不可行动作的Q值设为 -inf def masked_action_selection(q_values, feasible_mask): q_values q_values.clone() q_values[~feasible_mask] float(-inf) return q_values.argmax().item()feasible_mask是一个布尔向量根据当前电量和回传负载算出来。这个改动几乎不增加计算量但能显著减少无效探索训练初期尤其明显。验证策略是否真的学到了东西我一般用两个方法。一是固定一组用户分布看无人机最终悬停位置是否在用户质心附近如果偏得很远说明状态或奖励有问题。二是画速率累积分布曲线对比DQN策略和「随机悬停」「固定位置悬停」两个基线的CDF如果DQN的曲线明显靠右说明策略有效。我自己的习惯是每次改完奖励函数或状态设计都先跑5000步看趋势趋势不对就停下来改不要硬跑到10万步再看那样太费时间。希望帮到你。本文还有配套的精品资源点击获取