最初の世界

English

さて、今回から世界の実装を始めていきます。今回のゴールは、最初のシンプルな世界のルールを決め、OpenAI Gym に登録できる形式で書き下し、Keras-rl2を使ってトレーニングができるところまでとします。細かいことは気にせず、とりあえず動くものを作ります。

コードは Github に置いておいたので、ここでは世界の仕様を書いていきます。

  • 30 × 30 の二次元グリッドスペース空間
  • エージェントは1つのみ
  • エージェントは最初に100のエネルギーを持っている
  • 空間には食べ物がランダムに配置されている(場所も量(0-100)もランダム)
  • 時間は不連続(ステップ制)
  • 各ステップに生き物は各方向に移動するか、待機するかを選択できる(選択肢は5つ)
  • 生き物は移動するとエネルギーを1消費し、待機すると0.5消費する
  • 生き物が食べ物に重なるとそのエネルギーを自分のものにでき、同時に食べ物の量/100分のスコアを獲得する
  • 生き物が全てのエネルギーを使うと死亡し、スコアを3点失う
  • 1ステップごとに2%の確率でランダムなマスにランダムな量(0-100)の食べ物が発生する
  • 生き物が死ぬか2000ステップを過ぎたら終了する

OpenAI Gym に登録するときは、 pip -e gym-smallworld のように -e (editable) オプションをつけると、世界の仕様を変更するのが簡単になります。

一方、トレーニングの方法は、Keras-rl2の例にあるAtariゲーム用のトレーニングコードをほぼ流用しました。具体的には以下の仕様でトレーニングします。

  • 3 × 3 × 16 の畳み込みレイヤー(ストライド数1)を2枚
  • 32ニューロンの全結合層が1枚
  • 活性化関数は scaled exponential linear unit (selu) (変更点)
  • Deep Q Network (DQN) を epsilon greedy Q ポリシーと共に使い、線形焼き鈍し(linear annealing)をする
  • 最適化には Adam をラーニングレート0.001で用いる
  • ウォームアップステップは10000
  • ターゲットモデルは10000ステップごとに更新される

ネットワークを小さくし、デフォルトの relu を selu に変更しました。それ以外はだいたい元のコードのままです。GPUで動かすようにはしていないので、適当なパッケージ(gym, keras-rl2あたり)を入れればどんなパソコンでも動くはずです。(Python 3 で動かしています。)動いた場合は下のようなアニメーションが表示され、トレーニングが始まります。

緑が生き物で、赤が食べ物です。明るいほど食べ物のエネルギーが大きいことを示しています。この画像ですが、バックグラウンドにもっていって描画されないようにすると、計算を省略するみたいで、効率が上がります。見たいときはフォアグラウンドにもってくると適切な速度で表示されます。どういう仕組みかはわかりませんが、便利です。

見える範囲にある食べ物を集めていればよく、邪魔するものも何もないので、非常に簡単なタスクです。Atariのゲームの方がよほど難しいと思われます。episode_rewardもとんとん拍子に上昇し、次の図のようにだいたい1.5-2Mステップで収束します(青がエピソードごとのスコア、オレンジがQ値です)。Core i7-3770kで半日程度かかりました。

現時点での問題として、テストの時にトレーニング時のパフォーマンスが発揮できないのですが、これについては後々原因を追求します。(トレーニング時とテスト時のポリシーの変更によるところかなと思っています)

とりあえず動く世界ができました。次は複数エージェントでのトレーニングの実装をしたいと思います。

世界を作るための準備(ソフトウェア環境編)

English

前回の投稿で進化の実験ができる世界を作りたいと言いました。今回はその実現のためのソフトウェア環境について考察します。

将来的には深層学習を含めた複数エージェントの機械学習をすることになりますので、現時点で最適な言語は Python だと言えると思います。 OpenAI Gym などの機械学習のフレームワークが確立されている他、深層学習では強力なライブラリ群によってほぼ独壇場のシェアがあります。速度面でも Numpy や Numba をうまく使えば他の言語と遜色なく、フレキシブルに使える分 Python に利があるとも言えます。(Matlab と Julia でライフゲームの速度比較をしたのですが、Python も Julia もきちんと最適化をすればほぼ同等の性能が出ました。Matlabだけはどうしてもそこまで速度を上げることができませんでした。これらの実験の詳細は割愛します。もし興味がある方がいらっしゃれば、一報いただければ記事を書こうと思います。)

エディタは PyCharm を使うつもりです。VSCode も評価が高く、考慮はしたのですが、デバッグが PyCharm の方が簡単そうだったのでこちらにしました。 Vim も選択肢にはありましたが、実用的なレベルになるまでに必要なプラグインの数が多いこと(結果メンテナンスの量が増える)もあって、諦めました。無理してVimを使うよりは、PyCharm の Vim mode を使った方が短期的には楽になる気がしたので。このあたりは様子を見ながら色々試してみたいと思っています。

今回は OpenAI Gym に自作の環境(世界)を登録して、既存の深層学習ライブラリと組み合わせて計算することを試みます。やや古い Intel Mac を使っているので、PlaidML + Keras を使って Intel CPU のグラフィック機能を計算資源にできないかと思ったのですが、強化学習のフレームワークと相性が悪く、直す方法もわからなかったので大人しく CPU で計算することにしました。(こちらでとりあげられている問題が発生し、PlaidML側の反応としては、Kerasの方が何とかならないと難しい、とのことでした。PlaidMLのベンチマーク自体は走らせることができました。)

将来的には GPU を積んだ手頃な計算機を構築して、そちらで計算を回せるようにしたいところです。計算用のハードウェアの構成の考察も大変面白いので、別途記事にしますが、今は計算機を構築するのに最適な時期ではない気がするのでもう少し後に書こうと思います。少なくとも Apple Silicon Mac と、 AMD Ryzen 5000 シリーズの情報が出て来てから考えるべきだと思っています。

今回は特に紹介するコードもなく手短になりました。次回はおそらく手始めに OpenAI Gym に登録できる世界を作ってみることになると思います。お楽しみに。

電気羊は仮想空間で進化の夢を見るか?

English Version

長いこと私が心の奥の方で静かに「やりたいなぁ…」と思っていたことがあります。それは小さな世界で進化の実験をすることです。もちろん実際にやるのは難しいので計算機の上で、ということになりますが。突飛なことを、と思われるかもしれません。あるいは、現状の計算リソースでは足りないのでは? という批判もあるかもしれません。が、セル・オートマトンなどに代表されるようにごく単純なルールから複雑な事象が生まれるということは既に示されています。

もうすこし具体的にはセル・オートマトンをもう少し複雑にし、より「生命」らしくした存在を用いて観測をしてみたいと思っています。思考をし、学習をし、再生産をし、そして死ぬことができる「生命」と、それが生きる環境を用意して、自然選択に任せてどのようにそれが発達するかを見守る、といった感じの漠然としたプロジェクトです。もし条件が合えば、徐々に「知的(?)」な生命が生まれていくかもしれません。

これは簡単なことではないですし時間のかかることだと思います。おそらくたくさんの人々が過去に挑戦してきたテーマでもあるでしょう。私が個人的な趣味としてやったところで何か有益な結果が生まれるかといわれれば、それはわかりません。今までやってきた物理学と神経科学からひょっとしたら新しい知見を持ち込めるかもしれません。仮に知的生命体様のものが一切出てこなかったとしても、何かしら学ぶところがあることでしょう。とりあえずモチベーションはそれでよしとします。

当面は2つのことに注力するつもりです。1つめは個体の情報の継承と、自然選択を可能にする環境の構築。広い意味では、「遺伝的アルゴリズムの実装」と言えるかもしれませんが、目標関数だとかを設定するのではなく、あくまで「生き延びた者が次の世代を作る」というルールの実装になります。勝てば官軍とでも言いましょうか。2つめは、生きる過程でトレーニングが可能、かつ、進化によって構造自体のの変化が可能なニューラルネットワークを「生命」に持たせることです。

これから書く記事はこの探求を記録した個人的な日誌のようなものになることと思います。道は長いですが、その道中で小さなトピックを見つけて書いたり、考察した事柄をまとめたりすることになると思います。もし楽しみにしてくださる方がいらっしゃれば幸いです。