天天看點

OPENAI Baeslines 詳解(六)并行環境采樣Zee帶你看代碼系列OPENAI Baeslines 詳解(六)并行環境采樣

Zee帶你看代碼系列

學習強化學習,碼代碼的能力必須要出衆,要快速入門強化學習 搞清楚其中真正的原理,讀源碼是一個最簡單的最直接的方式。最近建立了一系列該類型文章,希望對大家有多幫助。

傳送門

另外,我會将所有的文章及所做的一些簡單項目,放在我的個人網頁上。

水準有限,可能有了解不到位的地方,希望大家主動溝通交流。

郵箱:[email protected]

Thanks for reading, and enjoy yourself。

OPENAI Baeslines 詳解(六)并行環境采樣

OPENAI 采用了 自帶的multiprocessing子產品 和 MPI4PY 庫,進行多個環境模組化,然後同時對多個環境進行采樣,這樣減少了環境探索時采樣的時常。

multiprocessing 和 MPI 介紹

在python中運用多個CPU的核心,是利用

multiprocessing

子產品來完成的,是Python 自帶的子產品,想學習的可以看一下的幾個官方文檔。

https://docs.python.org/zh-cn/3/library/multiprocessing.html?highlight=multi#module-multiprocessing

MPI的全稱是Message Passing Interface

先上一份官方Tutorial https://mpi4py.readthedocs.io/en/stable/tutorial.html

那麼再來一個簡單版的 https://zhuanlan.zhihu.com/p/25332041

OPENAI 的Multi-env

Multi-Env 主要是分為兩個部分

  • 第一個是對環境進行包裝,可以對一組動作進行step
  • 第二個是對agent 進行包裝,可以同時利用一個policy 對多個env的observation輸出action,這個地方比較簡單,因為對于tensorflow, 隻是 送進去一個batch 還是 單送進去一組輸入的差別。

對環境進行包裝需要通過這個形式。

env = make_vec_env(env_id, env_type, num_env or 1, seed=seed, reward_scale=reward_scale)
           

在對環境包裝的時候,其類似于環境進行一次外包裝。這次外包裝後,新的類具有原來類的所有方法,隻不過新類的方法在調用過去類方法的同時,還增加了一些新的方法。

當然也可以認為,我們通過gym.make(env_id)建立的類, 是這個env的父類, 這個子類繼承了所有方法(當然這個是不準确的)

注意輸入的環境是增加了Monitor。

通過這種方式建立的env 是一個SubprocVecEnv 在子程式中并行運作多個環境并通過pipes與它們通信。

新的環境通過 remote.send() 将資料送入 并通過 remote.reciever() 将三個環境回報的資料送回來。

以上這些部分沒有什麼難度的地方。重點是如何解決以下幾個問題。

重點問題:

  1. 多環境并行的時候,沒有辦法使得所有環境 分開reset。也就是說 所有的環境 隻能是互動相同的次數,無法使得每個環境互動達到done的時候reset,即使達到done的時候,還是要繼續互動step一直到所有的 指定的步數結束。

    有些環境可以不用reset比如豎立擺那個環境,但是有環境是必須要用的。

  2. 環境被包裝之後在管道的另一頭,無法直接通過env的方式調用。無法獲得env的資訊。

解決辦法:

針對第一個問題:

  1. 當環境達到done的時候,無法reset,但是這樣的結果隻能是所采樣的資料是無效的,那麼此時隻要阻止其進入經驗池進行訓練就好了 。以ddpg為例,在ddpg.py中
    flag=[1,1,1,1]
    for d in range(env.num_envs): # 157行 
        if done[d]:
        		flag[d]=0
    
    for i in num_env:            # 140行
    	if flag[i]:
    		agent.store_transition(obs[i], action[i], r[i], new_obs[i], done[i])
               

然後,當所有的flag都為零的時候reset 就好了。

  1. 方法一是較為簡單的方式,但是依然會有浪費的采樣,那麼更好的方式是什麼呢。直接異步reset就OK了。
    if done[d]:
    	self.remotes[d].send(('reset', None))
               
    但這種方式沒辦法reset agent中的附加噪聲。那麼也就是說會産生一種情況就是在某幾個回合開始的時候開始的時候噪聲非常的小。

針對第二個問題:

​ GYM的環境step輸出有4個值, newob,reward,done,info 可以直接把所要提取的資料寫在info中。Info是個字典,可以直接調用。