- 他のデータセット(今回は犬と猫の分類)を試してみる。
- GPUで学習できるようにする。
- モデルはとりあえずInception v1。
を目指してみた。
Edge TPUのImage classificationのサンプルは「TensorFlow-Slim image classification model library」を使っている。これを簡単にスクリプトから実行できるようにしている。
(Image classificationはKerasが主体になるので、slimを使ってのImage classificationはやったことがなかった。そのへんも理解したい。)
Edge TPUのImage classificationのサンプルは「TensorFlow-Slim image classification model library」を使っている。これを簡単にスクリプトから実行できるようにしている。
(Image classificationはKerasが主体になるので、slimを使ってのImage classificationはやったことがなかった。そのへんも理解したい。)
リポジトリはここに作成した。
https://github.com/NobuoTsukamoto/edge_tpu.git
https://github.com/NobuoTsukamoto/models/tree/edge_tpu
https://github.com/NobuoTsukamoto/models/tree/edge_tpu
環境
自分のPC環境
- CPU AMD Ryzen 7 1700 Eight-Core Processor
- GPU NVIDIA GeForce GTX 1070
- OS Fedora 29
Docker準備
まず、Fedora29にCUDA、Docker、NVIDIA dockerをインストールしておく。
- CUDAのインストールはここ。
- Dockerのインストールはここ(Get Docker CE for Fedora)。
- NVIDIA Dockerのインストールはここ。
(NVIDIA DockerはFedora29はサポートしていないが、CentOS/RHELと同じものをインストールすれば動く)
作業ディレクトリの作成とデータの配置
適当な作業ディレクトリを設定しておく。
学習データはKaggleのDogs vs. Catsで提供されているデータを使用する。
(Kaggleに登録してダウンロードしておく)
ダウンロードしたzipファイルを作業ディレクトリ/data/配下に置く。
学習データはKaggleのDogs vs. Catsで提供されているデータを使用する。
(Kaggleに登録してダウンロードしておく)
ダウンロードしたzipファイルを作業ディレクトリ/data/配下に置く。
$ CLASSIFY_DIR=..../classify && mkdir -p $ mkdir {$CLASSIFY_DIR}/ckpt $ mkdir {$CLASSIFY_DIR}/train $ mkdir {$CLASSIFY_DIR}/data $ mkdir {$CLASSIFY_DIR}/models $ cp dogs-vs-cats-redux-kernels-edition.zip {$CLASSIFY_DIR}/data/
※実は、Dogs vs. Catsのデータはマイクロソフトからもダウンロードできるのだが、一部ファイルが壊れていた。
Docker containerのセットアップ
DockerfileはGPUで学習できるように変更。
あとは、TensorFlowのmodelsをForkしたリポジトリをcloneしている。
(これは、Dogs vs. Catsのデータセットを追加してあるため)
あとは、TensorFlowのmodelsをForkしたリポジトリをcloneしている。
(これは、Dogs vs. Catsのデータセットを追加してあるため)
リポジトリのDockerfileを移動してビルドし、起動してあげる。
$ sudo docker build - < Dockerfile --tag classify-dogcat $ sudo docker run --name edgetpu-classify --rm --runtime=nvidia -it --privileged -p 6006:6006 --mount type=bind,src=${CLASSIFY_DIR},dst=/tensorflow/models/research/slim/transfer_learn classify-dogcat
データセットの準備
学習のためのTF-Recordを作成するためのスクリプトを準備する。
TensorFlow Modelsのdownload_and_convert_flowers.pyを参考にTF-Recordを生成するcreate_tfrecord_dogcat.pyを作成した。
犬、猫それぞれ12500枚から学習用にそれぞれ2,000枚、評価用にそれぞれ500枚を使ってTF-Recordを生成する(学習用:dogcat_train_xxxxx-of-00005.tfrecord、評価用:dogcat_validation_xxxxx-of-00005.tfrecord)。
また、画像とラベルを対応付けるためにslimのdataset_factory.pyを変更し、dogcat.pyを追加した。詳細はこちらを参照。
これで、コンテナ内でTF-Recodeを生成する。
また、画像とラベルを対応付けるためにslimのdataset_factory.pyを変更し、dogcat.pyを追加した。詳細はこちらを参照。
これで、コンテナ内でTF-Recodeを生成する。
# python edge_tpu/dataset/create_tfrecord_dogcat.py ${DATASET_DIR}/dogs-vs-cats-redux-kernels-edition.zip "${DATASET_DIR}"
学習の準備
Inception V1用にPre-trainedモデルのダウンロードと環境変数の登録を行う。
checkpointのダウンロードは、Tensorflowのmodelsで公開されているものを使った。
(Edge TPUのデモで使用するPre-trainedモデルは異なるリンクを指していた。何が違うのかは不明)
Checkpointのダウンロード
環境変数の設定
checkpointのダウンロードは、Tensorflowのmodelsで公開されているものを使った。
(Edge TPUのデモで使用するPre-trainedモデルは異なるリンクを指していた。何が違うのかは不明)
Checkpointのダウンロード
# wget http://download.tensorflow.org/models/inception_v1_2016_08_28.tar.gz # tar xvf inception_v1_2016_08_28.tar.gz # mv inception_v1.ckpt transfer_learn/ckpt/ # rm inception_v1_2016_08_28.tar.gz
環境変数の設定
# network_type=inception_v1 # train_steps=300 # quantize_delay=100 # image_size=224 # scopes=InceptionV1/Logits
学習
train_image_classifier.pyで学習を行う。
Pre-trainedモデルを使用する場合、--checkpoint_exclude_scopesフラグを指定して、出力層の重みをロードしないように指定する(Pre-trainedモデルの出力層と学習したい出力層のラベル数が異なるため。--checkpoint_exclude_scopesフラグで指定する層は${scopes}の環境変数で指定したもの)。
(Edge TPUのでもに含まれるconstants.shのscopes_mapを参照するか、コードから出力層がどのように定義されているかを確認すると良い)
--trainable_scopesは、出力層のみを学習したい場合に指定する。
ここまでは、Edge TPUに限らず一般的な学習の方法だが、--quantize_delayフラグだけは、Edge TPU(というかTensorflow Lite)向けのパラメータとなる。これは、モデルを量子化した際の精度をシミュレートするためのフラグである(詳細はここ)。指定するパラメータはシミュレートを開始するstep数で、ある程度学習が収束してからが良いとある。
全部の層を学習する場合
# python train_image_classifier.py\ --train_dir="${TRAIN_DIR}"\ --dataset_name=dogcat\ --dataset_split_name=train\ --dataset_dir="${DATASET_DIR}"\ --model_name="${network_type}"\ --checkpoint_path="${CKPT_DIR}inception_v1.ckpt"\ --max_number_of_steps="${train_steps}"\ --batch_size=32\ --learning_rate=0.01\ --learning_rate_decay_type=fixed\ --save_interval_secs=60\ --save_summaries_secs=60\ --log_every_n_steps=20\ --optimizer=sgd\ --weight_decay=0.00004\ --clone_on_cpu\ --train_image_size="${image_size}"\ --checkpoint_exclude_scopes="${scopes}"\ --input_queue_memory_factor=16
最終層のみを学習する場合
# python train_image_classifier.py \ --train_dir="${TRAIN_DIR}" \ --dataset_name=dogcat\ --dataset_split_name=train \ --dataset_dir="${DATASET_DIR}" \ --model_name="${network_type}" \ --checkpoint_path="${CKPT_DIR}inception_v1.ckpt"\ --max_number_of_steps="${train_steps}" \ --batch_size=100 \ --learning_rate=0.01 \ --learning_rate_decay_type=fixed \ --save_interval_secs=60 \ --save_summaries_secs=60 \ --log_every_n_steps=20 \ --optimizer=sgd \ --weight_decay=0.00004 \ --quantize_delay="${quantize_delay}" \ --clone_on_cpu \ --train_image_size="${image_size}" \ --checkpoint_exclude_scopes="${scopes}" \ --trainable_scopes="${scopes}"
学習後の確認
テストデータセットを使って評価する。
# python eval_image_classifier.py\ --checkpoint_path="${TRAIN_DIR}"\ --eval_dir="${TRAIN_DIR}"\ --dataset_name=dogcat\ --dataset_split_name=validation\ --dataset_dir="${DATASET_DIR}"\ --model_name="${network_type}"\ --eval_image_size="${image_size}"\ --quantize
全部の層を学習した場合
eval/Accuracy[0.994] eval/Recall_5[1]最終層のみを学習した場合
eval/Accuracy[0.976] eval/Recall_5[1]
この場合も--quantizeフラグは量子化をシミュレートするためのものである。
また悔過kのRecall_5はTop5の再現率であるので2クラス分類では必ず1である。
モデルのエクスポートとEdge TPU向けのモデルの作成
まず、tflite向けのモデルを生成する。
GETTING frozen graph template ...
# mkdir transfer_learn/output # OUTPUT_DIR=/tensorflow/models/research/slim/transfer_learn/output # python export_inference_graph.py \ --alsologtostderr \ --model_name="${network_type}" \ --image_size="${image_size}" \ --output_file="${OUTPUT_DIR}/graph_template.pb" \ --dataset_name=dogcat \ --quantize
CONVERTING from checkpoint to frozen graph ...
# output_tensors=InceptionV1/Logits/Predictions/Softmax # freeze_graph\ --input_graph="${OUTPUT_DIR}/graph_template.pb"\ --input_checkpoint="${TRAIN_DIR}model.ckpt-300"\ --input_binary\ --output_graph="${OUTPUT_DIR}/frozen_graph.pb"\ --output_node_names="${output_tensors}"
CONVERTING from frozen graph to TFLite graph ...
# input_tensors=input # tflite_convert\ --output_file="${OUTPUT_DIR}/inception_v1_dog_cat_tflite_graph.tflite"\ --graph_def_file="${OUTPUT_DIR}/frozen_graph.pb"\ --inference_type=QUANTIZED_UINT8\ --input_arrays="${input_tensors}"\ --output_arrays="${output_tensors}"\ --mean_values=128\ --std_dev_values=128\ --input_shapes="1,${image_size},${image_size},3"
tflite_convertを使うことで、tflite向けのモデルが生成できる。--mean_values、--std_dev_valuesを変えるとどのように変化するのかはまだ調査できていない。
生成した.tfliteファイルをEdge TPU Model CompilerでEdge TPU向けのモデルとして生成し、ダウンロードすればよい。
確認
Raspberry Pi+Edge TPUでモデルを動かしてみる(モデルは全部の層で学習)。
まずは、Dogs vs. Catsから適当なデータ。
$ python3 classify_image.py --model ~/dog_vs_cat/inception_v1_dog_cat_tflite_graph_1554209169_edgetpu.tflite --label ~/dog_vs_cat/labels.txt --image ~/dog_vs_cat/dog.1320.jpg --------------------------- dog Score : 0.996094 $ python3 classify_image.py --model ~/dog_vs_cat/inception_v1_dog_cat_tflite_graph_1554209169_edgetpu.tflite --label ~/dog_vs_cat/labels.txt --image ~/dog_vs_cat/cat.9276.jpg --------------------------- cat Score : 0.996094