【深層強化学習】Chainerrlのa3cのモデル定義で入力チャネル数でNoneは使わないこと
急にテーマが代わり、強化学習の話。
しかも、かなりニッチな話。
深層強化学習のライブラリとして「Chainrrl」を使っている。
「Chainrrl」はPreferred Networksが提供しているChainerを使った深層強化学習ライブラリ。
新しい手法とかも実装されているので便利。
「a3c」という強化学習手法を実装しているとき下記のようなエラーが発生した。
エラー内容
File "/Library/Python/2.7/site-packages/chainerrl/agents/a3c.py", line 122, in __init__ async.assert_params_not_shared(self.shared_model, self.model) File "/Library/Python/2.7/site-packages/chainerrl/misc/async.py", line 63, in assert_params_not_shared assert a_param.data.ctypes.data != b_param.data.ctypes.data AttributeError: 'NoneType' object has no attribute 'ctypes'
エラーの内容の通りだが、指定したモデルを同期しようしたときにパラメータ型でエラーが発生している。
原因と対策
モデルの中で下記の通り、モデルの定義部分で入力チャネル数(Convolution2Dの第1引数)をNoneにするとダメらしい。
def __init__(self, ndim_obs,n_channels=4): super(CommonFunction, self).__init__( conv1=L.Convolution2D(None,16,ksize=(4,1),pad=1,stride=1), conv2=L.Convolution2D(None,32,ksize=4,pad=1,stride=1), conv3=L.Convolution2D(None,64,ksize=4,pad=1,stride=1), c_fc1=L.Linear(256, 200), c_fc2=L.Linear(200, 200), c_fc3=L.Linear(200, 34))
入力チャネル数を指定するとうまく動く
def __init__(self, ndim_obs,n_channels=4): super(CommonFunction, self).__init__( conv1=L.Convolution2D(3,16,ksize=(4,1),pad=1,stride=1), conv2=L.Convolution2D(16,32,ksize=4,pad=1,stride=1), conv3=L.Convolution2D(32,64,ksize=4,pad=1,stride=1), c_fc1=L.Linear(256, 200), c_fc2=L.Linear(200, 200), c_fc3=L.Linear(200, 34))
おそらく、a3cのaの一つである「Asynchronous(非同期)」の実装に、ctypesを利用しているが、
L.Convolution2D(None,....)
とすると、ctypesを持たないインスタンスになってしまうので、エラーになってしまう。
(chainerrlのasync.pyの56~63行目あたり)
(あまりちゃんとchainerrlのソース読んでないので憶測です。)
ちなみにDeepQNetwork(DQN)ではL.Convolution2D(None,....)
で問題なかった。
(Asynchronousではないからかな?)
ちなみに上の例では、L.Convolition2D
でNoneを指定しているが、L.Linear(None,...)
でも同じ話。
まぁ深く考えず入力チャネル数を指定すればいいだけ。