Learn by Doing
在实践中学习
编写自己的移植程序
你应该尽可能多的移植Deep RL核心算法,以达到每种算法都可以书写最简洁、正确的代码实现。这是截至目前最好的理解Deep RL 算法如何工作的方法,也能直觉洞察算法的特殊变现特性。
简单是关键
你应该合理安排自己的经历,先从简单的算法开始移植,然后逐步增加复杂程度。如果你开始时选择一个有很多可化换部分的算法,你将面临很大的逆境,你容易失去调试它的意志。这时Deep DL 新手经常面临的失败情况,如果你发现自己困在了这样的困境,不要灰心,尝试改变方向,选择一个更简单的算法,然后再研究复杂算法。
选择哪些算法?
你应该从VPG算法开始,然后大概按照以下顺序研究,DQN,A2C,PPO,DDPG。这些算法的简单版本仅用寥寥几百行代码(大约250~300行),其中一些算法代码行数可能更少(例如,一个简介的VPG可能80行完成)。先采用但线程编码,然后再使用并行运算。(至少选择一种算法尝试并行编程。)
聚焦理解
编写RL代码的宗旨时能够清晰、详细的理解算法。这是因为差的RL代码经常在沉默中失效,此时代码运行看似无误,但是智能体没能学会增氧解决问题。通常时算法中的某个方程被写错了,或者使用了错误的分布,或者数据被注入到了错误的地方。有时发现这些bug的唯一方法,就是用一双挑剔的眼睛去审阅代码,了解它正常工作的确切表现,找出哪里与正确行为有差异。发展这项技能知识需要你聚焦学术论文和代码移植,所以你需要花费大量的时间来阅读。
在论文中搜寻什么?
当基于一篇论文移植算法时,要搜索研究那篇论文,特别是ablation分析与补充材料。ablation让你可以直观的了解到哪些参数和子程序对算法的影响,这有助于诊断bug。补充材料会提供详细的信息,包含网络结构、优化超参数,你应该将自己实现的代码与这些细节对齐,以提升代码有效工作的几率。
不要过分拘泥于论文的细节
有时论文过于描述很多技巧性内容,然后这些并非严格需要,所以对此保持一点警惕,在可能的地方尽量尝试简化。例如,原始的DDPG论文建议采用一个复杂的神经网络结构和初始化方案,还有批量数据的规范化。这些并非严格需要,一些更好研究结果报告,采用的是简单的网络。另一例子,原始的A3C论文从不同的actor-learners中采用异步更新,但是结果显示同步更新也能很好工作。
不要过分拘泥于一个已经存在的代码实现
学习一个已经存在的代码实现,以获取灵感,但是不要过分拘泥于工程细节。RL 库通常选择抽象化使得其便于用于不同的算法,但是如果你仅仅是编写一个简单的算法或者一个单例,这些就没有必要。
在简单的场景里快速迭代
如果调试你的代码实现,尝试用简单的环境运行,这样学习效果可以很快展现,例如,在OpenAI Gym中,CartPole-v0, InvertedPendulum-v0, FrozenLake-v0, and HalfCheetah-v2(采用一个较短的时间维度——仅100或250步,而不是1000步)。没有在简单的环境里面验证代码可以有效工作之前,不要在像Atari或者复杂人形环境中调试。你的理想实验调整时间是5分钟,不要超出太多。这些小规模的实验,不需要特殊的硬件,在CPU上运行也没有太多的困难。
如果不工作,怀疑有bug
在你诉诸于调参之前,花一些经历来查找bug:大多数情况下,是有bug存在。不良的超参数能够明显的退化学习效果,但是如果你按照论文或者已有实现设定的参数,这将不会有问题。请谨记:如果你有一个重要bug,但有时还可以在一个环境中正常工作,尝试在不同的环境中验证算法。
测量所有
做一些测量功能,查看表象下面的事情。
当算法工作正常,增加实验复杂度
如果你移植的RL算法可以在一个简单的环境里正常的工作,那么尝试一个更难的环境。在这个实验环境,将会花费更多的时间,顺序是几个小时的实验,几天的实验。在这个阶段,特殊的计算资源是需要的,你可以尝试使用云计算服务。
保持这些习惯
这些习惯对你的利益不局限于学习RL的初始阶段,它们将加速你的研发进度。