Show, Attend and Tell の再現をやる

概要

  • paper: Show, Attend and Tell: Neural Image Caption Generation with Visual Attention
  • Attention 能力を備えたキャプション生成
  • CNN で特徴抽出
  • 抽出した特徴からキャプションを生成するように LSTM を学習
  • 論文の著者は2週間くらい訓練にかけたらしい
  • 私は大学のDeepLearning講座(http://ail.tokyo)で題材にして再現を試みました
  • この記事は「初心者がとりあえず訓練回して簡単な例を生成できるとこまでいった」経緯を書いているだけ(自分はそこまでが大変だったので……)なので、申し訳ないのですがうまくいってる例などは論文を参照してください
  • もし間違ってる(あるいは非効率な)ことがあったら指摘してもらえると幸いです

再現

  • ソース
  • データセット
    • 今回は flickr30k にした(入手に名前とメールアドレスが要る)
    • 3万件の画像と5文ずつの説明文からなる
    • http://shannon.cs.illinois.edu/DenotationGraph/
    • 他に flickr8k と MSCOCO 向けにoptionがある
  • 環境構築
  • 特徴抽出まで:
    • 画像から抽出した特徴量と正解キャプションをpklファイルで固めたい
    • 単語のベクトル表現作るためのdictionary.pklも要る
    • pklファイル生成のコードはkelvinxuさんのところには置いてない(たかが前処理やんけという勢い)
    • 揉めてる: https://github.com/kelvinxu/arctic-captions/issues/1
      • pklファイルのフォーマットはここのコメント4つめくらいに書いてある
    • どうやって作るの: https://github.com/asampat3090/arctic-captions の make_flickr_data.py を使わせていただく
    • ただし dictionary.pkl の作成はうまくいってない(他のissuesで指摘されてる)
      • 正しい dictionary.pkl は気合で作る: カンマなども含めて頻度順に2からインデックスを振っていく(flickr30kは23462まで、cocoは35630までありました)
    • 注意1: caffe の load model は 絶対パスにすること
    • 注意2: asampat3090さんの caffe_cnn 用のコードも手元に置いてimportできるようにしておかなければならない
    • CPU mode のときは caffe_cnn.py L23 set_mode_gpuコメントアウト
    • でもCPUじゃ絶対やらないほうがいいです、現実的な時間では終わらないので(私はCNN側はCPUでやりましたが、LSTM側はGPU使いました)
    • という感じで、kelvinxu/arctic-captions/flickr30k.pyの末尾でロードしているような形のpklファイルを錬成する
  • CNN: 事前に訓練されてる caffe_model を使う
  • メインの訓練:
    • evaluate_coco.py が実行の本体
    • evaluate_flickr30k.py みたいな形でコピーして、オプションを変える
      • 最低限 dataset="flickr30k" とすれば無問題?
    • THEANO_FLAGS='floatX=float32' python eval_flickr30k.py をつける
      • GPU使うときは THEANO_FLAGS='mode=FAST_RUN,device=gpu0,floatX=float32' python evaluate_flickr30.py みたいにする
      • GPU状況の確認はターミナルで $ nvidia-smi すれば見られる
    • もしかしたら flickr30k.py L13 feat_list.append(features[cc[1]]) でエラー吐くかもしれない
      • 変数 features が scipy.sparse.csr_matrix(列重視の疎行列の型)ではなく scipy.sparse.coo_matrix(疎行列の基礎の型) になってるのが問題だった、このままだと列の切り出しがうまくできないので、 features = featurs.tocsr() という操作を挟んでおくと(もしかしたらcopulaにする必要ないかも)おっけー
      • pklからのロードしたときは元がcsrでもcoo扱いになるみたい(そこまで不思議なことでもないけれど)
  • 動作やスペックまわり
    • データちっちゃくして試しにやってみよって思っても精度は出ないし
    • ちっちゃくするときは batch_size あたりも変えましょう
    • 訓練すると途中でも my_caption_model が保存されるのでうまく区切りましょう
    • my_caption_modelはpkl付いてるほうがoptionの情報が保存されてる(と思う)
    • MacBookAir(core i5)のcpu_modeでは1epoch終わらせるのに10時間単位でかかった
    • そもそも pkl ファイルが計8-9GBくらいあるしラップトップでやるのは非理性的
    • 講座で貸し出されていたGPUありインスタンス使ったら100倍以上速くなった
  • 訓練が終わったら
    • generate_caps.py がテスト用の呼び出しをしてくれる

まとめ

  • GPU至上主義
  • 今回初めてまともにCNNやらLSTMやら回してるコード弄った
  • 結局データセットの前処理やら扱いやらが一番面倒なのでは?

という感じでした。一週間くらいずっとコードとにらめっこしてた。