PPOのハイパーパラメータメモ #2b: バッチサイズ&バッファサイズ（連続行動空間）編

# はじめに
PPOのハイパーパラメータを色々弄るとどうなるか実験のメモ．[前回](https://qiita.com/deepirl_learner/items/fbd222870a2dfc439343)に引き続き，今回は連続行動空間の環境でPPOを学習させるときのバッチサイズ，そして（ついでに）バッファサイズについて．

[Best Practices when training with PPO](https://github.com/EmbersArc/PPO/blob/master/best-practices-ppo.md)という記事のbatchsizeに関する知見の要約を再掲：

- バッチサイズ(batch_size)は勾配降下の各更新にどれだけのサンプルを使うかに対応する
- バッチサイズの倍数がバッファサイズ(buffer_size)でなければならない
- 行動空間が離散の時は小さめ，連続の時は大きめのほうがよい

前回の検証では，離散行動空間に対しては，確かにバッチサイズは小さい方がよいらしいことがわかった．
今回は連続行動空間を持つPendulum-v0で検証してみる．果たして……


#実験
update_interval(=バッファサイズ)を10240に固定し，バッチサイズを16,64,256,512,1024,2048,5120,10240と変えて実験してみる．

ソースコードも同じく[こちら](https://github.com/chainer/chainerrl/blob/master/examples/mujoco/train_ppo_gym.py)からお借りした．
argumentで変更するのは--batchsize（と，保存場所を実験ごとに変更するので--outdir）である．

```python

    parser.add_argument('--gpu', type=int, default=0)
    parser.add_argument('--env', type=str, default='Pendulum-v0')
    parser.add_argument('--arch', type=str, default='FFGaussian',
                        choices=('FFSoftmax', 'FFMellowmax',
                                 'FFGaussian'))
    parser.add_argument('--bound-mean', action='store_true')
    parser.add_argument('--seed', type=int, default=0,
                        help='Random seed [0, 2 ** 32)')
    parser.add_argument('--outdir', type=str, default='results',
                        help='Directory path to save output files.'
                             ' If it does not exist, it will be created.')
    parser.add_argument('--steps', type=int, default=10 ** 6)
    parser.add_argument('--eval-interval', type=int, default=10000)
    parser.add_argument('--eval-n-runs', type=int, default=10)
    parser.add_argument('--reward-scale-factor', type=float, default=1e-2)
    parser.add_argument('--standardize-advantages', action='store_true')
    parser.add_argument('--render', action='store_true', default=False)
    parser.add_argument('--lr', type=float, default=3e-4)
    parser.add_argument('--weight-decay', type=float, default=0.0)
    parser.add_argument('--demo', action='store_true', default=False)
    parser.add_argument('--load', type=str, default='')
    parser.add_argument('--logger-level', type=int, default=logging.INFO)
    parser.add_argument('--monitor', action='store_true')

    parser.add_argument('--update-interval', type=int, default=10240)
    parser.add_argument('--batchsize', type=int, default=64)
    parser.add_argument('--epochs', type=int, default=10)
    parser.add_argument('--entropy-coef', type=float, default=0.0)

```
最適化手法には，[以前の結果](https://qiita.com/deepirl_learner/items/d269f87a40295c40ca48)を踏まえSMORMS3（引数なし）を使う．


## 実験環境

- CPU : Intel Core i7-8700CPU @ 3.20Hz x 12
- メモリ : 32GB
- グラボ: GeForce RTX2080Ti 11GB

#結果
##学習曲線
100区間の移動平均をとったもの．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459984/c292ceee-f3a0-812e-72eb-c7737b6af1f3.png)

16～2048の場合は学習回数$1.0 \times 10^6$回の間に収束しているように見える．



## bestモデルの性能
bestモデルで10000回走らせたときの累積報酬の箱ひげ図．負の報酬なので，上に行くほどよい．左が全体，右は一部の拡大図．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459984/31a8f31f-d7e6-ed31-4e3b-6eca0608f91f.png)

これを見るに，最も良いのが1024のときではあるが，**小さいバッチサイズも十分な性能を出しているように思える．**
5120以上はダメな模様．

## 学習時間
右は拡大したもの．当たり前の話ではあるが，バッチサイズを小さくすると時間が増える．

# バッファサイズの実験
今度は，バッチサイズを1024に固定して，バッファサイズ(chainerRLのPPOにおける「update_interval」)を，1024, 2048, 4096, 10240, 20480, 40960, 102400, 409600, 819200と増やして学習させ，性能を比較してみる．

## 学習曲線

100区間の移動平均をとったもの．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459984/5088ebed-beeb-9279-6b3e-e7402ec408e8.png)


## bestモデルの性能

bestモデルで10000回走らせたときの累積報酬の箱ひげ図．同じく負の報酬なので，上に行くほどよい．左が全体，右は一部の拡大図．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459984/04454136-a147-e2f2-7283-c1fea1ec8d84.png)

# 結論
もう一度，元記事の理想範囲を見てみよう．

> Batch Size
> Typical Range (Continuous): 512 - 5120
> Buffer Size
> Typical Range: 2048 - 409600

Pendulum-v0においては：

- バッチサイズ：$1024$がベスト．$16 \sim 2048$ のレンジがよく，あまり大差がない（前半の方が学習が早い）．それ以降は学習が遅くなる．
- バッファサイズ：$4096$がベスト．$2048 \sim 20480$ ($batchsize \times 2 \sim 20$) のレンジがよく，それ以降は学習が遅くなる．

気が向いたら続きます．