言語生成の強化学習をやっていく 実験編 強化学習なしとSelf-Criticの比較

この記事は強化学習苦手の会 Advent Calendar 2020の14日目の記事です。


追記 2020.12.15:loss計算の式を以下のように変更しました。

  • (修正前):$loss = -\underset{\hat{Y} \sim \pi_{\theta}}{\mathbb{E}}\left[\left( r(\hat{Y}) - r_b \right) \right]$ (ただし、$r_b = r(\hat{Y}_{greedy})$)
  • (修正後):$loss = -\underset{\hat{Y} \sim \pi_{\theta}}{\mathbb{E}}\left[ \left( r(\hat{Y}) - r_b \right) \log \pi_{\theta} \right]$ (ただし、$r_b = r(\hat{Y}_{greedy})$)

はじめに

こんにちは、品川です。
以前の記事で強化学習の言語生成の方法について紹介しました。
本記事では、実験を通して実際に言語生成の強化学習がどのような結果になるのか見ていきたいと思います。

使ったコード

github.com

強化学習なしモデルと強化学習あり(Self-Critic)モデル

今回は、ベースラインのモデルとして、こちらのリポジトリのREADMEで紹介されているfcモデルを用いました。こちらはResNet101で抽出した画像特徴量を毎時刻単語トークンと一緒にLSTMへ入力するシンプルなモデルとなっています。(自前でも同様の設定のを実装していましたが、結局思ったような精度が出なかったので泣く泣くこちらを使いました・・・)

こちらはSelf-Criticの再現実装がメインコンテンツとなる非公式リポジトリのようですが、Transformerなど最近のモデルの実装もあってimage-captioningを始めるのにおススメかもしれません。

本記事では、このリポジトリでサポートされている強化学習なしと強化学習あり(Self-Critic)の設定で学習を回して比較してみます。

コードの動かし方:

# 強化学習なしのモデルの学習
python tools/train.py --cfg configs/fc.yml --id fc

強化学習あり(Self-Critic)のモデルの学習
python tools/train.py --cfg configs/fc_rl.yml --id fc_rl

実験設定

実験設定として、メモリをあまり食わなかったのでバッチサイズを大きくして実験しました。(この時は研究室の共用のマシンを使ってたので小さいバッチサイズは気が引けた)

強化学習なし

  • GeForce GTX 1080Ti×1 (実際に使用したメモリは5,000 MiB+α程度)
  • epoch: 30 (default)
  • batch size: 10(deault)→256
  • pre-trained image feature extractor: ResNet101 (default)
  • learning rate decayあり(以下の通り)(default)
  • scheduled samplingあり(以下の通り)(default)

learning rate decay

学習率は段階的にステップで減少させた
学習率の推移

scheduled samplingする確率

scheduled samplingを行う確率を段階的に上昇させた
scheduled samplingする確率

強化学習あり(Self-Critic)  

  • GeForce GTX 1080Ti×1 (実際に使用したメモリは5,000 MiB+α程度)
  • epoch: 50 (強化学習なし 30 epoch + RL 20epoch) (default)
  • batch size: 10(deault)→256
  • pre-trained image feature extractor: ResNet101 (default)
  • learning rate decayなし ($5.0 \times 10^{-5}$で固定) (default)
  • scheduled samplingなし (default)

学習結果

3000イテレーションごとに、validation set 5000サンプルに対してBLEU、CIDEr(正確にはCIDEr-D)SPICE、train/validation lossを計測してみた結果は以下の通りです。(perplexity, entropyは計算が間違ってる説があったので無視しました)オレンジが強化学習なし青が強化学習あり(Self-Critic)の結果になります。

BLEU(単語n-gramの一致率、高いほど良い)

BLEUは学習経過と共に上昇
BLEUスコアの推移

CIDEr (CIDEr-D) (TF-IDFも考慮した単語n-gramの一致率、高いほど良い)

CIDEr-Dは学習経過と共に上昇
CIDEr-Dスコア

SPICE(シーングラフの一致率、高いほど良い)

SPICE以外のSPICE_なんやらかんやらは、私は知らなかったのですが、一応載せておきます。(元のSPICEはシーングラフのObject, Attribute, Relationをカウントしていたと思いますが、このSPICEは他の要素も計算しているっぽい・・・?)

SPICEはおおむね上昇傾向
SPICEの推移

train/validation loss

train/validation lossは一度下降してから徐々に上昇
train/validation lossの推移

強化学習なし」のみ拡大版

train/validation lossの推移(「強化学習なし」のみ拡大版)

BLEUやCIDEr、SPICEが概ね継続的に上昇している一方で、 train/validation lossは一度減少してから上昇しました。強化学習なし(オレンジ)のlossは一見過学習している曲線のよう見えますが、scheduled samplingの影響でむしろteacher forcing形式への過学習が抑制された結果こうなっているのかなと考えられます。

強化学習あり(Self-Critic;青)のtrain lossは途中で負のlossが発生していて奇妙に見えますが、ここはlossの計算がcross entropyからrewardに切り替わったためでした。期待報酬の最大化は負の期待報酬の最小化に相当するので、これをlossの値として算出しています。前のREINFORCE紹介編の記事に沿って書くと、 以下のようになります。

$loss = -\underset{\hat{Y} \sim \pi_{\theta}}{\mathbb{E}}\left[ \left( r(\hat{Y}) - r_b \right) \log \pi_{\theta} \right]$
(ただし、$r_b = r(\hat{Y}_{greedy})$)

ということで、greedyに生成した文によるCIDErスコアであるベースライン$r_b$によっては負になる場合もあるわけですね。lossが0になるということは、サンプリングした場合の文とgreedyに生成した場合の文が近くなっていると解釈すれば良さそうです。

総合的な結果としては、強化学習なし(オレンジ)よりも強化学習あり(Self-Critic;青)の方が概ね優勢のようです(まだこの先はどうなるか分からないですが)

参考値

ちなみに、リポジトリで公開されている結果だと、以下のようなスコアになるようです。

CIDEr-D SPICE
強化学習なし 0.953 0.1787
Self-Critic 1.045 0.1838

生成例

生成例でもいくつか比べてみました。()内の評価は私の主観です。

生成例1(強化学習なし < Self-Critic)

f:id:snowman_88888:20201214194648p:plain

生成文
強化学習なし a person holding a piece of pizza in a hand
Self-Critic a bowl of broccoli on a plate with a table

Self-Criticでは、plateに野菜が乗ってる感が出てきています。

生成例2(強化学習なし < Self-Critic)

生成文
強化学習なし a close up of a bird on a branch
Self-Critic a piece of cake sitting on top of a plate

強化学習なしでは" bird on a branch"が出てきていましたが、Self-Criticではplateが出てきました。cakeはまあ、いくら丼はキラキラしてるしcakeと判断されるのはわかりみがありますね(piece of cakeとは)。

生成例3(強化学習なし = Self-Critic)

f:id:snowman_88888:20201214195151p:plain

生成文
強化学習なし a person is on a snowboard in the air
Self-Critic a man riding a wave on a surfboard in the ocean

ある忍者村で撮った写真です。空中に浮かんでいるのがスノボやサーフィンをしているように見えたようです。背景は空中なので、強化学習なしの方が若干正しい感じですね。

生成例4(強化学習なし = Self-Critic)

生成文
強化学習なし a person holding a pair of scissors in a hand
Self-Critic a man holding a pair of scissors on a pair of scissors

結構多かったのですが、人間の写っている画像ではscissorsを執拗に出してくる傾向にありました。そんなにハサミを使っている人間が多かったのか・・・

生成例5(強化学習なし > Self-Critic)

f:id:snowman_88888:20201214195621p:plain

生成文
強化学習なし a red and white fire hydrant sitting on a lush green field
Self-Critic a teddy bear sitting on top of a table

Self-Criticは謎にteddy bearを生成しています。何が見えているんだ・・・

生成例2(強化学習なし > Self-Critic)

生成文
強化学習なし a large clock tower with a sky background
Self-Critic a dog sitting on top of a traffic light

Self-Criticでは、 謎にdogが出てきています。

感想

生成文について

  • Self-Criticの方が、少し長めで多様な文を生成してくれてる傾向があった
  • Self-Criticの方が、"a person"を"a man"や"a group of xx"など、より具体的な表現にしてくれる傾向があった

全体的な感想

  • Self-Criticの影響は、生成文を見ても割と大きそう
  • scheduled samplingはしなくても、強化学習を使ってfine-tuningすれば良さそう

次回はコードをREINFORCEに改造してみて結果がどうなるか見てみたいと思います。