本文基于百度深度学习库 PARL 完成
四轴飞行器的模拟器使用的是百度的 RLschool
文章目录
一、DDPG 算法的收敛问题探讨:
1. 传统方法:
在传统的思路中,对于四轴飞行器的控制我们应利用 4 个维度的动作输出
以控制 4 个电机
但是这样的方法收敛速度非常慢
我的理解是:这种情况下 4 个输出不但要学习环境的反馈变化,还要学习 4 者之间的搭配,所以导致学习时间非常长
达到收敛通常需要 100w steps 左右
2. 新思路探讨:
在本文中,让 DDPG 算法直接进行 5 个维度的输出
其中一个维度作为主控,同时控制 4 个电机的主电压
另外 4 个维度作为微调,对 4 个电机的电压做修正
其中设定输出电压为:主控电压+0.1*修正电压
最后效果非常好,5w-6w steps 左右就可以达到很好的收敛
收敛速度比前一种算法快了 20 倍左右!
二、安装依赖
pip install paddlepaddle
pip install parl
pip install rlschool
三、具体代码及解析:
3.1 库引入
import numpy as np
from parl.utils import logger
from parl.utils import action_mapping # 将神经网络输出映射到对应的 实际动作取值范围 内
from parl.utils import ReplayMemory # 经验回放
from rlschool import make_env # 使用 RLSchool 创建飞行器环境
from parl.algorithms import DDPG
import paddle.fluid as fluid
import parl
from parl import layers
3.2 超参数设置
GAMMA = 0.99 # reward 的衰减因子,一般取 0.9 到 0.999 不等
TAU = 0.001 # target_model 跟 model 同步参数 的 软更新参数
ACTOR_LR = 0.0002 # Actor网络更新的 learning rate
CRITIC_LR = 0.001 # Critic网络更新的 learning rate
MEMORY_SIZE = 1e6 # replay memory的大小,越大越占用内存
MEMORY_WARMUP_SIZE = 1e4 # replay_memory 里需要预存一些经验数据,再从里面sample一个batch的经验让agent去learn
REWARD_SCALE = 0.01 # reward 的缩放因子
BATCH_SIZE = 256 # 每次给agent learn的数据数量,从replay memory随机里sample一批数据出来
TRAIN_TOTAL_STEPS = 1e6 # 总训练步数
TEST_EVERY_STEPS = 1e4 # 每个N步评估一下算法效果,每次评估5个episode求平均reward
3.3 智能体 Agent 模块
class QuadrotorAgent(parl.Agent):
def __init__(self, algorithm, obs_dim, act_dim=4):
assert isinstance(obs_dim, int)
assert isinstance(act_dim, int)
self.obs_dim = obs_dim
self.act_dim = act_dim
super(QuadrotorAgent, self).__init__(algorithm)
# Attention: In the beginning, sync target model totally.
self.alg.sync_target(decay=0)
def build_program(self):
self.pred_program = fluid.Program()
self.learn_program = fluid.Program()
with fluid.program_guard(self.pred_program):
obs = layers.data(
name='obs', shape=[self.obs_dim], dtype='float32')
self.pred_act = self.alg.predict(obs)
with fluid.program_guard(self.learn_program):
obs = layers.data(
name='obs', shape=[self.obs_dim], dtype='float32')
act = layers.data(
name='act', shape=[self.act_dim], dtype='float32')
reward = layers.data(name='reward', shape=[], dtype='float32')
next_obs = layers.data(
name='next_obs', shape=[self.obs_dim