エージェントを作ってみよう(1)
後半ではGeneral AI Challengeのエージェントを実際に作ってみましょう。General AI Challengeの環境を整えた上で、Chainerを用いた深層強化学習でモデル-コントローラ構造のエージェントを作成することによって、少し実践的な話題を提供したいと思います。
今回のエージェントに必要な環境
- Python 2.7 または 3.5+ (General AI Challengeに必要)
環境がCommAI-envをベースにつくられているためPythonが必要になります。エージェントもPythonで書くのが簡単であると思います。ただし、今回は触れませんがzmqを用いてリモートエージェントを作る場合、Python以外の言語も使用可能です。
- Chainer 1.23.0 (今回のエージェントに必要)
今回は強化学習の部分をChainerで書きます。CPU上で計算するため、GPUは必要ありません。実際に参加する際は、作りたいエージェントよって必要なライブラリを適宜選択してください。
なお、筆者の動作確認環境はUbuntu 16.04.2 LTS, Python 3.5.1, Chainer 1.23.0です。
リポジトリの入手と環境準備
下記のアドレスにアクセスして、General AI Challengeの現ラウンドのGitG\Hubリポジトリを入手します。git clone、zipファイルのダウンロードどちらでも構いません。
以降、コマンドライン上で入手したリポジトリのディレクトリにいるものとして進めます。依存するモジュールをインストールするためにpipコマンドを実行します。
- Python 2.7の場合: pip install -r src/requirements/py2.txt
- Python 3.5+の場合: pip install -r src/requirements/py3.txt
Pythonのバージョンがわからない場合は「python --version」で確認できます。正常に依存関係がインストールできた場合、以下のコマンドによって手動入力モードでタスクを試すことができるはずです。ここまでの作業はリポジトリのreadme.mdに詳しく記述されていますので問題があった場合はご参照ください。
python src/run.py src/tasks_config.challenge.json -l learners.human_learner.ImmediateHumanLearner
run.pyはエージェントを評価する際にも使用します。第1引数でタスクセットのファイルを、-lオプションで評価するエージェントを指定しています。エージェントの指定は実際のディレクトリ構造と対応しており「src/learners/(.pyファイル)/ファイル内のクラス」です。
モデル・コントローラ構造のエージェントの実装
それでは、エージェントの記述に入りましょう。今回はモデル-コントローラ構造のエージェントを作ります。これは複数モデルと1つのコントローラから成り立ち、各モデルは環境入力から出力候補を一つ決め、コントローラは環境入力と出力候補から最終的なエージェントの出力を決めます。モデルにはハードコードしたものや、ニューラルネットワークが利用できます(本サンプルではハードコードしたモデルだけを用いています)。コントローラには深層強化学習を用いることで、タスクを解くことに並行して報酬から自動的にどのモデルを使うべきかを決定します。
深層強化学習
深層強化学習のアルゴリズムにはDeep Q-Network(DQN)やA3Cなど複数ありますが、今回は比較的単純なDQNをベースとしました。Q-Learningに深層学習を取り入れたDQNはDeep MindのV. Mnihらによって報告されています。報告ではAtariのTVゲームをネットワークに学習させています。
Q-Learningの直感的な理解
Q-Learningは、ある離散的な行動(ボタンを押す、右に一定量動くなど)を実行した場合の価値を、これまでの状態に基づいて推定する手法です。価値の基準には割引累積報酬(discounted return, Q値)というものを用います。報酬とは、行動が望ましいか望ましくないかを知らせるために設定しておく数値であり、適当な条件(何かを達成できた、悪い方向に進んだなど)が満たされる度エージェントに与えられます。ある状態のもとである行動を実行した時、未来まで考慮してトータルでどれくらいの報酬になりそうか、その推定値が割引累積報酬となります。
合理的なエージェントに関する割引累積報酬は少しずつ正しい値に近づけることができます。現時点で知っている、状態sで行動aを実行することの価値をQ(s, a)としましょう。そして、実際に状態sで行動aを取ったところ報酬rが得られ、状態はs’になったという事例が得られたとします。合理的なエージェントならばaの次にはQ(s’, - )を最大にするような行動a’を取るはずです。Qは未来まで考慮した報酬の累積だったので、この事例(s→a→s’)を見たことからは、Q(s, a)はr + Q(s’, a’) (a’はQ(s’, - )を最大にする行動)と見積もれます。ただし、未来の価値は不確実なのでγ(0<γ<1)をかけて小さめに評価(割引累積)し、事例も偶然起こった可能性があるため、前に知っていた価値に新しく知った価値を割合α(0<α<1)で混ぜ合わせることにします。この更新を繰り返すことで、再現性のある事例から見積もれる値が次第に強まり、正しい割引累積報酬を知ることができます。以上を数式で表すと次のようになります。
Q(s,a)←(1-α)Q(s,a)+α(r+γ argmax┬a?Q(s',a) )
Q-Learningの基本式のQ(s, a)は基本的に状態と行動を縦横軸にして価値を並べた表です。ここを多層のニューラルネットワークに置き換えて汎化を狙ったものがDQNです。表ではなくニューラルネットワークを更新するため、基本式も勾配法を用いることができるロスの形に変更します。
Q-learning: Q(s,a)←Q(s,a)+α(r+γ argmax┬a?Q(s',a)-Q(s,a)) DQN: L(θ)=([r+γ argmax┬a?Q(s^',a;θ) ]_FIX-Q(s,a;θ))^2
DQNの式では更新前後のQ(s, a)の変化量をロス関数として、これを小さくする方向を誤差逆伝搬で求めパラメータθを移動させます。DQNの更新式では事例から得られた価値の部分はただの数値(近づけるべき対象)であると考えて、勾配の計算には含めない点に注意してください。また、新しい値に近づける度合いを表すαは勾配法の学習率で代用します。
