画像にキャプションを付ける「Show and Tell」のTensorFlow実装を試してみた⇒成功

tensorflow-im2txt-demo
画像にキャプションを付ける「Show and Tell」のTensorFlow実装であるim2txt。以下の記事では玉砕しましたが、状況の変化があったので再チャレンジしてみました。なんと、今回は画像のキャプション生成に成功しました。

画像にキャプションを付ける「Show and Tell」のTensorFlow実装を試してみた⇒玉砕
画像にキャプションを付ける「Show and Tell」のTensorFlow実装がオープンソースになったということなので試してみましたが、見事に玉砕しました。

ニュースソースは、Google Research Blogのこちらの記事(https://research.googleblog.com/2016/09/show-and-tell-image-captioning-open.html)です。

コードが公開されているのは、GitHubのこちら(https://github.com/tensorflow/models/tree/master/im2txt)。

以前の記事では、「Show and Tell」のTensorFlow実装であるim2txtが、TensorFlow 0.10.0にはないTF-Slimの機能を使っているため、エラーが発生したことを報告しました。GitHubのIssuesにも同様の書き込みがあり、TF-Slimの機能が拡張されたTensorFlow 0.11.0rc0ではうまく行ったという報告がありました。

また、相変わらずGoogleからのトレーニング済みモデルの提供はありませんが、有志の方が、トレーニング済みモデルを公開されていたので、再チャレンジしてみました。

なお、この記事では、トレーニング済みモデルを使用するため、1-2週間掛かるといわれているトレーニングは行っていません。

スポンサーリンク

環境構築

NVIDIA Docker

今回も、NVIDIA Docker上でTensorFlowを動作させます。

NVIDIA Dockerのインストール等を行っていない場合、GitHubのNVIDIA Docker(https://github.com/NVIDIA/nvidia-docker)のREADME.md通りに、インストールとテストを行います。

$ wget -P /tmp https://github.com/NVIDIA/nvidia-docker/releases/download/v1.0.0-rc.3/nvidia-docker_1.0.0.rc.3-1_amd64.deb
$ sudo dpkg -i /tmp/nvidia-docker*.deb && rm /tmp/nvidia-docker*.deb

$ nvidia-docker run --rm nvidia/cuda nvidia-smi

TensorFlow (0.11.0rc0-devel-gpu)

今回は、TensorFlow (0.10.0-devel-gpu)の代わりに、TF-Slimの機能が拡張されたTensorFlow (0.11.0rc0-devel-gpu)のイメージをダウンロードします。

$ docker pull tensorflow/tensorflow:0.11.0rc0-devel-gpu

ダウンロードしたイメージから、コンテナを生成します。

$ nvidia-docker run -it -p 8888:8888 tensorflow/tensorflow:0.11.0rc0-devel-gpu

なお、TensorFlow (0.11.0rc0-devel-gpu)のイメージですが、TensorFlowの実行時にlibcuda.so関係のエラーが発生するので、コンテナに入ったら、以下のコマンドでパスを追加しておきます。

# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/nvidia/lib64

tensorflow/models/im2txt

コンテナ側で、githubディレクトリを作成し、「Show and Tell」のTensorFlow実装であるim2txtを含むhttps://github.com/tensorflow/modelsをcloneします。

# cd /
# mkdir github
# cd /github
# git clone https://github.com/tensorflow/models

README.mdによると、im2txtの実行に必要なパッケージは、Bazel、TensorFlow、NumPy、Natural Language Toolkit (NLTK)となっていますが、ダウンロードしたTensorFlow (0.11.0rc0-devel-gpu)のイメージには、Bazel、TensorFlow、NumPyが、インストール済みです。

Natural Language Toolkit (NLTK)

トレーニング済みのモデルを用いてキャプション生成を行う場合、NLTKとNLTK dataのインストールを省略できます。

NLTKとNLTK dataのインストールを行う場合は、以前の記事をご覧ください。

COCO

上記のNLTKと同じく、トレーニング済みのモデルを用いてキャプション生成を行う場合、COCOのダウンロード・前処理を省略できます。

COCOのダウンロード・前処理を行う場合は、以前の記事をご覧ください。

Inception v3

im2txtでは、以下の記事で、画像の分類に用いた画像認識モデルのInception v3を用いて、画像から特徴量を取り出します。

TensorFlowのInception-v3で画像を分類してみた(Python API編)
TensorFlowのチュートリアルの画像認識(Python API編)に従って、Inception-v3による画像の分類にチャレンジしてみました。

Inception v3の準備を行います。

ダウンロードしたTensorFlow (0.11.0rc0-devel-gpu)のイメージには、wgetがインストールされていないので、wgetをインストールします。

# apt-get update
# apt-get install wget

以下のコマンドで、Inception v3のダウンロード・解凍等を行います。

# cd /github/models/im2txt/im2txt/data
# wget http://download.tensorflow.org/models/inception_v3_2016_08_28.tar.gz
# tar xf inception_v3_2016_08_28.tar.gz
# rm inception_v3_2016_08_28.tar.gz

トレーニング済みモデルの準備

本来は、ここからモデルのトレーニングを行いますが、有志の方がトレーニング済みのモデルを公開されているので、今回はこれを使用します。

GitHubのtensorflow/modelsのIssues「Pretrained model for img2txt? #466」(https://github.com/tensorflow/models/issues/466)で「here are links to a pre-trained model:」を検索すると、その書き込みの下に3つのリンクがあります。

(Dockerのコンテナ側ではなく)ホスト側で、finetuned(トレーニング済みのモデル、実態は、im2txt_2016_10_11.2000000.tar.gz)とword_counts.txtをダウンロードし、ダウンロードしたファイルをコンテナ側にコピーします。

$ docker cp im2txt_2016_10_11.2000000.tar.gz <コンテナ名>:/github/models/im2txt/im2txt
$ docker cp word_counts.txt <コンテナ名>:/github/models/im2txt/im2txt

コンテナ側で、トレーニング済みのモデルの解凍等を行います。

# cd /github/models/im2txt/im2txt
# tar xf im2txt_2016_10_11.2000000.tar.gz
# rm im2txt_2016_10_11.2000000.tar.gz

キャプション生成

上記の有志の方がトレーニング済みモデルと共に公開されているword_counts.txtですが、本来のフォーマットと違うため、/github/models/im2txt/im2txt/inference_utils/vocabulary.pyの49行目を

reverse_vocab = [line.split()[0] for line in reverse_vocab]

から

reverse_vocab = [eval(line.split()[0]) for line in reverse_vocab]

に変更します。

次に、run_inferenceスクリプトをビルドします。

# cd /github/models/im2txt
# bazel build -c opt im2txt/run_inference

ホスト側からコンテナ側にキャプション生成させたい画像ファイル(ここでは、/github/models/im2txt/im2txtディレクトリにCOCO_val2014_000000224477.jpgとPASCAL VOC2007の004545.jpg)をコピーした後、run_inferenceバイナリを実行します。

GitHubのREADME.mdとの違いは、checkpoint stateファイルがないため、--checkpoint_pathオプションで、モデルディレクトリではなく、モデルファイルを直接指定している点です。
また、--input_filesオプションに、”,"つなぎで、2つの画像ファイルを指定しています。

# bazel-bin/im2txt/run_inference \
  --checkpoint_path=im2txt/model.ckpt-2000000 \
  --vocab_file=im2txt/word_counts.txt \
  --input_files=im2txt/COCO_val2014_000000224477.jpg,im2txt/004545.jpg

それぞれの画像と生成されたキャプションは、以下の通りです。

COCO_val2014_000000224477.jpg

COCO_val2014_000000224477.jpg

Captions for image COCO_val2014_000000224477.jpg:
  0) a man riding a wave on top of a surfboard . (p=0.036315)
  1) a person riding a surf board on a wave (p=0.016300)
  2) a man on a surfboard riding a wave . (p=0.010876)

GitHubのREADME.mdとは、少し異なった結果となっていますが、いい感じです。

PASCAL VOC2007の004545.jpgに対しては、少し間違っているような・・・。

PASCAL VOC2007 004545.jpg

PASCAL VOC2007の004545.jpg

Captions for image 004545.jpg:
  0) a man riding on the back of a brown horse . (p=0.013252)
  1) a man riding on the back of a horse . (p=0.000469)
  2) a man riding on the back of a brown horse on a dirt field . (p=0.000178)

まとめ

画像にキャプションを付ける「Show and Tell」のTensorFlow実装であるim2txtに再チャレンジしてみました。今回は画像のキャプション生成に成功しました。