资讯动态

基于深度强化学习的车联网通信资源分配Python实现与优化

发布时间:2026/10/3 9:31:46 来源:尧图企业网站定制
简介这份资源是面向计算机相关专业学生与深度学习方向学习者的毕业设计项目包主题为基于深度强化学习的车联网通信资源分配优化系统。项目围绕车联网场景下的通信资源分配问题采用深度强化学习思路进行建模与优化适合用作毕设、课程设计或期末大作业也可供需要项目实战的开发者参考借鉴。压缩包共21个文件以13个Python源码文件为主另含6个编译缓存文件、1个zip子包与1份Markdown项目说明整体约82KB源码均带注释便于理解算法实现与模块划分。内容涵盖MADDPG、MADQN、SAMADDPG等多种多智能体强化学习方法的实现以及环境建模、经验回放、随机基线等模块结构清晰可直接运行验证。目前已有961人学习下载适合希望快速获取完整可运行方案、对照源码梳理算法流程与排错思路的读者。1. 车联网资源分配为什么值得用深度强化学习来做车联网里的通信资源分配说白了就是在车辆、路侧单元、基站之间把有限的频谱、时隙、功率这些资源分给谁、分多少的问题。传统做法靠凸优化或启发式算法前提是信道状态、车辆位置、业务需求都能提前建模清楚。可现实是车流随机到达、信道快速时变、V2V 和 V2I 链路互相干扰模型根本写不准。深度强化学习算法之所以被大量搬进这个场景就是因为它不需要精确的环境模型智能体通过不断试错学出一套分配策略环境变了还能继续适应。这个毕设项目标题指向的正是一套用 Python 实现、带注释、能跑通训练和评估闭环的车联网通信资源分配优化系统。适合正在做相关毕设、想找一个能复现的 DRL 落地骨架、又不想从零搭环境的人。2. 把资源分配问题翻译成强化学习能吃的形式2.1 状态、动作、奖励三件套怎么定深度强化学习落地车联网资源分配第一步不是写网络而是把问题形式化成马尔可夫决策过程。状态通常包含当前各链路的信道增益、车辆位置与速度、队列积压量、剩余功率动作是给每条 V2V 链路选信道、给每条 V2I 链路分配功率档位奖励则要同时体现吞吐量和可靠性常见做法是 V2I 容量之和减去 V2V 链路中断惩罚。这里最容易翻车的地方是状态维度随车辆数线性增长车辆一多网络就训不动所以一般会做归一化和固定窗口截断。import numpy as np class V2XEnv: def __init__(self, num_v2v4, num_v2i4, num_channels4): self.num_v2v num_v2v self.num_v2i num_v2i self.num_channels num_channels # 状态 信道增益 队列 位置全部归一化到 0~1 self.state_dim (num_v2v num_v2i) * num_channels num_v2v num_v2i self.action_dim num_v2v * num_channels num_v2i # V2V选信道 V2I选功率档 def reset(self): self.channel_gain np.random.uniform(0.2, 1.0, (self.num_v2v self.num_v2i, self.num_channels)) self.queue np.zeros(self.num_v2v) return self._get_state() def _get_state(self): gain self.channel_gain.flatten() return np.concatenate([gain, self.queue / 10.0]).astype(np.float32)这段代码定义了环境的最小骨架。state_dim的计算方式决定了后面网络输入层大小action_dim用离散动作空间把「选信道」和「选功率」拼在一起方便用 DQN 这类算法直接处理。reset里信道增益用均匀分布模拟真实项目里应该换成射线追踪或 3GPP 信道模型生成的数据。队列除以 10 是经验归一化系数具体值要看你的业务到达率量级。2.2 奖励函数设计别让智能体学会摆烂奖励函数是整个项目里最玄学的部分。我见过太多人把奖励写成简单的吞吐量之和结果智能体学出来的策略是拼命给某一条链路堆功率其他链路全饿死。合理的做法是把 V2I 容量和 V2V 可靠性做成加权和再对违反约束的动作加惩罚项。权重不能拍脑袋定一般先用 0.5 比 0.5 跑一轮看两条链路的性能曲线是否均衡再微调。def compute_reward(self, action, v2i_rate, v2v_success): # v2i_rate: 每条V2I链路的速率, v2v_success: 每条V2V是否满足时延约束 throughput np.sum(v2i_rate) reliability np.mean(v2v_success) # 惩罚V2V中断比例过高时扣分 penalty max(0, 0.9 - reliability) * 10.0 reward 0.5 * throughput 0.5 * reliability * 10 - penalty return rewardthroughput和reliability量纲不同所以给可靠性乘了 10 做尺度对齐。penalty里的 0.9 是可靠性阈值低于它才开始扣分这样智能体不会因为偶尔一两次中断就被过度惩罚。这几个系数都需要在训练日志里观察 reward 曲线和实际性能指标是否同步上升来调整。2.3 选 DQN 还是 DDPG动作空间说了算动作空间离散就用 DQN 或它的改进版连续就用 DDPG、TD3、SAC。车联网资源分配里信道选择天然离散功率分配可以是连续值也可以是离散档位。如果全用离散DQN 最省事但动作维度一高比如 10 辆车 10 信道Q 网络输出层会爆炸。常见做法是功率离散成 3 到 5 档动作维度控制在几十以内。如果坚持连续功率DDPG 更合适但训练稳定性差需要经验回放和目标网络软更新来兜底。import torch import torch.nn as nn class QNetwork(nn.Module): def __init__(self, state_dim, action_dim, hidden128): super().__init__() self.net nn.Sequential( nn.Linear(state_dim, hidden), nn.ReLU(), nn.Linear(hidden, hidden), nn.ReLU(), nn.Linear(hidden, action_dim) # 输出每个离散动作的Q值 ) def forward(self, x): return self.net(x)网络结构故意保持浅层因为车联网场景的状态维度通常不超过几百深层网络反而容易过拟合且训练慢。hidden128是起点如果训练曲线震荡厉害可以降到 64如果欠拟合再升到 256。输出层不加激活函数因为 Q 值可以是任意实数。3. 用 Python 把训练和评估闭环跑起来3.1 经验回放与目标网络的实现细节DQN 能训起来靠的就是经验回放池打散样本相关性和目标网络稳定 Q 值目标。回放池容量一般设 10000 到 50000太小样本不够多样太大旧策略的数据会拖后腿。目标网络更新用软更新比硬更新平滑tau 取 0.001 到 0.01 之间。import random from collections import deque class ReplayBuffer: def __init__(self, capacity20000): self.buffer deque(maxlencapacity) def push(self, state, action, reward, next_state, done): self.buffer.append((state, action, reward, next_state, done)) def sample(self, batch_size): batch random.sample(self.buffer, batch_size) state, action, reward, next_state, done zip(*batch) return (np.array(state), np.array(action), np.array(reward), np.array(next_state), np.array(done)) def __len__(self): return len(self.buffer)deque设了maxlen后自动丢弃最旧的数据省去手动管理。sample返回的是 numpy 数组后面转 tensor 时注意done要转成 float 才能参与计算。batch_size 从 64 起步显存够就上 128 或 256。3.2 训练主循环与关键超参数训练循环里几个容易忽略的点epsilon 衰减不能太快否则智能体还没探索够就锁死在次优策略每轮结束要判断是环境自然结束还是达到最大步数奖励要做裁剪防止梯度爆炸。def train(env, q_net, target_net, buffer, episodes500, batch_size64, gamma0.95, lr1e-3, epsilon_start1.0, epsilon_end0.05): optimizer torch.optim.Adam(q_net.parameters(), lrlr) epsilon epsilon_start for ep in range(episodes): state env.reset() total_reward 0 for step in range(200): # 每轮最多200步 if random.random() epsilon: action random.randint(0, env.action_dim - 1) else: with torch.no_grad(): q_values q_net(torch.FloatTensor(state).unsqueeze(0)) action q_values.argmax().item() next_state, reward, done, _ env.step(action) buffer.push(state, action, reward, next_state, done) state next_state total_reward reward if len(buffer) batch_size: s, a, r, ns, d buffer.sample(batch_size) s torch.FloatTensor(s) ns torch.FloatTensor(ns) a torch.LongTensor(a).unsqueeze(1) r torch.FloatTensor(r).unsqueeze(1) d torch.FloatTensor(d).unsqueeze(1) q q_net(s).gather(1, a) with torch.no_grad(): q_next target_net(ns).max(1)[0].unsqueeze(1) q_target r gamma * q_next * (1 - d) loss nn.MSELoss()(q, q_target) optimizer.zero_grad() loss.backward() # 梯度裁剪防止爆炸 nn.utils.clip_grad_norm_(q_net.parameters(), 1.0) optimizer.step() if done: break # epsilon 线性衰减 epsilon max(epsilon_end, epsilon - (epsilon_start - epsilon_end) / episodes) # 软更新目标网络 for tp, p in zip(target_net.parameters(), q_net.parameters()): tp.data.copy_(0.005 * p.data 0.995 * tp.data) print(fEpisode {ep}, Reward: {total_reward:.2f}, Epsilon: {epsilon:.3f})gamma0.95比常见的 0.99 小因为车联网决策更看重即时回报折扣太大反而让智能体短视。clip_grad_norm_是后悔药没有它训练中途 loss 突然飙到 nan 是常事。软更新系数 0.005 对应 tau改大更新快但不稳改小稳但学得慢。3.3 评估阶段看哪些指标才算数训练 reward 涨了不代表策略真的好。评估必须单独跑一批固定随机种子的场景统计 V2I 平均吞吐量、V2V 中断概率、资源利用率三个指标和随机分配、贪心分配做对比。如果 DRL 策略只在训练分布内表现好换个车辆数就崩说明过拟合了得加域随机化。def evaluate(env, q_net, episodes50): metrics {throughput: [], outage: [], utilization: []} for _ in range(episodes): state env.reset() done False while not done: with torch.no_grad(): action q_net(torch.FloatTensor(state).unsqueeze(0)).argmax().item() state, _, done, info env.step(action) metrics[throughput].append(info[v2i_rate]) metrics[outage].append(info[v2v_outage]) metrics[utilization].append(info[resource_used]) return {k: np.mean(v) for k, v in metrics.items()}评估时 epsilon 必须设为 0只用网络输出的贪心动作。info字典需要环境在step里返回这是很多人写环境时漏掉的。跑 50 轮取平均是为了消除随机性轮数太少方差大结论不可信。4. 避坑与排查训练不收敛时先查这几处4.1 奖励曲线震荡不上升现象是 reward 在某个值附近来回跳几百轮都不见涨。原因通常是回放池太小导致样本相关性高或者学习率太大让 Q 值估计发散。解决方法是把回放池容量翻倍、学习率降到 1e-4再检查奖励里各项量纲是否差了几个数量级量纲不统一会让网络只优化大项。4.2 智能体学会「摆烂」策略现象是所有动作都选同一个信道或最小功率reward 稳定但性能很差。原因是惩罚项太弱或者奖励里可靠性权重太低智能体发现摆烂也能拿分。解决方法是提高中断惩罚系数或者在动作选择时加动作屏蔽把明显违规的动作直接置为负无穷。4.3 换车辆数就性能暴跌现象是训练时 4 辆车表现很好评估时加到 6 辆就崩。原因是网络输入维度固定状态里车辆数变了维度对不上或者策略过拟合到特定车辆数。解决方法是状态设计成固定最大车辆数、不足补零训练时随机化车辆数做域随机化。4.4 loss 突然变成 nan现象是训练到一半 loss 打印出 nan后面全废。原因是梯度爆炸常见于奖励值过大或网络输出未做限制。解决方法是在 loss.backward() 后加梯度裁剪奖励做归一化或裁剪到固定区间学习率再降一档。4.5 评估指标和训练 reward 不同步现象是训练 reward 一直涨但评估吞吐量不涨甚至下降。原因是奖励函数和真实性能指标有偏差智能体在钻奖励的空子。解决方法是把评估指标直接纳入奖励设计或者定期用评估指标做模型选择而不是只看训练 reward。5. 让策略从仿真走向可用的几个进阶技巧训练跑通只是起点真正让这套东西有价值的是泛化能力和部署可行性。第一个技巧是课程学习先在小规模场景2 辆车 2 信道训到收敛再逐步增加车辆数和信道数每次增加后加载上一阶段的网络权重继续训。这样比一上来就大规模训练快得多也不容易卡在局部最优。第二个技巧是动作空间分解把「选信道」和「选功率」拆成两个子动作分别输出动作维度从乘积变成求和网络输出层小一个量级训练稳定性明显提升。第三个技巧是推理加速。训练用 PyTorch 没问题但部署到车载单元或边缘服务器时可以把网络导出成 ONNX 再用 onnxruntime 推理单次决策延迟能从毫秒级降到微秒级。导出时注意输入维度要固定动态维度虽然 ONNX 支持但部分推理引擎兼容性差。技巧适用阶段主要收益代价课程学习训练初期收敛快、不易卡局部最优需要设计课程表动作分解动作维度大于 50网络小、训练稳需要改环境接口ONNX 导出部署阶段推理延迟降一个量级动态维度兼容性差域随机化泛化要求高换场景不崩训练轮数增加最后一个习惯每次改完奖励函数或网络结构先跑 50 轮看趋势别一上来就 500 轮省下来的时间够你多试好几组超参数。这套东西我踩过的坑比跑通的次数多希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑