在envs/SingleAgent
路径下配置了四个版本的环境:
0421 (v2.0)
:最基础环境,小车固定初始化位置和位姿,无重建的室内场景,环境的图像尺寸(128$\times$128)较小。0505 (v3.0)
:初始位置和位姿随机、增加了室内真实环境模型,但是智能体交互时采样速率极慢。0508 (v3.1)
:在0505 (v3.0)
版本上增大图像尺寸(320$\times$240),有更高的观察刷新频率,但是智能体交互时采样速率极慢。0510 (v3.2)
:在0421 (v2.0)
版本上增加初始位置和位姿随机,其他与0421 (v2.0)
版本相同
0505 (v3.0)
和0508 (v3.1)
两个版本的环境可能由于需要渲染室内环境,导致采样速率很慢(并行20个环境后的采样速率15步/s),因此在本次RL实验中未采用。我们仅使用0421 (v2.0)
(固定初始)和0510 (v3.2)
(随机初始)环境进行训练。
我们采用了tianshou
库实现的PPO算法,并把trick拉满,包括:正交初始化、状态归一化、奖励归一化、优势归一化、重计算优势、梯度剪裁、GAE计算优势、动作加噪、策略熵正则项等。
奖励函数:我们始终仅使用了mine_toy.py
中定义的简单的密集奖励,它定义:除了完成目标获得环境给予的+10
奖励外,执行动作前后到目标点的距离差会作为辅助奖励。实验中,我们曾设计过额外的奖励,但最终没有使用:在观察到小车总能到达目标点附近但是朝向不正确,导致不能完成任务后,我们设计了朝向奖励。将四元旋转数转换为欧拉角后,计算执行动作前后与目标点的角度差作为辅助奖励,使得小车更偏向目标方向时获得正奖励,偏离目标方向时获得负奖励。但是发现该奖励刺激了小车在前进时保持不停的自转,故未使用。
注:
mine_toy.py
中的密集奖励有问题,它将小车到坐标原点的距离当作了到目标点的距离。实验中我们已将其修正。
超参数:我们使用了下表中所示的超参数取值,其他超参数均与PPO论文中超参数取值保持一致。
变量名 | 含义 | 取值 |
---|---|---|
学习率 | 3e-4 * | |
批量大小 | 256 | |
衰减因子 | 0.9 |
*: 在基于checkpoint继续训练时,有时学习率设为1e-4
mine_toy.py
中环境类EpMineEnv
初始化时设置:
only_state | only_image |
---|---|
True |
False |
此时state
为七元组(四元旋转数+三元位置坐标)。由于state
是全局信息,且环境初始化无随机性,因此该任务最为简单。下图展示了训练过程中每局回报与训练步数的变化曲线。训练在3e5
步时就已收敛。测试性能时,我们在10个随机种子下跑100局,完成目标的成功率99%,完成目标平均需要40步左右。
网络架构:actor和critic都是具有两个隐藏层的MLP,隐层中神经元个数都是64。
网络参数checkpoint路径:logs/EpMine/ppo_v4/42/230508-065453/policy_best.pth
由于该任务较简单,因此训练和测试代码未单独保存,后续实验代码在此代码基础上做修改,因此已被覆盖。
only_state | only_image |
---|---|
False |
True |
这是RL大作业所要求的输入。由于图像中的视野受限,且视角固定,此时环境属于部分可观测(Partially Observable)。为了解决PO问题,我们采用了Nature DQN的思路,选择连续八帧的图像作为输入,利用CNN网络分别对八帧图像提取特征后,将特征向量拼接作为actor和critic网络的输入。
网络架构:CNN网络基本与Nature DQN所使用的CNN保持一致,差异仅在nn.Flatten
前加了全局池化层来控制特征向量的维度。CNN网络代码如下(一些reshape
等的预处理代码省略):
nn.Sequential(
nn.Conv2d(3, 32, kernel_size=8, stride=4),
nn.ReLU(inplace=True),
nn.Conv2d(32, 64, kernel_size=4, stride=2),
nn.ReLU(inplace=True),
nn.Conv2d(64, 64, kernel_size=3, stride=1),
nn.ReLU(inplace=True),
nn.AdaptiveAvgPool2d(1),
nn.Flatten()
)
因此,CNN的输入是大小为B×8×128×128×3
的批量多帧图像,输出是大小为B×512
的特征向量,其中$B$表示批量大小。策略网络actor和价值网络critic都是有两个隐层的MLP,隐层神经元数量分别为128和64,然后actor输出层映射到动作的条件概率(维度3),critic映射到状态价值(维度1)。
训练过程中回报收敛曲线如下图所示,训练在8e5
步后趋于稳定,且收敛值与固定位置+状态输入的agent收敛值十分接近。测试性能时,同样使用10个随机种子rollout100局,成功率80%,但是平均所需步数100步左右,且观察到小车更加抖动,控制过程不如之前流畅。因此,PO问题其实没有完全解决,但是该方案已经取得了可以接受的效果。
网络参数checkpoint路径:logs/EpMine/ppo_v7/42/230509-121505/policy_best.pth
复现:执行如下命令训练智能体:
python train_ppo_consecutive_frame.py
执行如下命令查看控制效果:
python eval_policy_consecutive_frame.py
norandom_image.mp4
反思:固定初始化的环境,其训练结果大概率存在过拟合现象,或者可能仅是记住了固定的一条路。因此测试的结果并不能说明智能体已经学会了导航任务,所以需要在随机初始化的环境中继续实验。
only_state | only_image |
---|---|
True |
False |
起初我们依然使用七元组信息进行训练,但是发现始终无法学到有效的策略。同时,由于我们是基于固定初始+状态输入的checkpoint及继续训练,在训练后我们发现:若初始点在原固定初始点附近,智能体有概率能完成目标,而在其他位置初始时,智能体学会了摆烂(顶着墙壁不动)。这印证了我们认为固定初始环境下训练过拟合的猜想。
反思结果我们认为,即使七元组信息能明确告知智能体的精确位置、位姿,但是缺少了全局地图、目标点方位、障碍物等信息,导致训练失败。因此我们在七元组的基础上引入了另外两元信息:到目标点的距离和方向。实验证明这二元信息对导航任务至关重要,智能体成功收敛到有效的策略上。
收敛的回报值较固定环境下略小一些,这是因为固定初始点距离目标点较远,因此容易获得更多的定义的密集奖励;而随机初始化的位置大概率比固定初始点离目标点更近,所以最终回报略小。比较收敛速度可以看出,随机初始化的确使得导航任务更加困难,在8e5
步才收敛。测试10个随机种子下rollout1000局,成功率67.2%(约在65~70%之间)。
网络架构:actor和critic都是具有两个隐藏层的MLP,隐层中神经元个数都是64。
参数checkpoint路径:logs/EpMine_0505_random/ppo_v9/42/230511-034009/policy_best_672.pth
由于下一个实验是该实验的“升级版”,代码也是基于该实验代码继续修改,因此已被覆盖。
only_state | only_image |
---|---|
False |
False |
在上次实验中,我们观察到小车总能快速到达目标点附近,但是小车朝向不正确,而在旋转车身时又被放置目标的台子卡住陷入死循环,导致任务失败。我们尝试加入朝向奖励,但是却激发出了奇怪的行为,因此本实验(最终实验)同时使用九元组state
和连续4帧的图像作为输入进行随机初始化的导航任务。
网络结构:CNN与之前保持一致,因此输入是大小为B×4×128×128×3
的批量多帧图像,输出是B×256
的特征向量。而后将256维的图像特征向量和9元组state
向量同时映射成64维特征向量,并拼接成128维向量。actor和critic网络分别用一个单隐层大小为64的MLP将拼接后的128维向量映射到动作条件概率和状态价值。
训练中回报收敛图如下所示,此实验的奖励函数略有修改。由于开始尝试PPO未果,中途曾换成过SAC算法,因此调整过奖励放缩参数reward scale
,导致奖励变成:完成任务仍然是获得+10
奖励,但是中间的密集奖励变成原来的10倍。但是SAC效果更差,所以又换回PPO,但没改奖励函数。训练在5e5
步终止是因为提前满足了另一个终止条件:测试时的平均奖励超过阈值。由于开始的失败经历导致最终训练时把阈值设的略小了一点,对结果预期较悲观,但是实际训练结果其实很乐观。
训练结束后,测试时使用10个随机种子rollout1000局,成功率85.3%(约在85%~90%之间),平均所用步数约30步。这一结果稍微逊色于固定初始+状态输入的智能体,由此证明这套方案能够在随机初始化的场景中完成导航任务。
参数checkpoint路径:
-
logs/EpMine_0505_random/ppo_v14/42/230514-020416/policy_best_1684041860.147892.pth
-
logs/EpMine_0505_random/ppo_v14/42/230514-054417/policy_best_1684054347.7338653.pth
无聊的发现:policy_best_1684041860.147892.pth这套参数在随机种子设置为48、测试局数>=100的情况下,成功率能达到90%,是实验中观察到的随机初始化环境中的成功率上限。
复现:执行如下命令训练智能体:
python train_ppo.py
执行如下命令查看控制效果:
python eval_policy.py