这一学期学了不少强化学习的相关内容,但是还没有动手写过代码,不知道从何下手,所以就从github上面找了一个强化学习游玩flappybird的项目来看,这个项目是六七年前的了,有点老,直接跑因为pytorch的api修改了,会报错,所以我fork了这个仓库,然后修改了一下。如何想要直接跑可以参考我这个仓库https://github.com/axgn/Flappy-bird-deep-Q-learning-pytorch,这一篇文章主要讲一下dqn的相关内容(这里默认大家都已经知道它的前身q-learning算法),还有我对这个仓库里的代码的一些理解。
为什么要有dqn算法
在q-learning中,我们会建立一张存储每个状态下所有动作Q值的表格。这个表格中的每个值代表在某一状态下选择某一动作时的动作价值。而如果我们的状态特别多,那么这个方法就会开始有心无力了。例如,如果我们将一张$100\times100$的RGB图片视作状态的话,那么RGB图片里有$100\times100\times3$个数值,而每一个数值都有256个可能值,所以最终的状态数量是$256^{100\times100\times3}$ 种,这么大的表格想要在计算机中完整存储是不可能的,进行相应的计算更加不可能。所以便有了dqn这种通过
dqn算法的核心内容
相关代码逐段解析
一些其他的内容
因为我这里是主要讲dqn,就不详细讲解Flappy-bird相关实现代码了,如果感兴趣可以自行查看。不过我还是想要分享一些看代码时的心得。
- 一定要会用搜索功能。最开始要先找到程序的入口,常间的项目一般都会有main函数,如果是多线程也可能会有thread.start之类的,这些都是可以通过搜索找到的。然后在vscode里可以不仅可以在当前文件里进行搜索,也可以在整个工作区进行搜索。如果是用vscode的话,一定要理解工作区的概念,我后面应该也会发文章讲一些vscode中关于工作区的小trick。
- 一定要分模块去看。程序设计语言基本都有函数,类等概念,还会分文件组织代码,这都是为了将代码模块化,这样对人才更好理解,所以应该充分利用这一特性。一般我的习惯是会逐层去看,而不是一遇到函数调用就直接一直深入下去,我会先弄清楚当前这个模块是在做什么,然后再看一下这一层直接调用的模块,把直接调用的模块读完,再接着读子模块。简而言之,就是一定要先把当前模块读完,再读子模块。
- 大概简单读完之后,就要debug一下代码,可以再一些刚刚读的过程中觉得比较重要的地方打上断点,然后逐步验证自己的想法是否正确,也可以看一下一些关键变量的值是否符合预期。
- 如果一些地方是对第三方库的接口调用,那么可以先问一问ai或者网上搜索了解这个第三方接口的基本作用。然后对当前模块代码有了整体的了解之后,再去查阅官方文档,了解这个接口的更详细信息。因为无论是从ai得到的还是在网上简单搜索得到的,如果涉及到一些比较复杂的接口,都会出现一些比较片面的情况,所以我最后还是会去看官方文档,以期得到一个更完整的认知。(而且,如果是一些比较有意思的接口我还会去看一下它究竟是怎么实现的,不过这就是个人兴趣的范畴了)