この記事は、自身のブログ、Data Science Struggleを翻訳したものになる。
概略
今日では畳み込みニューラルネットワークは画像分類に対する最適解の一つとして認められてきている。画像の絡む様々な分野で使用されるようになっており、深層学習を学習する際のモチベーションの一つとなっているだろう。
とはいえ、畳み込みニューラルネットワークはいくつかのルールを持っている。
- 大量の画像を要する(タスクによってはそうでもないが)
- 学習に非常に時間がかかる
- 目標達成のための良いモデルを作るために地道で牛歩とも言えるようなステップを踏んでいくこともしばしば
- 実験と失敗を素早く回すためにハイスペック環境が必要
もちろん、畳み込みニューラルネットワークを試すことだけが目的であればライブラリから使用できるフリーデータが使えるわけだし、その手のフリーデータは様々な人が既に実験を行なっているためある程度うまくいくネットワーク情報を簡単に入手することが可能だ。問題になるのは、実際に仕事やプライベートで、設定された問題を実践的に解決していく際の畳み込みニューラルネットワークの利用だ。
上記のルールは見た目以上に重たく目の前に立ちふさがることになる。
そこで、Inception-v3とfine tuneの組み合わせで上記の問題を解決し、畳み込みニューラルネットワークとライトに付き合っていくことで実践的な場での利用に役立てたい。
詳細
Inception-v3とは画像分類を行うためのモデルの一つだ。大規模なネットワークで相当量の画像により訓練済みであり、フリーで公開されているため、比較的簡単に試すことができる。fine tuneとは既にパラメーターの確定したニューラルネットを新規のデータに対応させる仕組みのことだ。
Inception-v3
Inception-v3は上で書いたように画像分類を行うためのモデルの一つであり、フリーで公開されている。
おそらくはハイスペック環境で試行錯誤の下で時間をかけて作成されたネットワークだ。
Fine tune
どんなにInception-v3が画像分類において素晴らしいモデルであったとしても、それは、現在自分たちが対面している画像データで訓練されたものではなく、そのラベルも一致しないため、基本的に問題解決にそのままで役立てるのは難しいだろう。
fine tuneはこの問題を解決してくれる。fine tuneとは、既にパラメーターを確定させたニューラルネットワークのラストの方の層のみを、別のデータで訓練し直し、実質的に、既存モデルの大部分と別データで訓練した新しいレイヤーの組み合わせでモデルを焼き直す仕組みだ。
畳み込みニューラルネットワークの畳み込み層は画像から特徴を際立たせるためのものだが、そこには一種の普遍性がある。ゆえにネットワークとパラメーターの大部分は使いまわすことができ、ラストの方のレイヤーだけを新規データで対応させれば良い。
この方法により、学習において確定させる必要のあるパラメータの数は劇的に減り、時間、必要な環境スペック、データ量を節約することができる。
実践
Inception-v3のfine tuneを試すのは非常に簡単だ。
git clone https://github.com/tensorflow/tensorflow.git
cd tensorflow
./configure
bazel build -c opt --copt=-mavx tensorflow/examples/image_retraining:retrain
bazel-bin/tensorflow/examples/image_retraining/retrain --image_dir IMGDIR
上記のコードでtensorflowの獲得、fine tune実行のためのビルド、fine tuneの実行までなされている。'IMGDIR'はネットワークのレイヤーを書き換えるために使用する自分が用意した画像のディレクトリになる。上記実行の結果であるファイルは/tmpにデフォルトで吐き出される。
import tensorflow as tf
import numpy as np
with tf.gfile.FastGFile('output_graph.pb', 'rb') as f:
graph = tf.GraphDef()
graph.ParseFromString(f.read())
tf.import_graph_def(graph, name='')
with open('output_labels.txt', 'rb') as f:
lines = f.readlines()
labels = [str(w).replace("\n", "") for w in lines]
with tf.Session() as sess:
image_data = tf.gfile.FastGFile('pug.jpg', 'rb').read()
softmax_tensor = sess.graph.get_tensor_by_name('final_result:0')
prediction_outcome = sess.run(softmax_tensor, {'DecodeJpeg/contents:0': image_data})
# delete empty dimension
prediction_outcome = np.squeeze(prediction_outcome)
label = {}
for node_id in range(len(labels)):
label_name = labels[node_id]
# labels
score = '{:.10f}'.format(prediction_outcome[node_id])
label.update({label_name: score})
result = {
'scores': label
}
print(result)
output_graph.pbとoutput_labels.txtがモデルファイルだ。変数'result'が予測結果となっている。
まとめ
畳み込みニューラルネットワークのような、時間、物量の面で制約を持つ仕組みを実践的な場で使用していくのは難しい場面が多くある。
fine tuneのような仕組みをうまく使って、重い仕組みをライトに使っていくことでどんどん実践的な場での問題解決に役立てていきたい。