OpenAIの最近のブログポストが面白いので紹介する。

OpenAIは2016年にTeslaやSpaceXの創業者であるイーロン・マスクが YコンビネータCEOのサム・アルトマンらと共同で設立した非営利組織で、 人工知能の技術の発展とその民主的な普及を目的としている。 OpenAIは創設以来強化学習の研究開発に特に力を入れてきた。 例えば、強化学習用の様々な仮想環境を共通のインターフェースで提供するUniverseGymを発表したり、 エージェントがゲームのバグを利用することで人間が意図したものとは異なる振る舞いにより報酬を得てしまう問題を指摘するなどしている。

そのOpenAIの最新の成果は、進化的手法(Evolution Strategies)と呼ばれる数十年前から知られていた強化学習の最適化手法についてのものだ。 強化学習では、環境の特定の状態においてエージェントがどのような行動を取るべきかを、パラメタを持つ方策関数によって定める。 報酬の期待値を最大にするような方策のパラメタを探すことが強化学習の目的だ。 進化的手法はそのために以下の2つのステップを繰り返す。

  1. 現在の方策パラメタにノイズを加え、エピソードを実行し、その方策により得られた報酬を計算する。このステップを複数回実行する
  2. 上のステップで生成されたパラメタをそれぞれのエピソードでの報酬によって重み付け平均し、新しい方策パラメタとする

Pythonコードで具体例を示すと以下のようになる。

# ある点を極小値とする2次関数fを目的関数として最適化を行う
import numpy as np
solution = np.array([0.5, 0.1, -0.3])
def f(w): return -np.sum((w - solution)**2)

npop = 50      # population size
sigma = 0.1    # noise standard deviation
alpha = 0.001  # learning rate
w = np.random.randn(3) # initial guess
for i in range(300):
  N = np.random.randn(npop, 3)
  R = np.zeros(npop)
  for j in range(npop):
    w_try = w + sigma*N[j]
    R[j] = f(w_try)
  A = (R - np.mean(R)) / np.std(R)
  w = w + alpha/(npop*sigma) * np.dot(N.T, A)

進化的手法は、実装が容易であるバックプロパゲーションの計算の必要がない並列化による恩恵が大きい報酬がスパースに与えられるタスクにおいてもうまく動くパラメタ数が少ないなどの利点を持つ。

並列化を行う恩恵が大きいのは次の理由による。ステップ1における「複数回繰り返す」の部分は複数のノードで並列して行うが、 この時にそれぞれのノードが他のすべてのノードでパラメタに加えられるノイズをあらかじめ共有しておくことにより、 ステップ2で必要なノード間の通信は各ノードで実行されたエピソードの報酬を表すスカラーのみとなり、通信量が非常に少なくて済む。 これにより大規模な並列化を行なっても通信帯域のボトルネックに到達しにくくなる。

仮想3次元物理環境のMuJoCoを使った実験では、進化的手法を用いたアルゴリズムが1440個のCPUコアを用いてヒューマノイドの歩行タスクをたったの10分で覚えた。32コアのA3Cアルゴリズムを使った場合だと同じタスクを解くのに10時間が必要であり、学習時間が大幅に短縮されていることがわかる。 また、アーケイドゲーム環境のAtariで720コアを用いて1時間学習させた時の性能が1日学習したA3Cと同等だった。

MuJoCo環境での3次元ヒューマノイドの歩行

上の実験では使用している計算リソースが違うので一見不公平な比較かと思うかもしれないが、A3Cでは大規模な並列化をしてもノード同士の通信のボトルネックが生じて速度向上がなされないし、さらに進化的手法の方は価値関数を利用しないことと、バックプロパゲーションを行わないことにより、1コアあたりの計算が軽いので、実用的には十分公平な比較といえる。

進化的手法は非常に単純であるため、このように良い性能を示すのは驚異的だ。 深層強化学習の最近の研究では勾配の情報を利用してバックプロパゲーションを行うアルゴリズムが主流であり、1970年代に提案された進化的手法はコミュニティからはほとんど忘れ去られていた。 それだけにこの発見のインパクトは大きい。