はじめに
練習がてら、PyTorchを使って自作のマインスイーパを機械学習させてみます。
わからないことだらけなので、いろいろと勉強しながらメモ。
一旦メモ書き程度に作成して、必要ならあとから体裁整える。
目標
Windowsの標準(だった)マインスイーパの初級を、安定してクリアできるようになること。
とりあえずは9割ぐらいの勝率を目指す。
構成
こちらのDQNを写経しました。
では済まないので、簡単に。
ネットワークはシーケンシャルモデルを使用。
入力層(状態$s$)と出力層($Q_{s,a}$)のニューロン数は盤の目の数。
隠れ層は2層で、各層のニューロン数は盤の目の数×SIZE_MAG
。
とりあえず盤の目の数に対してスケーリングすればいいかなと(適当)
活性化関数はReLU、最適化手法はAdam(学習率0.001)を使用。
マインスイーパは自作。画像取り込んで頑張ろうかと思ったけど、本題はそこじゃないので。
アルゴリズムは省略。
報酬は次の通り。
変数 | 条件 |
---|---|
reward_win |
ゲームクリア |
reward_failed |
ゲーム失敗 |
reward_miss |
すでに開いているマスを開こうとする |
経過
1回目
まず学習できるのかを確認するため、盤のサイズを6×6、地雷の数を5個にしてみる
GAMMA = 0.99
NUM_EPISODES = 1000
CAPACITY = 10000
BATCH_SIZE = 200
SIZE_MAG = 8
reward_failed = -100
reward_win = 100
reward_miss = -1
極まれに勝てるけど、偶然勝利している感じ。
誤差を見てみると2000stepくらいで4桁ぐらいに吹き飛んでた。えぇ…
単純な報酬和を見ても既に開いてるマスばかり開こうとするし、報酬の問題?
2回目
というわけで報酬を修正。
reward_failed = -100
reward_win = 100
reward_miss = -10
reward_open = 1
reward_open
はマスを新しく開けたら与える報酬。
誤差はさっきより落ち着いたけど、10くらいでずっと振動。
n回目
いろいろといじったけど、振動も発散も止まらず。
挙動を見てみても、すでに開いてるマスを相変わらず開こうとする。
Fixed target Q-Networkを導入するか…
1晩経って…
以下の可能性を考えた。
- ε-greedy法のランダム動作の時、既に開いているマスばかり開こうとしている
- すでに開いているマスをQネットワークが選択した場合、次の状態$s_{t+1}$と前の状態$s_t$が同じになるから、ループする
- ミニバッチを作る際に、すでに開いているマスを開く行動が多く選択されている
試しに既に開いているマスを選択した場合もゲームオーバーにしたら、誤差自体は1未満で推移するようになった。
εの値を小さくする(初期値0.5→0.2)とさらに誤差は小さくなった。(0.1~0.01くらい)
ただ、ミニバッチを作る際の問題は解消されていないため、Prioritized Experience Replayを実装する。
コードはそのまましゃk(
ってやってみても、うまくいかない。
そりゃ、コーディングミスってたらねぇ(
target Q-Networkだって初期値のままだったし…
で、修正した結果、うまくいかなかった。
報酬が大きすぎるのか?
reward_failed = -1
reward_win = 1
reward_miss = -1
reward_open = 1
やっぱり駄目だったよベイベ…
ふと思う
これまでは毎回違う盤面に対して学習してきたけど、
ある1つの盤面に対しては学習できるのか…?
→できた。勝率9割になるまでに200~300エピソードくらい。
1回クリアできるとすぐに勝率9割になるのがかわいい。
じゃあ150エピソードに1回変えたら?
→全く勝てない。過去の学習データに引きずられていると思われる。
じゃあいっそのこと毎回盤面変えるように戻そう!