背景
TensorFlowとは、Googleが公開している機械学習プログラムです。本家のサイトに参考になるページがあったので、それを参考にしながら、自分の用意した画像に対して学習する方法を共有します。
使ったもの
Linuxの動くPC
下記の環境で動くことを確認しました。- ノートPC(CPU: Intel Corei7-4600U、メモリ8GB)+ Ubuntu17.10
- Raspberry Pi3B+ + Raspbian Stretch
Raspberry Piを利用する場合、学習はノートPCで行い、結果のデータをRaspberry Piに移動して利用するなどをすると、学習時間を減らせると思います。
判別したい対象の画像
1種類に対して20以上の画像を用意します。(20未満だと学習時にエラーになることがあります。)判別したい種別名をディレクトリ名として、それぞれのディレクトリ構造に画像を置いてください。
今回の記事で利用した画像データはこちらです。
asukiaaa/halake-chair-images
TensorFlowをインストール
参考にするページでPythonというプログラミング言語を通してTensorFlowの実行環境を構築していたので、それに倣って環境を構築します。新しいバージョンのPythonが良いだろうと思うので、この記事ではPython3を利用します。
Python3とPython3のパッケージマネージャーであるpipをインストールします。
sudo apt install python3-pip
Python3のpipでTensorFlowをインストールします。
sudo pip3 install tensorflow tensorflow-hub
自分がRasbpianで試した時はlibatlasに関するエラーが出ましたが、下記のコマンドでlibatlasをインストールすると解決しました。
sudo apt install libatlas3-base
サンプルを実行
背景でも紹介した下記のページを参考に、テストデータに対して学習プログラムを実行します。How to Retrain an Image Classifier for New Categories
作業用ディレクトリを作成
今回の記事のプログラムを動かすためのディレクトリを作って、その中に移動します。mkdir ~/tensor-train cd tensor-train
学習
学習対象データをダウンロードします。curl -LO http://download.tensorflow.org/example_images/flower_photos.tgz tar xzf flower_photos.tgz
このサンプルでは1種類に対して600個以上の画像が用意された5種類の花を学習するようです。(daisy: ヒナギク、dandelion: タンポポ、rose: バラ、sunflower: ひまわり、tulip: チューリップ)
学習を行うプログラムをダウンロードします。
wget https://raw.githubusercontent.com/tensorflow/hub/52d5066e925d345fbd54ddf98b7cadf027b69d99/examples/image_retraining/retrain.py
学習を行います。
ノートPCだと30分くらい、Raspberry Piだと3時間くらいかかりました。
python3 retrain.py --image_dir flower_photos
上記のプログラムを実行すると、90MBくらいのグラフデータ(学習結果)が/tmpディレクトリに出力されます。
下記のコマンドでサイズを確認できます。(# で始まる行はコメントなので、入力しなくてよいです。)
ls -la /tmp/output_graph.pb # -rw-r--r-- 1 asuki asuki 87523054 7月 21 14:26 /tmp/output_graph.pb # 87MB
学習結果を利用して判別
出力されたグラフデータ(/tmp/output_graph.pb)とラベルデータ(/tmp/output_labels.txt)を利用して、画像に写っている物体を判別します。判別プログラムをダウンロードします。
wget https://raw.githubusercontent.com/tensorflow/tensorflow/master/tensorflow/examples/label_image/label_image.py
下記のようなコマンドで学習結果を利用して判別を行なえます。
python3 label_image.py \ --graph=/tmp/output_graph.pb --labels=/tmp/output_labels.txt \ --input_layer=Placeholder \ --output_layer=final_result \ --image=flower_photos/daisy/21652746_cc379e0eea_m.jpg
99%の確率でヒナギクだという結果が出力されました。
daisy 0.99792874 sunflowers 0.0012147657 dandelion 0.00043442898 tulips 0.00033576202 roses 8.6313376e-05
学習結果を保存
/tmpディレクトリに置いたままだとOSによって消されることがあるので、学習結果(フラフとラベルのデータ)を保存したい場合は、出力されたファイルを移動させます。mv /tmp/output_graph.pb ./ mv /tmp/output_labels.txt ./
移動させたファイルを利用して判別を行う場合は、コマンドに渡すグラフとラベルのパスを変えてプログラムを実行します。
python3 label_image.py \ --graph=output_graph.pb --labels=output_labels.txt \ --input_layer=Placeholder \ --output_layer=final_result \ --image=flower_photos/daisy/21652746_cc379e0eea_m.jpg
mobilenetの学習結果を出力
mobilenetとは、機械学習の結果を携帯端末で利用するのを目的として作られた、比較的軽量なデータ形式です。「90MB近くの学習結果を扱うのは難しい」という場合は、下記のコマンドでmobilenetの形式でグラフデータを出力できます。
python3 retrain.py \ --image_dir flower_photos \ --tfhub_module https://tfhub.dev/google/imagenet/mobilenet_v2_100_224/feature_vector/1
上記のコマンドで出力したグラフデータは9MBくらいでした。
ls -la /tmp/output_graph.pb # -rw-r--r-- 1 asuki asuki 9204105 7月 21 15:17 /tmp/output_graph.pb # 9.2MB
mobilenetの学習結果で判別
下記のコマンドでmobilenetのグラフデータを用いた判別を行なえます。ヒナギクの画像を--imageに渡しています。
python3 label_image.py \ --graph=/tmp/output_graph.pb --labels=/tmp/output_labels.txt \ --input_layer=Placeholder \ --output_layer=final_result \ --input_height=224 --input_width=224 \ --image=`pwd`/flower_photos/daisy/21652746_cc379e0eea_m.jpg
99%の確率でヒナギクだという結果が出力されました。
daisy 0.99240065 sunflowers 0.0067252107 dandelion 0.0007642565 tulips 6.780581e-05 roses 4.2129705e-05
mobilenetの学習結果を保存
90MBのグラフデータと同様に、学習結果を/tmpに置いたままだとOSによって消されてしまうことがあるので、結果を保存したい場合はファイルを移動させます。下記のコマンドでは、90MBのファイルと名前が被るのを避けるために、「mobilenet」を含むファイル名に変更しています。
mv /tmp/output_graph.pb ./mobilenet_graph.pb mv /tmp/output_labels.txt ./mobilenet_labels.txt
グラフとラベルのファイルパスを変えれば、保存したファイルを利用して画像の判別を行なえます。
python3 label_image.py \ --graph=mobilenet_graph.pb --labels=mobilenet_labels.txt \ --input_layer=Placeholder \ --output_layer=final_result \ --input_height=224 --input_width=224 \ --image=flower_photos/daisy/21652746_cc379e0eea_m.jpg
用意したデータに対する学習と判別
画像を用意
「flower_photos」のディレクトリ構造を参考に、ラベル名をディレクトリ名として、画像ファイルを配置します。コワーキングスペース HaLakeに置いてある椅子を分類するためのデータをこのように用意してみました。
asukiaaa/halake-chair-images
halake-chair-images |- train | |- balance | | |- バランスボールが載った椅子の画像 20個以上 | |- round | | |- 丸っこい椅子の画像 20個以上 | |- sofa | |- ソファーの画像 20個以上 |- test |- balance | |- バランスボールが載った椅子の画像 |- round | |- 丸っこい椅子の画像 |- sofa |- ソファーの画像
一つの種類の画像を10個くらいで学習しようとしたところ、下記のような警告が出た後にエラーが出て終了しました。
そのため、一つの種類に対して最低20個は画像データを用意しておくのが良さそうです。
INFO:tensorflow:Looking for images in 'balance' WARNING:tensorflow:WARNING: Folder has less than 20 images, which may cause issues. INFO:tensorflow:Looking for images in 'round' WARNING:tensorflow:WARNING: Folder has less than 20 images, which may cause issues. INFO:tensorflow:Looking for images in 'sofa' WARNING:tensorflow:WARNING: Folder has less than 20 images, which may cause issues.
このデータを利用して学習と判別を試してみたい場合は、下記のようなコマンドでデータをダウンロードできます。
sudo apt install git git clone https://github.com/asukiaaa/halake-chair-images.git
TensorFlow標準の形式で学習・判別
halake-chair-images/testを入力として、学習します。python3 retrain.py --image_dir halake-chair-images/train
結果が消えるのを防ぐために、学習結果を/tmpディレクトリから移動させます。
mv /tmp/output_graph.pb ./halake-chair-graph.pb mv /tmp/output_labels.txt ./halake-chair-labels.txt
作成されたデータは、花の判別のときと同じく、90MBくらいでした。
学習に利用する画像の量に関係なく、出力される結果のデータサイズは同じようです。
ls -la halake-chair-graph.pb # -rw-r--r-- 1 asuki asuki 87506662 7月 22 13:44 halake-chair-graph.pb # 87MB
下記のようなコマンドで判別できます。
このコマンドは、テスト用のバランスボールが載った椅子の画像を「--image」として渡して判別しようとしています。
python3 label_image.py \ --graph=halake-chair-graph.pb --labels=halake-chair-labels.txt \ --input_layer=Placeholder \ --output_layer=final_result \ --image=halake-chair-images/test/balance/IMG_20180722_155644.jpg
上記のコマンドを実行すると、99%の確率でバランスボールの載った椅子であるという下記のような結果が得られました。
balance 0.9997631 sofa 0.00016037884 round 7.6473036e-05
mobilenet形式の出力で学習・判別
halake-chari-imagesを入力として、mobilenet形式の結果を出力する学習を行います。python3 retrain.py \ --image_dir halake-chair-images/train \ --tfhub_module https://tfhub.dev/google/imagenet/mobilenet_v2_100_224/feature_vector/1
結果が消えるのを防ぐために、学習結果を/tmpディレクトリから移動させます。
mv /tmp/output_graph.pb ./halake-chair-mobilenet-graph.pb mv /tmp/output_labels.txt ./halake-chair-mobilenet-labels.txt
tenstoflow形式のときと同じように、学習データの大きさが違っても同じくらいの大きさのデータが出力されるようです。
ls -la halake-chair-mobilenet-graph.pb # -rw-r--r-- 1 asuki asuki 9193852 7月 22 13:51 halake-chair-mobilenet-graph.pb # 9.2MB
下記のようなコマンドで判別できます。
TensorFlow標準の形式のときと同じように、バランスボールの載った椅子の判別をしようとしています。
python3 label_image.py \ --graph=halake-chair-mobilenet-graph.pb --labels=halake-chair-mobilenet-labels.txt \ --input_layer=Placeholder \ --output_layer=final_result \ --input_height=224 --input_width=224 \ --image=halake-chair-images/test/balance/IMG_20180722_155644.jpg
上記のコマンドを実行すると、99%の確率でバランスボールの載った椅子であるという下記のような結果が得られました。
balance 0.9996779 sofa 0.0002461057 round 7.606004e-05
まとめ
自分で用意した画像をTensorFlowで学習して、判別装置を作れました。何かの参考になれば嬉しいです。
0 件のコメント :
コメントを投稿