Tensorflowでの画像分類(ラズパイカメラも使ってみた)

いまどき深層学習のツールの使い方くらい知らないと恥ずかしいとずっと思っていながら何年も後回しにしてきたが、最近ようやくきっかけがつかめてPyTorchを使い始めた。イチからネットワークをどう作るかというのはいまだ神秘の技にしか思えないけど、今実用的な使い方に関してはたいていサンプルがあるので、これを自分のデータに適用するだけなら難しいことはなさそう。
で、いろいろチュートリアルを見ている中で画像の分類器(Classification)の部分に差し掛かり、ちょっとやってみたので報告。
ただし、自分の手持ちの古いWindows内に置いてある画像に対して実行したいと思っていて、PyTorchをこのWindowsにインストールすることは失敗し、TensorFlowでは動いたので、今回に限りTensorFlowでやってみた。ちなみにこのWindows、最近爆音の異音がするようになってきたので、そろそろ乗換かなあと思っております。最近ノートPCでもかなりのGPUを載せて機械学習もできるとのこと。ただ調べてみたら軒並み3kg近くあり、あまりオサレでないのは確か。どうしたもんかなあ。

深層学習での画像の分類には、移転学習(transfer learning)という方法を使うと効率よく作れるらしい。これは、すでに多数のクラスに関して学習が済んだ認識器の、出力のところだけ自分用の認識器に替えてそこを学習させるというもので、短時間で学習が完了する。もちろん膨大なマシンパワーを持っている人なら最初から学習させてもいいんだろうけど、それをやると一週間とか学習時間がかかることもざらだとか。移転学習を使えばCPUで計算させても30分ほど、GPUを使えば1分もかからずに学習が終了するんだって!

TensorFlowのページにやり方が書いてあるので、まずはPyTorchのほうにあったデータを食わせてみたら、確かに僕のCORE i7ノートでも30分くらい(計ってないけど)で学習が終了しました。表示をみていたら4000回ステップを回しているけど、1000回に満たないくらいからaccuracy=100%に達していたので、もうそれくらいで充分なのかも。

やり方(Tensorflow自体はインストール済みとする):

まず、pipパッケージのtensorflow-hubというのをインストールする

pip3 install tensorflow-hub

次に、移転学習のサンプルプログラムを落としてくる。

curl -LO https://github.com/tensorflow/hub/raw/r0.1/examples/image_retraining/retrain.py

教師データとしては、あるフォルダー内にデータのラベル名のサブフォルダーを掘って、その下にそのラベルに該当する画像をたくさん放り込んでおく。例えば上記のPyTorchのサンプルでは、ハチの画像群とアリの画像群がdata/train/ants/ とdata/train/bees/に含まれているので、このままのフォルダー構造でよい(というわけでフォルダー名は大事)
これで学習を開始するにはこうする。

python3 retrain.py --image_dir data/train

すると、image_dirに指定されたフォルダ内の、サブフォルダ内の画像を使って学習してくれる。
ここが30分くらいかかるところ。
プログラムが終了したら、結果は/tmpの下に出力されるとのことだったが、僕の環境ではpythonをcygwinのやつではなくて普通のWindows用のやつにしたためか、結果は(cygwinで見るところの)/tmpではなく、Windowsのc:\tmpの下であった。cygwinで言えば/cygdrive/c/tmpである。ここは注意点。

以下のコマンドで学習結果を可視化できるサーバが立ちあがるそうな。

tensorboard --logdir /tmp/retrain_logs

こうしておいて、ブラウザからhttp://localhost:6006/にアクセスすると結果が見えるらしいが、僕のPCのファイアーウォールの設定のせいか、見えませんでした。まあとにかく、c:\tmpの下にある学習結果ファイルoutput_graph.pbと、ラベルが書かれたファイルoutput_labels.txtを使うと、新しい認識器を使えるので次にそれを示す。

学習結果の適用

学習結果を適用するためのスクリプトを落としてくる。

curl -LO https://github.com/tensorflow/tensorflow/raw/master/tensorflow/examples/label_image/label_image.py
python3 label_image.py \
--graph=output_graph.pb --labels=output_labels.txt \
--input_layer=Placeholder \
--output_layer=final_result \
--image=TestInputImage.jpg

結果はこんな感じである。

ants 0.99967587
bees 0.00032412793

これはアリ画像を食わせてみた結果だが、アリである可能性が99.96%で、非常に正確である。

他のデータの学習結果を流用するような方法では精度が落ちるのでは?と漠然と思っていたが、そんなことは全然ありませんでした。使うだけならスクリプトが充実しているので、深層学習の知識なんて何もいらんですな。

ラズパイカメラでやってみる

さて、某所でラズパイでもTensorflow動くということを知ったので、やってみた。(Ref1,Ref2)

いくつかハマりどころはあったが、ラズパイのカメラから読んだ画像を、移転学習で作った認識器で認識するというもの。ハマりどころとしては、最初にデフォルトで使った学習済みモデルはInception-v3というやつなんだけど、それはデータが大きすぎてラズパイ上ではロードできなかったのでMobileNetというのを使ったとか、その場合、入力画像のサイズが違っている、とか、その他軽微なところがいろいろと。MobileNetを使うと学習も早い。やたらMobileNet押せ押せな兄ちゃんも笑
ちなみに、OpenCVも使っているサンプルが多いが、今回僕がやった範囲内では不要。

ラズパイ3Bで実行。幸か不幸か身近にアリやハチはいないためこういう羽目に(笑

ラズパイカメラを介しているが、よく映っていればそれなりに精度は出ている気がする。フレームレートはおおよそ4秒/フレームくらい。他のサイトでもだいたいその位だと書いてあるのでそんなもんなんだろう。

ただし、MobileNetを変更せずにそのまま認識に使うと1秒/フレームくらいだったような気がするので(うろ覚えだが)、移転学習のやり方がよくなかったのかもしれない。TensorFlowのサンプルをそのまま使っただけなんだけど。

あと、やたらアリだと思いたがる傾向がある。何も映ってないときはアリだって思われるし、認識しやすい画像というのはあるんでしょうね。

もっと高速化するには、TensorFlow Liteというのを使うと2~3倍くらいになるらしい。コンパイルはできたがまだ試していない。なんでも、ネットワークそのものも高速実行のために変換する必要があるんだとか。

そしてさらに異次元の高速化を図るにはMovidiusでしょうね。昨日友達から教えてもらったんだけど。これはすごそう。それにしては1万円位で安い。

ラズパイものんびりした認識くらいには使えるらしいことがわかってよかった。