课程大纲
学习感悟
强化学习一直是我非常感兴趣的领域。为了了解强化学习的原理,我也曾看过伯克利大学的CS 294-112课程来了解相关的知识,但是一直没有找到合适的教程去实践体验一下。这也是7日营里科科老师提到的国内强化学习存在的一个问题,缺少一个难度适中的实践教程,导致强化学习的门槛较高。
幸运的是,百度飞桨推出了这期7日营。全程学习下来我能感受到这个课程真的诚意满满。首先,这门课的难度适中,省略了绝大部分公式推导,着眼于让大家能够尽快上手体验一下强化学习。这个切入点我觉得是非常合适的,市面上不缺深入推导公式的课程,也不缺科普,缺的正是这种让人能够体验强化学习,引起学习兴趣的课程。
省略公式推导并不意味着这次课程的含金量低,相反,科科老师对于sarsa、Q-learning、DQN、DDPG这些强化学习算法的原理都讲得非常全面且浅显易懂,关键创新点也没有落下。建议大家去看看课程,这里就不赘述。
最大的收获
图一是DQN算法的流程,从这个流程图可以很容易看出model、agent、env的交互流程以及obs、action、loss在其中是如何传递的。图二则是在图一的基础上,进行代码层面的抽象,把agent、model和algorithm封装起来。结合这两张图去看代码就会发现这个代码层面的封装真的做得非常好,逻辑清晰。如果想改变网络结构,只需改动model中的网络结构即可。如果想对模型更新的算法进行改动,则只需改动algorithm。如果想在交互层面上做文章,则在agent里修改。这样的设计允许我们在解决不同的强化学习任务时,只需做尽可能少的改动,大部分代码都直接复制粘贴即可完成迁移。
实际上对于每个算法,科科老师都有给出对应算法的流程图。对于看过的论文,学过的方法,我一直苦恼于没法用比较形象的方式表达出来,与别人交流的时候通过文字描述又会啰嗦一大堆事后想起来完全没必要的解释。科科老师这种配图解释模型运作机理的形式,以及由此延伸出的代码设计方法都使我深受启发。
对强化学习的理解
我们来想象一个任务场景,一个探险家(agent)手持一个设备(algorithm,记录Q信息)在漆黑的地穴(env)中寻找宝藏。
地穴就是强化学习中的environment,又像游戏中的裁判。它需要具备的功能有以下几点:
- 状态更新(step)。输入当前state和action,能够计算出下一个state是什么。
- 输出奖励(step)。根据self.state,计算当前reward的功能。
- 额外的规则判断(done)。例如,什么时候任务结束,任务的一些边界设置等等。
- 额外的功能。任务重置(reset),显示图像(render)等。
探险家就是强化学习中的agent,它一般是与环境配套的(因为不同的环境需要不同的action来交互,就像矿洞探险需要矿工,菜田探险需要菜农,海底寻宝需要海王一样,agent都要换,但各个agent之间外在区别估计就在于obs和action接口的不同)。它需要具备的功能有以下几点:
- 作出行为决策(sample)。根据手中的指示器/随意走,执行一个行为action,与环境进行交互。
- 看指示器(predict)。看指示器的结果,借鉴结果来行动。sample其实常常包含predict,区别在于sample获得的动作有可能是看指示器得到的,有依据的,也可能是随意的。
- 更新手中的指示器(learn)。根据自己试验得到的经验更新指示器。
- 拿到一个指示器的壳子(build_program)。对于sarsa和Q-learning方法来说,agent里其实没有build_program这个函数,但这并不意味着这个探险家不需要拿到指示器壳子。仔细观察sarsa和Q-learning中agent的代码就会发现里面有一个Q = np.zeros(…)这就是他们的build_program,只是这个指示器太简单了,没必要写个函数,甚至不需要额外的指示器核心(algorithm),壳子就已经是本体了。而对于DQN和DDPG这种复杂点的方法来说,就需要一个build_program函数。那么这两种有什么区别呢?sarsa和Q-learning中的指示器就像是一个简陋的地图,不需要额外设计核心(algorithm),而DQN和DDPG中的指示器就像是一个导航/小度智能/百度之类的,复杂的指示器。由于它复杂,壳子和核心(algorithm)要分开搭。所以在agent可以先搭建一个指示器的壳子build_program。在示例代码中我们可以看到,它实现的功能就是初始化两张动态图。只要能和里面的核心algorithm交互就行,真正的算法额外抽象出来,这样也方便更换不同的算法。
指示器核心(algorithm)就是帮助我们做决策(action)的。它需要具备以下功能:
- 预测(predict)。这里预测的结果可以有两个,action和Q。action是我们的终极预测目标,但是我们缺少预测action的依据。reward对于环境而言是已知量,但它是仅与env中state相关的量,与action无关。如果我们能够将reward和action产生联系,那么我们就能通过已知的reward来选择action。Q就是我们构造的联系。Q就像是对环境reward的一个拓展,对于爬虫找终点任务而言,每个state有reward,但是每个格子state对应的各个action的reward’是不可知的;对于一些游戏任务而言,各个状态对应多少分通常是可知的,但是在各个状态做出什么action的reward’是不可知的。Q则帮助我们将仅与state相关的reward拓展到了和state、action都相关,从而让我们对action的预测有了依据。
对于sarsa和Q-learning而言,Q的更新依靠的是公式。而action的选择依据就是选择Q最大的action。对于DQN和DDPG而言,由于状态空间连续,一个简陋的表格记不下了,那就用一个网络来记录Q信息,这就是critic表格。而actor网络的作用就是在给定state下,选择使得Q最大的action。所以DDPG的网络结构是actor网络输出action,使得critic网络输出的Q最大。 - 学习(learn)。关于学习,我有一个个人理解,不知道正确与否,就是对于给定的任务。只要它每个状态的reward是固定的,那么最终能学到的Q信息也是固定的。以虫子走迷宫为例,4*4格的迷宫,终点在(4, 4),终点reward是1,其余全是0。Q网络的更新就是一个迭代的过程,根据那条Q的更新公式(粘贴不上来)。不断将终点的reward蔓延到所有state的所有action上,就像波纹一样传递(源?)。这个蔓延是单向的,因为全图只有一个reward。比如衰减因子是0.6,那么(4,3)和(3, 4)的对应方向的reward就是0.6,再往前一格的对应动作Q就是0.36,不断蔓延覆盖整个表格。如果另外一个点也有reward,那么影响就复合。最终迭代到稳定的情况时,表格就固定下来了。连续动作的估计也是这个道理,只要state空间每个点对应的reward是固定的,最终Q空间也会是固定的,critic网络也会有一个学习的极限。
- 额外的设计。如DQN和DDPG中固定Q目标要用到的更新网络函数。
上述两个功能一个是指导我们做出决策,相当于在指示器界面显示个答案,让探险家去执行。而另一个就是让自己不断完善。个人感觉只要能具备这两个功能,都能作为algorithm【似乎找到了水论文的切入点】。
举个例子作为对上述理解的总结吧,正好也作为终极项目的思路记录。
以股票预测为例。首先这是一个连续状态连续动作的任务,因为股价state和买入卖出股数action都是连续的,可以使用DDPG。
思考如果要我们设计这个任务的env,要怎么做。为了降低难度,只对一支股票进行操作。那obs/state应该是什么呢,obs应该是有助于判断买入卖出操作的依据,比如历史峰值,k线,上一操作日收盘价,开盘价,前几个时刻的买入卖出数,当前剩余资金,当前已有股数,当前时刻股价等等。然后返回的reward肯定是利润值,终止条件是破产或者超过一定天数。env的step函数就是加载下一刻的股价(agent与env交互产生的影响可能只在于前几个时刻的买入卖出数,当前剩余资金,当前已有股数之类的),并且计算state的几个值,还有当前利润。
agent自然就是买入卖出的股数,用正负浮点数表示就行,但是这样的话action的上下限无法确定,因为手中资金一直在变,可以买卖的股数也在变。所以设置action范围为(-1, 1),表示用当前剩余资金的比例来操作。
algorithm就是调参的事了,看obs维度来确定结构。具体细节还没想好,待定吧。