并行化(或者分布式)强化学习的本质是什么???
序言:读书的研究方向为强化学习,做学术自然开始着手做的事情就是阅读论文,不过读着读者相关的论文就发现了一些问题,强化学习方向的论文大部分都是上来给出一种在以往算法上的改进,给出具体改进算法的伪代码,然后说下简单的理解判断用来说明一下为什么这个改进的算法有效,但是这往往导致这些所谓的解释难以真正的对其算法给出解释,这也就慢慢变成大家花费大量的时间去拼模型,改算法,花着大大把的时间拿着几十万元一台的服务器死劲的开启了烧CPU和GPU的活动,却很少给出相应算法的详细解释。对于晦涩难懂的论文,再加上原文也往往没有给出什么太多的解释而是简单的往上加上大量的对比试验,十多个baseline,每个baseline算法再给出10多个数据集下的结果,然后就说,嘿,everybody,你看数据,我这个就是好用,但是这东西往往就是解释不清,说不明白,最后大家也就是知道了这个东西这么搞好用,原文给出了这么个解释,估计就是这样子的原因,这种情况下我想我们更需要去思考这些改进真正work的原因是什么,所以平时慢慢也就往这方面多了些思考,想的东西可能也是极为不对的,给出的我个人的解释往往也是错误大的很,不过这也是自己的一些观点和看法,这也本就不保证对错,再者这东西有真正绝对正确的那一说吗。在学术和科普之间的一种中间状态吧,半科普还带有些许学术的思考,或许该这么定位这个博客吧。
--------------------------------------------------------
引用前文博客的数据:
强化学习 —— reinforce算法中更新一次策略网络时episodes个数的设置对算法性能的影响 —— reinforce算法中迭代训练一次神经网络时batch_size大小的不同设置对算法性能的影响
ssh://devilmaycry@192.168.1.111:22/home/devilmaycry/anaconda3/envs/tf-14.0/bin/python -u /tmp/mode2/analysis.py batch_size 为: 1 mean: 945.9293 std: 192.9449 共解决任务数: 99 batch_size 为: 5 mean: 3111.8041 std: 377.6134 共解决任务数: 97 batch_size 为: 10 mean: 5247.8571 std: 619.4505 共解决任务数: 98 batch_size 为: 25 mean: 11210.2500 std: 1125.7558 共解决任务数: 100 batch_size 为: 50 mean: 20717.1717 std: 2423.9770 共解决任务数: 99 batch_size 为: 100 mean: 40154.5455 std: 6498.1625 共解决任务数: 99 batch_size 为: 300 mean: 113667.0000 std: 16274.0472 共解决任务数: 100 batch_size 为: 500 mean: 187413.2653 std: 20496.8919 共解决任务数: 98 batch_size 为: 1000 mean: 380818.1818 std: 51131.5127 共解决任务数: 99 [1.52 1.186 1.17 1.082 1.032 1.06 1.011 0.984] [1.52 1.803 2.11 2.283 2.356 2.497 2.524 2.484] Process finished with exit code 0
根据上面的数据,我们只拿batch_size=1和batch_size=50 这两种设置下的数据进行分析:
batch_size=1时,我们平均需要946个episodes数据来训练,由于batch_size=1,我们也就是需要每个episode的数据都训练一下网络并更新参数,因此也就是需要训练更新网络参数946次。
batch_size=50时,我们平均需要20717个episodes数据来训练,由于batch_size=50,我们也就是需要每50个episode的数据都训练一下网络并更新参数,因此也就是需要训练更新网络参数20717/50=414次。
可以看到使用batch_size=50时,414/946=0.4,也就是说此时网络参数更新的次数为batch_size=1时的0.4倍。
推测1:
根据上面的数据我们可以有个大胆的假设,就是batch_size=1时,需要N个episodes数据来训练更新网络,而batch_size=m时,我们需要训练更新M次网络,也就是此时需要的episodes数为m*M。我们可以通过增加batch_size的大小,也就是说增加m值,从而减少M值,虽然m*M可能会远大于N,但是我们的M值会小于N值,甚至是小于一个数量级。那么假设这个推断是成立的,那么这个又和强化学习的并行化有什么关系呢???
强化学习以前是很少有并行化这个概念的,根据前文(相关内容参见:https://www.cnblogs.com/devilmaycry812839668/p/14165876.html):
我们知道强化学习可以在数据生成部分做并行化,也可以在网络训练部分做并行化,而现在大多数的并行化强化学习都是指数据生成部分的并行化,而且数据并行化的强化学习是当今强化学习领域中SOTA的表现,既然一个十分简单的方法,就是数据生成的并行化就能如此高的提升算法性能为什么以前几十年却很少有人做呢???其实答案很简单,从推断1中我们可以看到虽然通过增加m值后我们可以有效的减少M值,但是m*M的值往往要大于甚至是远大于N值,在某种层面上来说算法的数据利用率降低了,甚至是大大的降低了。换句话说就是batch_size=1时往往是数据利用率最高的情况,虽然增加m值有可能在运算稳定性上对算法给以提升,但是从最终的运算结果上来看batch_size=1才是效率最高的,最有效的设置。
但是既然,batch_size=1时效果这么好,这么多年一直在如此使用,为什么现在可是搞大batch_size的情况,搞并行化了呢,一个最主要的原因就是现在计算资源比较充足,数据的效率问题本身就没有那么重要了,我们可以适当的牺牲数据的有效性来提升算法的运行效率和最终优化效果。至于最终效果问题又怎么解释呢???
推测2:
对于非传统的强化学习问题(不是gym上cartpole这种简单问题,而是Atari这种较困难的视频游戏问题时)batch_size=1设置的情况下同样结构的算法最终的优化结果为H1,而当batch_size大于1时,如:batch_size=50时,算法的最终优化效果是H2,而往往H2是要大于H1,或者说H2要优于H1的。在计算资源较为充足的情况下,可以牺牲一定数据计算效率的情况下,对于难度较大的问题(不是gym中传统的问题环境,不是那种可以认为现已经解决的问题),我们通过增加batch_size的大小,从而减少网络训练的参数更新次数,并且提高算法最终优化效果,这就是可行的一个方案,也正是因此在现在的强化学习领域并行化开始大行其道。也就是说并行化强化学习,可以提高算法的优化结果和减少运行时间,这又何乐而不为呢。
--------------------------------------------------------
那么根据上面的推测1,推测2,就是现在的并行强化学习的所有基础吗,其实不然,还有一个容易被忽视的一点,那就是数据分布的情况,那就是用于训练策略网络的生成数据要求是待训练策略网络相近分布的网络生成的,那就需要尽量减少待训练策略网络和生成数据所属的策略网络 所决定的数据分布差异。在前文中:强化学习中经验池的替代设计——A3C算法 ,我们讨论过相关问题,在同策略算法中要求这两者分布更加高,分布更相近,而在异策略算法中对这两者要求会弱一些,但是不管在异策略算法还是同策略算法中,这两者的分布越靠近算法的性能也就越高,算法也就越能更快的收敛,速度更快,最终达到的最终结果也越优。也因此我们给出并行化强化学习的第三个推测:
推测3:
在更新网络时,训练网络的数据(batch_size个episodes)可以是k次更新策略网络之前的策略所生成的,其中k为某个较小的数值,比如5,这意味着我们训练网络的时候所采用的数据是5次更新网络之前的策略所生成的。只要保证用来训练策略网络,或者说更新策略网络时我们用来训练的数据是几次更新之前的策略网络所生成的,但是由于更新次数较少或时间较靠近,我们也可以把这些数据视作近似的看为时当前策略网络所生成的数据,那么我们使用这些数据来训练当前的策略网络就可以了。使用近似策略分布生成的数据训练当前策略也是同样有效的,近似程度越高效果也就越好。
---------------------------------------
凑够了推测1,2,3,我们也就自然容易得出并行强化学习的设计原理了,通过并行化数据生成喂给策略网络足够的数据,即使这些数据是几次更新前的策略所生成的也是完全可以用来训练当前网络策略的。根据推测1和2,我们知道训练策略网络时使用大量的数据,也就是说batch_size不为1,那么我们需要较少的网络参数更新次数,并且最后的优化结果也会有一定的提升。根据推测3,我们知道我们可以使用前几次更新策略网络时生成的数据来训练当前策略网络,那么我们我们在加上这么一个前提假设,那就是强化学习算法中往往数据生成所需要的时间要大于网络策略训练的时间(详见:深度学习中使用TensorFlow或Pytorch框架时到底是应该使用CPU还是GPU来进行运算???)
假设生成一个episode的数据需要100秒,而训练一个episode的数据仅用1秒,这里我们只是为了描述生成数据和训练策略的时间差距,具体时间视具体情况而定。
如果只考虑推测1和2,那么我们假设此时有50个物理核心的CPU可以完全给数据生成使用,那么我们使用这50个进程并行生成数据,那么同样的数据生成的时间里,这里假设为100秒,我们使用50个CPU就会生成50个episodes的数据,然后我们再把这50个episodes的数据给策略网络进行一次训练,这时候的batch_size就是50,如果进行策略网络更新的设备(CPU或GPU计算能力不是满负荷运算这样的计算的话)计算能力足够的话batch_size=50时和batch_size=1时的耗时相差不会太大。
此时假设batch_size=50和batch_size=1时的策略更新一次的时间相同,根据本文前面的数据(可以看到使用batch_size=50时,414/946=0.4,也就是说此时网络参数更新的次数为batch_size=1时的0.4倍),假设batch_size=50是策略更新的次数为batch_size=1时的0.4倍,那么batch_size=1时需要W次策略更新,batch_size=50时需要0.4W次策略更新,那么batch_size=1时的总运算时间为W*(100秒+1秒)=101*W秒,而batch_size=50时,总运算时间为0.4*W*(100秒+1秒)=40.4*W秒,从而通过并行化数据生成的方式来提高强化学习的运算效率,缩短运行时间,同时由于batch_size的增加也能提高算法的最终优化效果。
那么在考虑推测1,2的同时加上推测3呢,我们这时就能得到现在主流的强化学习并行方法,也就是现在的SOTA强化学习算法。
现在比较SOTA的并行强化学习的做法是什么呢,那就是数据生成部分和网络训练部分异步并行,此时不仅仅是数据生成部分并行,同时数据生成部分和网络训练部分也并行而且还是异步的。为了解释清楚,我们还如上面的假设,假设产生一个episode的数据需要100秒,训练一个batch的数据需要1秒(batch_size=1或50时均为1秒),假设此时我们可以用来并行化运行生产数据的物理CPU数为5000个,每一个CPU都运行一个生成数据的进程,那么每一秒我们可以产生的episodes个数为50个(5000/100=50),而策略网络进行训练一秒更新一次需要50个episodes的数据,这样我们可以保证策略网络每秒都有足够的数据进行训练(每秒都可以得到50个episodes的训练数据),每次更新策略后我们再为这5000个进程(生成数据的进程)更新参数,以此来确保这5000个生成数据的进程生成的数据尽可能的与当前训练的策略相匹配。
设这5000个生成数据的进程的索引号为0—4999号,我们观察策略更新进程100秒时间的运行情况,也就是说第0号秒时策略更新进程从0-49号生成数据的进程取出数据进行训练,第1号秒则是从50-99号生成数据的进程取出数据进行训练,以此类推,第99号秒时从4950号至4999号生成数据的进程里取出数据进行训练,也就是说第4950号到第4999号生成数据的进程所生成数据使用的策略其实是分别包括了第0秒时策略网络的策略,第1秒时策略网络的策略,一直到第98秒时策略网络的策略,也因此保证了从第4950号到4999号生成数据的进程中取出的数据是由接近于第99秒时策略网络当前时刻下的策略所生成的数据。
也正是由于推测3存在的前提条件下,我们可以更大程度上的提升算法运行速度,还如前面的假设,batch_size=1时,我们需要W次更新网络,生成一个episode数据需要100秒,更新一次网络的时间为1秒,完全串行的话共需时间:W*(100+1) 秒,在推测1和2之下,batch_size=50时共需运行:40.4*W 秒,而在推测1,2,3的条件下,batch_size=50,我们共需时间为:100+W*1*0.4=100+0.4W 秒。
实际我们可以假设W一个实际数值,如10000次,那么完全串行需要用时:101万秒,而推测1,2条件下,并行需要用时:40万4千秒,而在推测1,2,3条件下,保证可用CPU数足够的前提下,我们就需要4千100秒,这样的话提速超过百倍。当然,这些都是完全理想化前提下的推断。
------------------------------------
可用看到,在推测1,2条件下,我们需要的CPU个数为batch_size的个数,在上面假设场景中为50,即需要50个CPU;而在推测1,2,3的条件下,我们需要CPU的个数为单进程生成数据所需时间与更新策略网络所需时间的比值再乘以batch_size,在上面假设场景中需要100*50=5000个CPU。
实际中虽然难以有足够的CPU数来满足本文中最后给出的主流并行算法下的最高性能时所需的CPU个数,但是也比第一种并行方法性能要高(推测1,2条件下的并行方法)。
实际中往往生成一个episode数据的时间与更新网络一次的时间要小于本文的假设的,而实际中可以使用的CPU个数也是远远小于本文中假设的,本文只为解释现在的并行化强化学习的设计原理,故做了如此理想化假设。即使实际中可以使用的CPU数较少的情况下,并行化强化学习也会得到不错的性能的。
========================================================
根据本文的分析,可以使用的CPU数越多,并行化强化学习的效果越好(数据生成一般需要在CPU端进行),但是往往实际上CPU的可使用数较少呢,比如就只有4个CPU,或者8个CPU这种家用级别的电脑呢,这种情况下batch_size还是应该设置为1还是一个较大的值呢???
其实,这个还真就是一个很不好回答的问题。在可使用CPU数较少的情况下,最好的解决方法就是下调batch_size的大小,也或者可以选择batch_size=1。
如果用于生成数据的CPU个数较少,那么使用较小的batch_size也是可以的,其实最重要的一点就是使进行策略更新的进程持续工作,尽量避免出现策略更新进程空转等待生成数据进程产生数据。像服务器这种的计算设备一般都是可以具备几十甚至上百CPU的,而家用级别的主机往往具备的cpu核心数都是个位数,如此情况下还是将batch_size设置较大的情况往往会导致策略训练的进程长时间空转,从而导致性能甚至不如batch_size=1的情况。
----------------------------------------------------------------
posted on 2021-01-06 08:38 Angry_Panda 阅读(1012) 评论(2) 编辑 收藏 举报