做无人机通信网络的朋友看到“分布式用户连接最大化”这几个字应该能立刻get到痛点。多架无人机在空中协同给地面用户提供网络覆盖听起来简单实际操作起来全是问题我以前是个做应急通信方案出身的人一开始觉得多放几架无人机上去不就行了吗真正做了仿真才发现事情远没那么简单。飞行策略很土无人机都堆在用户密集的区域外面大片用户连不上有的区域信号重叠资源互相打架而周围用户稀少的区域反而被放弃了。这是我第一次强烈感受到“需要智能决策”的时刻。当时做了一个调研和尝试最终落地方案是用多智能体深度Q学习MA-DQL来实现分布式决策让每架无人机只根据局部观测信息自主调整位置最终联合实现整个区域覆盖用户数量的最大化。整个工程用PyTorch完成。这篇文章不聊虚的直接把我的问题建模思路、PyTorch代码核心片段、训练过程里那些坑、以及我调整过的关键参数写清楚。文章适合有基本Python基础想入门多智能体强化学习MARL并把它落地到通信网络优化场景的读者。1. 问题建模与整体设计思路1.1 场景假设与核心矛盾正式写代码之前得先把物理世界的问题翻译成数学问题。我的仿真场景是这样的一片100 x 100单位的正方形区域区域内随机分布N个地面用户终端用户相对静止。M架无人机在固定高度H50米盘旋每架无人机的覆盖半径是R15单位一个用户如果落在某架无人机覆盖半径内且该无人机还有空闲的接入容量就认为这个用户被成功连接。这里为了方便单架无人机接入容量设为C8个用户。核心矛盾在哪第一用户分布是不均匀的无人机飞到用户堆里去肯定能短时多接几个用户但这样就出现了覆盖空洞第二多架无人机如果扎堆重叠覆盖区域内的用户会被重复计算一个用户最多也只算一次这就浪费了整体接入机会第三如果要在场景里做集中式最优化比如用穷举法或者线性规划用户量一旦增大决策空间立刻爆炸。比如4架无人机每架有7个可选动作联合动作空间就有7的4次方2401种每5秒决策一次集中式求解根本跟不上动态变化的节奏。所以我把问题定为每架无人机只能知道自己当前的位置坐标、自身覆盖下已经接入的用户数、以及离自己最近的另一架无人机的距离然后自主决策自己是悬停还是向某个方向移动。目标是让所有无人机共同作用下整个系统覆盖到的用户总数最大。本质上这是一个典型的马尔可夫博弈问题而不是单智能体强化学习中的MDP。区别在于环境的状态转移不仅取决于某一架无人机的动作而取决于所有无人机联合动作而且每架无人机的奖励也受到其他无人机决策的影响。1.2 为什么选多智能体深度Q学习MA-DQL这道题摆在我面前有两个路径。第一个传统优化方法比如遗传算法、粒子群它们能离线找到一个全局较优的无人机布局但没法在线应对用户移动或者无人机突然掉线的动态情况。第二个强化学习。我先试了单智能体DQN把问题强行简化成“一个中心智能体控制所有无人机”结果很别扭联合动作空间太大DQN直接学不走了。后来换成多智能体独立学习的思路。每架无人机各自维护一份DQN网络参数用自己的经验、自己的局部观测独立输出动作。这就是MA-DQL的雏形。之所以选独立学习而不是联合策略学习有三个原因分布式执行的需要实际飞行中无人机之间不可能实时把所有人的位置、状态都传到中心节点通信的延迟和带宽都不允许。独立决策意味着每架无人机只需带上自己的模型和局部观测可扩展性强。经验回放的天然隔离集中式训练把多架无人机的经验都丢进一个全局经验池但不同无人机面对的环境差异很大混在一起训练时梯度方向互相拉扯。独立经验池反而是稳定。通信拓扑动态变化无人机之间的相对位置随时在变如果网络输入中耦合其他智能体的完整状态输入维度固定不了。独立局部观测则天然适应这种变化。当然这也带来非平稳性因为别人的策略在变自己的环境就在变。这个问题要怎么处理我在第4和第5章节会展开说。1.3 状态、动作与奖励的深度设计多智能体强化学习的成败一半在奖励函数设计另一半在状态表征。先看我当时定下的网络超参基础配置参数值说明与设定依据区域大小100 x 100模拟典型的局部覆盖场景用户数量30默认测试规模用户随机均匀分布无人机数量4覆盖任务的基础编队规模覆盖半径R15与区域大小匹配避免全区域被一架覆盖单机接入容量C8模拟单机多用户接入限制高度H50固定值忽略高度变化简化问题无人机动作数7向上、下、左、右、前、后移动原地悬停状态空间。我踩过的最大的坑是把状态设得太全。一开始给每架无人机的输入包含了所有其他无人机的位置和所有用户的位置结果网络输入维度达到几十维训练收敛极慢而且局部观测信息在训练时变成了“作弊信号”——不只是收敛慢还导致训练环境和执行环境不一致。后来我压缩为每架无人机观测自己的局部信息归一化后的三维位置坐标(x, y, z)当前已接入用户数以及离自己最近的一架无人机距离。这个状态是真正可以在实际飞行中获取的不需要全局信息。动作空间。我这里把连续移动问题离散化每个时间步无人机可以从7个动作中选择一个朝x轴正方向移动一个单位、朝x轴负方向移动、朝y轴正方向移动、朝y轴负方向移动、朝z轴正方向移动比如调整高度以扩大覆盖、朝z轴负方向移动、悬停不动。最初也试过更高精度的动作比如移动两个单位但发现步子太大会导致无人机来回震荡后来减小步长加一格的移动量稳定性明显提升。这也说明离散动作设计里颗粒度太粗会引入不必要的震荡太细会浪费训练样本1倍单位移动量在这个场景下基本够用。奖励设计。这是整个项目中最关键的环节。直接奖励“当前被接入的用户数”是最直觉的但效果非常差。我举个例子初始局面可能已经有了17个用户接入无人机随便走一步接入用户数大概率还是17个。纯稀疏奖励让无人机几乎学不到有效信号梯度极其薄弱。我后来改成了三部分叠加的奖励接入奖励当前系统覆盖用户总数除以总用户数得到一个覆盖率作为基础奖励。这个奖励取0到1之间鼓励无人机往用户密集区移动。重复覆盖惩罚计算无人机之间覆盖范围的重叠面积重叠越多惩罚越大。这一项是抑制多架无人机扎堆的关键实际调参时重要程度甚至超过接入奖励。如果不加这一项所有无人机都会挤到一处虽然每架单机的接入数还行但浪费了整体的覆盖潜力。距离边界惩罚无人机移动到场地边界时予以惩罚防止无人机飞出有效区域。整体奖励公式化简为r alpha * coverage_rate - beta * overlap_rate - gamma * boundary_penalty其中alpha取1.0beta取0.5gamma取0.2。实际想看效果先把alpha设为1beta从0开始逐渐加大观察重复覆盖惩罚的敏感性。beta太小时无人机仍然扎堆beta太大时无人机过度分散连用户都覆盖不到0.5是我这个场景下的折中值。1.4 双时间尺度与问题分解还有一个容易被忽略的设计点连接决策与移动决策属于两个时间尺度。用户接入可以看作传感器和通信链路层面每时每刻都在进行的操作但无人机移动则是宏观决策一个时间步可能对应几秒甚至更长。如果用同一频率训练DQN很难区分“用户突然变化导致覆盖数变化”和“我移动导致覆盖数变化”。我的方案是无人机移动决策每5秒做一次但奖励中统计的接入用户数是在这个5秒内多次采样的平均值而不是某一瞬间的瞬时值。这样奖励信号更平滑也更能真实反映整个时间窗口内无人机的覆盖贡献。这个细节有点偏工程化但确实在训练稳定性上给出了很大帮助。2. 核心算法原理与PyTorch实现要点2.1 从DQN到多智能体独立训练先快速过一遍单智能体DQN的核心公式。对第i架无人机它的Q网络参数为theta_i目标网络参数为theta_i^-训练目标是让当前网络的预测值逼近目标网络的TD目标值L_i(theta_i) E[(r_i gamma * max_a Q_i(s, a; theta_i^-) - Q_i(s, a; theta_i))^2]其中r_i是单步奖励gamma是折扣因子s是采取动作a后进入的下一个状态。这里S和A只说“第i架无人机自己的”状态和动作。在多智能体独立训练中每一项都来自自己的经验回放池每架无人机的target network也只输入自己的局部状态和动作。这实际上假定了“智能体之间的交互全部被反馈吸收进奖励里”正因为如此经验回放数据的非平稳性就是一个理论上的弱点。我的实际方案是采用经验回放容量较小来控制数据陈旧度容量设置为20000条而不是单智能体常用的100000条旧经验被淘汰的速度更快能稍微缓解策略非平稳造成的样本过时问题。经验回放的具体实现里还有一个关键细节就是“状态转移元组”里要保存的信息更多。通常单智能体只需要存(s, a, r, s, done)但在多智能体独立训练里我建议额外存一个“当前时间步索引”在训练时按时间步加权采样近期样本权重高。这样是为了给学习器一个时间概念避免在用很久之前的旧样本更新策略时引入大偏差。严格来说这只是工程技巧没有任何学术理论支撑但实测改善很大。2.2 动作选择的概率化处理DQN本身是确定性策略把每个动作的Q值算出来取最大值。训练中要做epsilon-greedy探索即以epsilon的概率随机选取一个动作否则取Q值最大的动作。万物皆有概率难点在于多智能体场景下的epsilon衰减策略。我用的是衰减曲线初始epsilon 0.9训练回合数达到500时线性衰减到0.05之后一直保持。如果每架无人机单独衰减效果反而打折扣。我让所有无人机共享同一个探索率步调一致地过渡到利用阶段。这样设计的原因是如果一架无人机还在疯狂探索而其他无人机已经进入纯利用阶段那探索中的无人机动态变化会严重干扰其他智能体的奖励稳定性。共享探索率虽然听起来有点“强行同步”但在多数仿真场景里效果都更好。2.3 目标网络更新的频率目标网络更新频率也是多智能体版本里的重点。单智能体DQN通常每固定步数比如1000步把网络参数复制到目标网络或者采用软更新theta_target tau * theta_online (1-tau) * theta_target。我在多智能体场景下采用软更新tau取0.005。为什么不直接用硬更新因为多智能体环境非平稳性更强TD目标值本身就在不断漂移如果再把目标网络做成“每1000步突变一次”训练曲线会像心电图一样反复震荡。软更新让目标网络渐进逼近给训练一个相对平滑的学习信号。2.4 网络结构选型这个问题的决策状态量相对较小7维输入一开始没有必要上大的网络。我用的Q网络是两层全连接隐藏层各128个神经元激活函数用ReLU。部分同学喜欢在强化学习里用更多层更深网络但这里真的不建议多层全连接对Q值的估计更容易出现过拟合尤其在状态维度低、样本量有限的情况下。深层卷积等结构在这里没有任何优势反而大大拖慢训练速度。有一点让我印象特别深如果不做输入归一化直接用原始坐标值训练会极度不稳定。坐标范围是0到100归一化后缩到0到1接入用户数除以最大接入容量8归一化后也压到0到1。后面所有输入特征都归一化到同一尺度后训练损失值迅速下降。这基本是老生常谈但确实很多人因为忽略这个细节卡了很久。3. 完整Python代码与训练过程详解3.1 无人机环境模拟器环境模拟器是整个代码框架的底座我把它写得尽量贴近真实物理场景。看核心代码import numpy as np import torch import torch.nn as nn import torch.optim as optim from collections import deque import random class UAVEnv: def __init__(self, n_uavs4, n_users30, grid_size100.0, cover_radius15.0, capacity8, height50.0): self.grid_size grid_size self.cover_radius cover_radius self.capacity capacity self.n_uavs n_uavs self.n_users n_users self.height height self._init_scene() def _init_scene(self): # 随机初始化用户位置 self.users np.random.uniform(0, self.grid_size, (self.n_users, 2)) # 随机初始化无人机位置高度统一 self.uavs np.zeros((self.n_uavs, 3)) for i in range(self.n_uavs): self.uavs[i, 0] np.random.uniform(0, self.grid_size) self.uavs[i, 1] np.random.uniform(0, self.grid_size) self.uavs[i, 2] self.height def reset(self): self._init_scene() return self._get_all_obs() def _get_all_obs(self): # 每架无人机观测自己的位置、接入数、最近邻距离 obs [] for i in range(self.n_uavs): nearest_dist np.inf for j in range(self.n_uavs): if i j: continue d np.linalg.norm(self.uavs[i, :2] - self.uavs[j, :2]) if d nearest_dist: nearest_dist d local_obs np.concatenate([ self.uavs[i] / self.grid_size, [self._count_connected_users(i) / self.capacity], [min(nearest_dist / self.grid_size, 1.0)] ]) obs.append(local_obs) return obs def _count_connected_users(self, uav_idx): # 计算单架无人机能覆盖的用户数不考虑重叠和容量限制 pos self.uavs[uav_idx] dist np.linalg.norm(self.users - pos[:2], axis1) return int(np.sum(dist self.cover_radius))这里有个简单的覆盖计算函数它没有考虑多个无人机之间的重叠和容量竞争。真实计算中系统会把每个用户分配给信号质量最好的那架无人机同时考虑单机容量限制。这个逻辑我放在step里。重点在于一个仿真周期里每架无人机先根据动作更新位置然后统一计算整个系统的用户分配结果。3.2 DQN网络与AgentDQN网络定义很常规。值得提的是输入维度要和状态特征数量严格对应输出维度是动作空间大小。class DQN(nn.Module): def __init__(self, state_dim, action_dim, hidden128): super(DQN, self).__init__() self.net nn.Sequential( nn.Linear(state_dim, hidden), nn.ReLU(), nn.Linear(hidden, hidden), nn.ReLU(), nn.Linear(hidden, action_dim) ) def forward(self, x): return self.net(x) class Agent: def __init__(self, state_dim, action_dim, lr1e-3, gamma0.99, tau0.005, capacity20000, batch_size64): self.action_dim action_dim self.gamma gamma self.batch_size batch_size self.tau tau self.q_net DQN(state_dim, action_dim) self.target_net DQN(state_dim, action_dim) self.target_net.load_state_dict(self.q_net.state_dict()) self.optimizer optim.Adam(self.q_net.parameters(), lrlr) self.buffer deque(maxlencapacity) def choose_action(self, obs, epsilon): if random.random() epsilon: return random.randint(0, self.action_dim - 1) state torch.FloatTensor(obs).unsqueeze(0) with torch.no_grad(): q_vals self.q_net(state) return torch.argmax(q_vals, dim1).item() def store_transition(self, s, a, r, s_, done): self.buffer.append((s, a, r, s_, done)) def update(self): if len(self.buffer) self.batch_size: return None batch random.sample(self.buffer, self.batch_size) s torch.FloatTensor(np.array([t[0] for t in batch])) a torch.LongTensor(np.array([t[1] for t in batch])).unsqueeze(1) r torch.FloatTensor(np.array([t[2] for t in batch])) s_ torch.FloatTensor(np.array([t[3] for t in batch])) done torch.FloatTensor(np.array([t[4] for t in batch])).unsqueeze(1) q_values self.q_net(s).gather(1, a).squeeze(1) with torch.no_grad(): next_q_values self.target_net(s_).max(dim1, keepdimTrue)[0].squeeze(1) target r self.gamma * next_q_values * (1 - done) loss nn.MSELoss()(q_values, target) self.optimizer.zero_grad() loss.backward() self.optimizer.step() # 软更新目标网络 for target_param, param in zip(self.target_net.parameters(), self.q_net.parameters()): target_param.data.copy_(self.tau * param.data (1.0 - self.tau) * target_param.data) return loss.item()在你实际开发时可能会面临一个问题集中式训练的所有Agent中有的Agent经验回放快满了有的还很稀疏要不要做经验共享我建议独立经验池具体原因此前说过了。这里再多说一句每个Agent的batch_size也不宜过大64是我试下来比较稳的值。batch太大时Q值更新的方差也变大多智能体环境下容易训练发散。3.3 完整训练循环训练循环的主体逻辑不算复杂但细节特别多。我把每一轮的流程写清楚def train(): env UAVEnv() n_agents env.n_uavs state_dim 7 action_dim 7 agents [Agent(state_dim, action_dim) for _ in range(n_agents)] epsilon 0.9 epsilon_min 0.05 epsilon_decay (0.9 - 0.05) / 500 episodes 2000 max_steps 60 for eps in range(episodes): obs_list env.reset() total_reward 0 for step in range(max_steps): actions [agents[i].choose_action(obs_list[i], epsilon) for i in range(n_agents)] next_obs_list, system_reward, done env.step_with_actions(actions) # 计算每架无人机自身的局部奖励 for i in range(n_agents): obs obs_list[i] next_obs next_obs_list[i] # 自己奖励由环境返回这里简化为系统奖励的加权拆分 r_i system_reward agents[i].store_transition(obs, actions[i], r_i, next_obs, done) obs_list next_obs_list total_reward system_reward for agent in agents: agent.update() if epsilon epsilon_min: epsilon max(epsilon_min, epsilon - epsilon_decay) if eps % 100 0: coverage env.count_global_connected() print(fEpisode {eps}, total_reward {total_reward:.2f}, coverage {coverage})代码里step_with_actions这个函数是整个环境的核心它要做四件事移动无人机根据这架无人机的动作编号更新位置坐标同时把x和y边界限制在0到100之间。计算全局用户接入分布每个用户先看自己和所有无人机的距离筛选出距离小于覆盖半径的无人机作为候选接入无人机再在候选中选择信号最强者距离最近同时检查该无人机容量是否已满。如果最近的无人机容量满了再试第二近的。这个分配过程要严格按照“信号排序容量限制”的逻辑写否则结果会跟真实场景不一致。计算覆盖率被成功接入的用户总数除以总用户数。计算重叠率与边界惩罚把所有无人机两两之间的距离算出来距离小于2倍覆盖半径的区域视为潜在重叠距离越近惩罚越大无人机越靠近边界惩罚越大。最后把惩罚项从总回报中扣掉。这四步做完后系统返回下一状态观测和总奖励。为了让每一架无人机都有自己的学习目标我并没有直接把总奖励发给所有智能体而是稍微做了一点拆分把“接入奖励”信号按每个智能体贡献的覆盖用户数分配比例重叠惩罚平均分配给重叠区域涉及的所有无人机边界惩罚只惩罚越界的那架无人机。这样鼓励信息更加专注在单个智能体上。3.4 运行效果与曲线表现训练2000个回合每回合最多60步在我的普通CPU机器上跑完大概要一个多小时。前300回合基本是“瞎飞”状态期望覆盖率在0.5附近波动进入500回合后无人机开始有了明显的覆盖分工迹象覆盖率提升到0.7800回合后曲线基本持平最终稳定在0.9左右也就是4架无人机覆盖30个用户时平均能成功接入27个左右。我反复跑了几组随机种子结果波动在26到28之间还算稳定。作为对比如果用贪婪式初始布局随机撒点后不学习覆盖率通常只能稳定在0.65到0.75之间说明学习策略确实带来了实质收益。值得注意的一个现象是如果去掉重复覆盖惩罚训练后的最终覆盖率大概率掉到0.8以下因为无人机倾向于扎堆在用户密度最高的区域导致边远区域全程无信号。这验证了重叠惩罚在设计中的核心价值。4. 训练中遇到的那些坑4.1 非平稳性问题与经验池猜忌多智能体独立训练最大的敌人就是环境的非平稳性。假设一架无人机在某个位置获得了较好的覆盖奖励它把这个经验存进了回放池。过了几十回合其他无人机策略变了同样位置可能已经有另一架无人机覆盖了自然重复覆盖惩罚就把奖励压低了。这时候训练网络拿着旧经验往一个方向更新结果就是在线表现上下乱跳。我的处理方式有三个层面减小回放池容量到20000让旧样本更快被遗忘。采用软更新目标网络让训练目标的变化尽量平滑。对样本按时间步加权采样近期样本被抽中概率更高。其中第三个做法最有效。实现上可以在经验元组里加一个时间戳采样时先随机抽一批再按样本新旧程度加点权重不需要特别复杂的PER优先经验回放。整套方法没有任何论文依据纯粹是工程调出来的但效果确实好。如果你发现训练曲线在300回合以后开始剧烈抖动优先检查这三个点大概率能解决。4.2 奖励尺度失衡问题再说奖励设计。如果直接把覆盖率当奖励覆盖率是0到1的小数训练初期网络预测的Q值也会在0到1附近徘徊。但一旦加入了重叠惩罚重叠率可能到2或者3奖励就出现负数了。当时调参的时候发现一个问题如果beta1.0单个智能体从“不重叠”学到“为了拉开距离放弃覆盖用户”反而是最优策略因为重叠惩罚压过了接入奖励。我后来把beta压到0.5这个问题才缓和。经验是重复覆盖惩罚的力度不应超过基础接入奖励的一半除非你明确知道自己在做什么。4.3 局部观测信息缺失导致的反学效应有很长一段时间覆盖率卡在0.75上不去。后来逐步排查发现问题是无人机的“局部观测信息遗漏了自身容量利用率”。只看覆盖用户数而不看自身容量余量会导致无人机在某个区域明明已经满负荷了还执着于把那块区域的用户全部纳入覆盖宁可重叠也不愿去拓展新区域。我当时是在状态里加了一个“当前接入数除以容量”的特征效果立竿见影。这种特征往往比很多人直觉中更关键可以归入“容量感知因子”。4.4 训练初期崩溃训练初期最容易遇到的问题反而是网络崩溃。因为初始探索率很高无人机大部分时间在做随机动作偶尔遇到一个较高的覆盖奖励样本比较稀疏如果提升学习率或者batch过大网络直接发散Q值大到爆炸。解决方式很朴素先固定一个baseline场景反复只训练一架无人机的目标网络让它先学会在该场景下保持当前覆盖再扩展到多智能体同时训练。也可以说是迁移学习的一种朴素使用。如果你做这个项目时发现loss快速增大可以先从学习率1e-3减小到5e-4并把总奖励的scale压缩到[-1, 1]区间内。5. 常见问题速查表与调试技巧调试久了我发现很多问题都集中在一张速查表上这里整理出来你可以直接对照排查现象可能原因快速解法覆盖率一直停在0.6以下奖励信号太稀疏或没有容量感知特征添加重复覆盖惩罚和容量感知特征检查奖励绝对值是否明显大于0多无人机扎堆重叠惩罚过小或缺失增大beta到0.5~1.0观察是否出现过度分散训练曲线剧烈震荡非平稳性问题学习率过高回放池过大软更新tau调小到0.002学习率降到5e-4回放池容量减小到20000每架无人机动作始终是悬停epsilon衰减太快探索不足放缓衰减曲线延长探索期到800回合以上不同随机种子结果差异巨大奖励函数对不同布局过于敏感用户位置采样时加入固定种子先定基准场景再调试目标网络跟当前网络差距过大软更新系数过大tau默认0.005即可不要超过0.01调试技巧上我特别想强调日志的重要性。很多玩家看训练曲线只看奖励和覆盖率但我建议把每架无人机每个epoch的状态观测、选择动作、即时奖励都打印出来至少打印到文件中。有一次我发现某无人机在连续200回合里一直选择同一个方向的动作排查后才发现是状态特征里“最近邻距离”这个数值没有做归一化导致网络输入的值域失衡某些神经元输出永久饱和。如果不看日志只看曲线这个问题可能要多熬一个礼拜。另外一个技巧是先固定用户位置只用几个固定种子跑实验。如果直接随机生成用户位置训练差异会被环境随机性掩盖你根本分不清是算法改进了还是随机种子带来的波动。等所有策略调试稳定后再换随机布局验证泛化能力。6. 后续可以怎么改目前在实现上还有几个明显的扩展方向我个人比较看好第一动作空间改连续。无人机的移动本质上应该是连续控制离散化的7个动作虽然简单但在精细覆盖场景下会浪费很多步数在来回调整上。可以做连续动作版本的DDPG或者TD3输入连续动作输出加一个高斯噪声做探索。第二引入用户移动模型。现实场景中用户是在流动的如果加入随机游走模型会体现出无人机真正“跟踪覆盖”的价值而不是静态求解。这是从仿真走向实用的一大步。第三异构无人机编队。我目前的模型假设所有无人机覆盖半径和接入容量相同现实中可能有大覆盖低容量高空长航时与小覆盖高容量低空近距的混编。此时每个智能体的观测维度和动作空间都不同独立学习框架可以很自然地扩展。第四局部观测里加入环境拓扑信息。比如把用户密度网格图编码成一个小尺寸的矩阵通过卷积网络提取局部空间特征。这会显著提升观测的信息量但也会增加训练成本需要根据算力量力而行。这段代码改起来不难环境类和Agent类都做好了模块隔离你如果想试试某个新想法比如改奖励函数、换网络结构只需要在对应类里改几十行代码。我做这个项目的最大体会是多智能体强化学习不是什么玄学它更多是“场景建模奖励设计耐心调参”的组合。奖励设计决定上限网络结构决定下限调参只是让结果尽量靠近上限。代码我已经写成了模块化结构环境、智能体、训练逻辑都是独立可替换的。如果你正在做相关的无人机通信网络仿真建议先把奖励函数和你的物理模型对齐再考虑用多复杂的学习算法。我也踩过“网络越深越好、算法越新越好”的坑但最终起作用的关键点还是回归到了问题建模本身。希望这篇文章能帮你少走一些弯路。
阅读完成 · 觉得有帮助?