Reinforcement Learning の self play についてのまとめ
強化学習の self play について知りたいことがあるので、ざっくりと有名な論文を読んでいく。熟読はしない。
知りたいこと
論文
- Mastering the game of Go without human knowledge +
- Mastering Chess and Shogi by Self-Play with a
General Reinforcement Learning Algorithm)
- 上記と同じっぽい
Beating the World’s Best at Super Smash Bros. Melee with Deep Reinforcement
- 6種類の違うモデルを戦わせた。過去の自分と戦わせたとの記述がある。
- game 内に内蔵されている別AIとの対戦で評価?
強化学習/RL/Reinforcement Learning のデバッグ方法
RL のデバッグは難しい。RLアルゴリズムの選択、適切な reward の設定、Deep RLの場合モデルの選定、実装の正しさ、適切なパラメータ、そもそも学習できる問題なのか。切り分けが難しい。世の中には同じように思っている人がたくさんいるようだ。情報元から適当にまとめる。
情報元
- What are your best tips for debugging RL problems? : reinforcementlearning
- Deep Reinforcement Learning practical tips : reinforcementlearning
- williamFalcon/DeepRLHacks: Hacks for training RL systems from John Schulman's lecture at Deep RL Bootcamp (Aug 2017)
- DQN debugging using Open AI gym Cartpole - The intersection of energy and machine learning
チェックリスト
- 低次元の state をもつシンプルな environment で問題をかんたんにする
- reward を simple にしてみる。すぐに効く形の feedback も良い。
- random policy に解かせてみる。random でも時々問題を解けそうなら有望。
- 自分の目で observation を見て、自分でも解けるか確認
- Observation mean 0 std 1 に scaling する
- Reward も可能なら scale する
- Observation/Reward に outlier がいないことを確認する
- 動くかな。やってみよう。はうまくいかない。たくさんのことを正しくやらないと学習は進まない。
- agent を正しく実装することがとても重要。他のコードよりもテストが大事。
- 可能な限り unit tests を書く
- ありとあらゆる場所に asserts を。matrix dimension, input, output, action の range
- 長い時間実行する前に、1行1行目を皿にしてコードを読む。
- 可能な限り見える化、すべてを log する
- いくつかの states をピックアップして q-value を見てみる。徐々に変わって stablize されるはず。
- すべての input/output/state を記録する
- Neural Net がからむと 10 倍難しくなる。最初は Neural Net でやらず。うまく動いたら swap する
- seed を固定する
- optimizer の選択にsensitiveなので注意
- すべてを normalize せよ
- 良い結果が出ているものは100-1000 の reward 使ってる
- 参照実装が使っている hyper parameters 使う
- 大きい replay buffer, bigger batch size
- 常に simple version から試して動くことを確認
- そもそも agent はときどき正しいことをやっているの?
- DQN は収束がおそいよ
RL での batch size
Reinforcement Learning を Welcome to Spinning Up in Deep RL! — Spinning Up documentation で勉強しながら実装している。とある実装で batch size = 5000 となっていて「値が大きすぎる」と思い、何気なく小さな値に変更した。それをすっかり忘れて試行錯誤しているうちに policy gradient (logprob) が 0.0 になってしまい学習が進まない減少に悩まされた。ログを見て、よくよく考えてみたら logprob が 0 ってことは選択された action の確率が 1 ってことだ。つまり policy はどんな状態でも1つのアクションしか取りようがない状態をモデルが学習してしまっていた。さらに観察すると、これはある episode で agent が右に移動し続けただけで大きな報酬を得てしまったのを学習したのだとわかった。batch size が小さかったせいでこれが大きく聞きすぎてしまったようだ。
OpenAI Gym の MountainCar が難しいという話
Colab + PyTorch Lightning + Comet ML + Bert
Colab + PyTorch Lightning + Comet ML - higepon blog の続き。
目標
Tensorflow 2.0 コンペで自分が書いた training のコードを Colab + PyTorch Lightning + CometML に移植する。移植したことでメリットがあるかを検証する。
Google Drive の利用とその失敗
Colab を利用すると 12時間毎にマシンがリセットされる。つまり巨大な kaggle の dataset や生成物が全て消えてしまう。生成物の例としては train/valid split したものとか modelを save したものとか。これらを毎回生成するのは無駄なので Google Drive 上に置いておく。これをダウンロードすれば良い。というコードを書いたのだがうまく行かなかった。生成にかかる時間はほほゼロになったが Google Drive から生成物をダウンロードする時間が支配的になってしまった。ボツ。
移植
transformers Bert のモデルを TF2.0 で使ったモデルにする。
import torch from transformers import ( BertModel, BertTokenizer ) bert_model_name = 'bert-large-uncased-whole-word-masking-finetuned-squad' tokenizer = BertTokenizer.from_pretrained(bert_model_name) bert = BertModel.from_pretrained(bert_model_name)
次に LightningModule の Optional な callback をコメントアウトする。validation_step, validation_end, test_step, test_end は Optional である。 forward と training_step を埋めてこんな感じになった。batch が dataloader の返すものかな。
def training_step(self, batch, batch_nb): # batch input_ids, attention_mask, token_type_ids, no_answers, y_batch = batch # fwd y_hat = self.forward(input_ids, attention_mask, token_type_ids) # loss loss = loss_fn(y_hat, y_batch, no_answers) # logs tensorboard_logs = {'train_loss': loss} experiment.log_metric('train_loss', loss.detach().cpu().numpy(), step=self.global_step, epoch=self.current_epoch, include_context=True) return {'loss': loss, 'log': tensorboard_logs}
謎の CUDA エラー
データローダーの実装が終わり end to end で動かしてみると以下のエラー。
RuntimeError: CUDA error: device-side assert triggered
付加情報がない。普通の PyTorch NN なら同じモデルを CPU で動かすと詳細なエラーが分かるのだが transformer Bert はどこかで GPU 前提っぽい。と思ったが CPU 上で動かせた。num_classes が 5 であるべきところが別の config file が使われて 2 になっていた。これが cross entropy loss を計算するところでこけてた。