強化学習が流行っている昨今、自分も何か勉強せねばと思い、テトリスを強化学習で解かせてみることにしました。
強化学習というと、少し前に流行ったDQN、その後続いた研究成果の集大成であるA3Cの2種類が今まず学ぶべきものだろうということで、その2つを試しています。ただ、DQNではお話にならないくらい性能が出なかったのでわざわざ記事にはせず、思い出の中にしまいこみました。
一方、A3Cの方は多少「それっぽい」挙動を示し始めています。タイトルに「失敗例」としている通り、全然満足なレベルには到達していません。それでも、うちの妻曰く「何か考えている様子は見られる」と一定の評価をもらいましたので、一応、記しておく次第です。
参考にした論文・コード
実装
githubはこちらを参照。
- gameMgr.pyの中で、テトリスの動作を記述
- agent.pyの中で、A3Cの学習動作を記述
- train.pyで学習を実行。ループを管理。
- test.pyで、学習したモデルを使ったデモを実行。
今後もアップデート予定なこともあり、実験途中のコードを、きれいにせずそのまま載せています。間違い等ありましたら、ご指摘いただけますと幸いです。現状、(pythonなのに)メモリリーク的な症状がありますので、長時間の実行の際には工夫をお願いいたします。
実験
-
実行環境: GeForce 960。なのであまり早くは無いです。
-
学習時間: 2~3日程度
-
Model構造: Conv2Dを2層、その後Fully Connected層を2層、その後二股に分けて、ActorとCriticの出力を作り出しています
-
Optimizer: Adam
-
Leraning rate: 1e-4にて2日程度。その後、10万ゲームをこなすごとに半分にし、最終的に1e-5前後になっていたと思います
上記で最も重要だったのが、OptimizerとLearning rateの選定でした。
まず、Optimizer=RMSprop、Learning rate=1e-3の組み合わせではほぼ全く学習が進まず、Learning rate=1e-4へと変えてようやく学習が進むようになりました。ただそれでも一定のところまで行くと性能が伸び悩みを迎えてしまうことがわかり、Optimizer=Adamへと変えたところ、学習がより早く進むようになりました。
Optimizer=Adamが多くのケースで最強というのはよく知られています。強化学習の場合でも、同じく非常によい性能を持つということが一つの発見です。
Learning rateのスケジューリングは、学習をより良く進めていく上で大きなポイントのようです。どの強化学習の論文でも、スケジューリングに関しては行を割いて記載があります。
未知の課題に関しては、スケジューリングを事前に決めることは難しいですので、学習がサチり始めたなと思ったら、適宜止めて、学習係数を下げていくのが良いでしょう。
結果
下記画像は、1ゲーム中(積み上がって再スタートとなるまでを"ゲーム"と定義しています)で消せた行の平均をプロットしたものです。徐々に学習が進んでおり、消せる率も向上しています。ただ、2~3日学習させた時点では、最終的にまだ1にすら及んでおらず、つまり、大半のゲームで1列も消すことができずに終わっていることがわかります。
これを以て、本実験はタイトルの通り「失敗例」としています。
このまま続けていけば徐々に性能は向上していくのかもしれませんが、他に試したいことがある関係上、一旦ここで学習を止め、まとめとしています。
Youtubeにプレイ動画をアップロードしています。よろしければ御覧ください。
改善を検討している点
実はいくつか改善を検討できるポイントが見え始めています:
- Layerが浅すぎるので、もう一歩深くする: 既存の論文でテトリスに取り組んだものを見ると、実は結構深いネットワークを使用しています。今のネットワークに追加を行う予定です
- LSTMの追加: 今のネットワークは、1手前の自分がどのような戦略を行おうとしていたかすら覚えていません。各盤面を見ながら、反射的にボタンを操作しているような状況です。長期的な戦略を踏まえるという意味で、LSTMの採用は性能を大きく向上する可能性があります
- メモリリークの解消: 実は今のコードは、(pythonなのに) メモリリークのような挙動があり、長期間安定して走らせることができません。改善を検討しています
上記の改善を行った実験結果を、近々公開できればと思っています。