写在前面
上一章节我们就提到了,A2C有几个问题,第一必须在线,第二数据有太大的相关性,所以会导致我们的学习可能向不是我们想要的地方去发展了
A3C
为了解决数据的相关性的问题,我们主要通过了如下的办法,第一种办法,每个进程都独立的和环境进行交互,但是只在一个环境上进行权重更新,接下来将学习到的网络同步更新到所有的环境上。
第二种:我们个都独立的和环境进行交互收集片段,并且计算梯度,但是并不直接进行更新,而是传递我们的梯度到我们的计算进程,SGD更新后,将更新后的网络传递分布式的神经网络上。
为了大家能方便了解,我搞到了这本书的原图
一些想法
这里主要是两个点,一个是采样分布式,一个是计算分布式,如果你有很多的GPU,你可以使用第二种方法,如果你有很多的CPU,你可以使用第一种方法,如果你有很多的分布式的环境,则完全可以基于你自己的实际的情况来进行更新
data分布式
数据平行,注意传递的参数是samples,我们前面就已经学习了多进程使用的方法,直接使用我们的queue,作为我们的sample的生产者就可以了,如果你还记得之前的情况,我们也已经做过类似的事情
效果
兄弟们,十倍效率,真的杠杠的块,A3C绝对是比A2C好太多的东西
代码
这里创建了很多去收集数据的子进程
train_queue = mp.Queue(maxsize=PROCESSES_COUNT)
data_proc_list = []
for _ in range(PROCESSES_COUNT):
data_proc = mp.Process(target=data_func,
args=(net, device, train_queue))
data_proc.start()
data_proc_list.append(data_proc)
具体干的活,创建环境,收集经验(或者reward结果)
def data_func(net, device, train_queue):
envs = [make_env() for _ in range(NUM_ENVS)]
agent = ptan.agent.PolicyAgent(
lambda x: net(x)[0], device=device, apply_softmax=True)
exp_source = ptan.experience.ExperienceSourceFirstLast(
envs, agent, gamma=GAMMA, steps_count=REWARD_STEPS)
micro_batch = []
for exp in exp_source:
new_rewards = exp_source.pop_total_rewards()
if new_rewards:
data = TotalReward(reward=np.mean(new_rewards))
train_queue.put(data)
micro_batch.append(exp)
if len(micro_batch) < MICRO_BATCH_SIZE:
continue
data = common.unpack_batch(
micro_batch, net, device=device,
last_val_gamma=GAMMA ** REWARD_STEPS)
train_queue.put(data)
micro_batch.clear()
结果
学习效率直接提升了十倍,GPU终于不用再等待CPU给数据了,嗯,嘎嘎好使
,但是我的跑了300多w的frame以后,还是丁点也不学习,我的环境肯定有问题
但是我用自己的电脑跑了一下还是这个问题,300多w依然不收敛,我怀疑是我的环境的问题,替换了gym可能是这个问题,我需要再探究一下
3071296: done 3322 games, mean reward -20.430, speed 3808.68 f/s
3071552: done 3323 games, mean reward -20.430, speed 3760.81 f/s
3072096: done 3324 games, mean reward -20.440, speed 3628.43 f/s
3073824: done 3325 games, mean reward -20.440, speed 3756.18 f/s
3074016: done 3326 games, mean reward -20.450, speed 3188.30 f/s
3074240: done 3327 games, mean reward -20.430, speed 3806.10 f/s
3075680: done 3328 games, mean reward -20.410, speed 3682.12 f/s
3077728: done 3329 games, mean reward -20.410, speed 2024.45 f/s
梯度平行
显然,如果你有很多计算单元,你完全可以使用分布式计算,梯度累加的形式进行学习,
三个问题
1: 问题一:梯度如何
内存共享
本地的net直接使用了net.share_memory()的形式,进行了梯度的共享