- 投稿日:2019-03-07T00:02:34+09:00
色々な環境でDeep Learningアプリケーション開発 (2)
この記事について
機械学習、Deep Learningの専門家ではない人が、Deep Learningを応用したアプリケーションを作れるようになるのが目的です。特に、組み込み向けアプリケーションを意識しています。
モデルそのものには言及しません。Deep Learningモデルをどうやって使うか、ということに重点を置いています。数学的な話も出てきません。
- Kerasで簡単にMNIST数字識別モデルを作り、Pythonで確認
- TensorFlowモデルに変換してPythonで使用してみる (Windows, Linux)
- TensorFlowモデルに変換してCで使用してみる (Windows, Linux)
- TensorFlow Liteモデルに変換してPythonで使用してみる (Windows, Linux)
- TensorFlow Liteモデルに変換してCで使用してみる (Linux)
- TensorFlow Liteモデルに変換してPython/Cで使用してみる (Raspberry Pi)
今回の内容
- 前回作成したKeras用モデル(.h5)をTensorFlow用モデル(.pb)に変換する
- 変換したTensorFlow用モデルを使って、入力画像から数字識別するアプリケーションを作る
ソースコードとサンプル入力画像: https://github.com/take-iwiw/CNN_NumberDetector/tree/master/02_Tensorflow_Python
なぜ必要? 想定するシナリオ
- TensorFlow用モデルしかないとき
- 社内の機械学習エンジニア様、データサイエンティスト様がTensorFlowでモデルを作成したら、それに対応したアプリケーションを作る必要があります (後述するように変換はできますが)
- 今一番勢いがある?
- ONNXやMMdnnを使用したら、異なるDeepLearning用フレームワーク間でのモデル変換が出来ます
- TensorFlowに対応したアプリケーションの作り方を覚えておけば、大抵のことには対応できると思います
- 動作環境にPython, Kerasがないとき
- C言語用APIが用意されているので、ライブラリと一緒に配布すれば実行先での環境構築は不要です
- お客様にPythonやAnacondaをインストールしてもらうわけにはいきません!
- 今回はPythonで試しますが、C言語での実装の前段階ととらえてください
環境
- OS: Windows 10 (64-bt)
- OS(on VirtualBox): Ubuntu 16.04
- CPU = Intel Core i7-6700@3.4GHz (物理コア=4、論理プロセッサ数=8)
- GPU = NVIDIA GeForce GTX 1070 (← GPUは無くても大丈夫です)
- 開発環境: Anaconda3 64-bit (Python3.6.8)
今回の内容は、WindowsとLinux(Ubuntu)のどちらでも動きますが、本記事の説明はWindowsメインで行います。
Keras用モデル(.h5)をTensorFlow用モデル(*.pb)に変換する
https://medium.com/@pipidog/how-to-convert-your-keras-models-to-tensorflow-e471400b886a のサイトを参考にさせていただき、変換用スクリプトを作りました。現在、FastGFileは非推奨とのことなので、tensorflow.gfile.GFileに置き換えています。
convert_keras_to_tensorflow関数を呼ぶことで、Keras用モデル(.h5)をTensorFlow用モデル(*.pb)に変換できます。また、get_model_info関数を呼ぶことで、変換したTensorFlow用モデルの情報をJSONファイルに保存します。
このスクリプトをそのまま実行すると、前回作成したKeras用モデル(conv_mnist.h5)を、TensorFlow用モデル(conv_mnist.pb)に変換してくれます。keras_to_tensorflow.py# -*- coding: utf-8 -*- # Reference URL: https://medium.com/@pipidog/how-to-convert-your-keras-models-to-tensorflow-e471400b886a import tensorflow as tf from tensorflow.python.keras.models import load_model from tensorflow.python.keras import backend as K from tensorflow.python.framework.graph_util import convert_variables_to_constants import numpy as np import json def freeze_session(sess, keep_var_names=None, output_names=None, clear_devices=True): graph = sess.graph with graph.as_default(): freeze_var_names = list(set(v.op.name for v in tf.global_variables()).difference(keep_var_names or [])) output_names = output_names or [] output_names += [v.op.name for v in tf.global_variables()] input_graph_def = graph.as_graph_def() if clear_devices: for node in input_graph_def.node: node.device = '' frozen_graph = convert_variables_to_constants(sess, input_graph_def, output_names, freeze_var_names) return frozen_graph def convert_keras_to_tensorflow(keras_model_filename, tf_model_filename): model = load_model(keras_model_filename) model.summary() frozen_graph = freeze_session(K.get_session(), output_names=[out.op.name for out in model.outputs]) tf.train.write_graph(frozen_graph, './', tf_model_filename, as_text=False) def get_model_info(tf_model_filename): ops = {} with tf.Session() as sess: with tf.gfile.GFile(tf_model_filename, 'rb') as f: graph_def = tf.GraphDef() graph_def.ParseFromString(f.read()) sess.graph.as_default() _ = tf.import_graph_def(graph_def) for op in tf.get_default_graph().get_operations(): ops[op.name] = [str(output) for output in op.outputs] writer = tf.summary.FileWriter('./logs') writer.add_graph(sess.graph) writer.flush() writer.close() with open(tf_model_filename+'_param.json', 'w') as f: f.write(json.dumps(ops)) if __name__ == '__main__': # convert keras_model_filename = 'conv_mnist.h5' tf_model_filename = 'conv_mnist.pb' convert_keras_to_tensorflow(keras_model_filename, tf_model_filename) get_model_info(tf_model_filename)モデル情報を確認する
上記スクリプトを実行すると、TensorFlow用モデル(conv_mnist.pb)と共に、モデル情報を記した(conv_mnist.pb_param.json)も出力されます。
このモデル情報は非常に重要です。変換したモデルを使用する際に入出力の名前が必要になります。前回モデル作成時に、入力には
Inputを使い、出力は全結合をするDenseを使いsoftmaxを取るようにしました。また、グラフ名はデフォルトではimportになるようです。このような情報をヒントに入出力のTensorを探します。
今回は以下であることが分かります:
- 入力:
import/input_1:0- 出力:
import/dense_1/Softmax:0conv_mnist.pb_param.json{ "import/input_1": [ "Tensor(\"import/input_1:0\", shape=(?, 28, 28, 1), dtype=float32)" ], "import/conv2d_1/kernel": [ "Tensor(\"import/conv2d_1/kernel:0\", shape=(3, 3, 1, 8), dtype=float32)" ], ~略~ "import/dense_1/Softmax": [ "Tensor(\"import/dense_1/Softmax:0\", shape=(?, 10), dtype=float32)" ], ~略~ "import_2/training_1/Adam/Variable_11": [ "Tensor(\"import_2/training_1/Adam/Variable_11:0\", shape=(10,), dtype=float32)" ] }変換したTensorFlow用モデルを使って、入力画像から数字識別するアプリケーションを作る
Spyder上で
number_detector_tensorflow.pyというファイルを開き、以下のようなコードを実装します。
動作仕様は前回Keras用に作成したnumber_detector.pyと同じです。TensorFlow呼び出しもこの中でやっているので、少し複雑になっています。
get_tensor_by_nameに先ほど確認した入出力名を設定して、入出力Tensorを取得しています。number_detector_tensorflow.py# -*- coding: utf-8 -*- import cv2 import tensorflow as tf import numpy as np if __name__ == '__main__': img = cv2.imread('resource/4.jpg') cv2.imshow('image', img) img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) img = cv2.resize(img, (28, 28)) img = 255 - img img = img.reshape(1, img.shape[0], img.shape[1], 1) img = img / 255. with tf.Session() as sess: with tf.gfile.GFile('conv_mnist.pb', 'rb') as f: graph_def = tf.GraphDef() graph_def.ParseFromString(f.read()) sess.graph.as_default() _ = tf.import_graph_def(graph_def) tensor_input = sess.graph.get_tensor_by_name('import/input_1:0') tensor_output = sess.graph.get_tensor_by_name('import/dense_1/Softmax:0') probs = sess.run(tensor_output, {tensor_input: img}) result = np.argmax(probs[0]) score = probs[0][result] print("predicted number is {} [{:.2f}]".format(result, score)) cv2.waitKey(0) cv2.destroyAllWindows()次回は、今回作成したTensorFlow用モデル(conv_mnist.pb)を、C言語から使用してみます。
- 投稿日:2019-03-07T00:02:34+09:00
Deep Learningアプリケーション開発 (2) TensorFlow with Python
この記事について
機械学習、Deep Learningの専門家ではない人が、Deep Learningを応用したアプリケーションを作れるようになるのが目的です。特に、組み込み向けアプリケーションを意識しています。
モデルそのものには言及しません。数学的な話も出てきません。Deep Learningモデルをどうやって使うか(推論)、ということに重点を置いています。
- Kerasで簡単にMNIST数字識別モデルを作り、Pythonで確認
- TensorFlowモデルに変換してPythonで使用してみる (Windows, Linux)
- TensorFlowモデルに変換してCで使用してみる (Windows, Linux)
- TensorFlow Liteモデルに変換してPythonで使用してみる (Windows, Linux)
- TensorFlow Liteモデルに変換してCで使用してみる (Linux)
- TensorFlow Liteモデルに変換してPython/Cで使用してみる (Raspberry Pi)
今回の内容
- 前回作成したKeras用モデル(.h5)をTensorFlow用モデル(.pb)に変換する
- 変換したTensorFlow用モデルを使って、入力画像から数字識別するアプリケーションを作る
ソースコードとサンプル入力画像: https://github.com/take-iwiw/CNN_NumberDetector/tree/master/02_Tensorflow_Python
なぜ必要? 想定するシナリオ
- TensorFlow用モデルしかないとき
- 社内の機械学習エンジニア様、データサイエンティスト様がTensorFlowでモデルを作成したら、それに対応したアプリケーションを作る必要があります (後述するように変換はできますが)
- 今一番勢いがある?
- ONNXやMMdnnを使用したら、異なるDeepLearning用フレームワーク間でのモデル変換が出来ます
- TensorFlowに対応したアプリケーションの作り方を覚えておけば、大抵のことには対応できると思います
- 動作環境にPython, Kerasがないとき
- C言語用APIが用意されているので、ライブラリと一緒に配布すれば実行先での環境構築は不要です
- お客様にPythonやAnacondaをインストールしてもらうわけにはいきません!
- 今回はPythonで試しますが、C言語での実装の前段階ととらえてください
環境
- OS: Windows 10 (64-bt)
- OS(on VirtualBox): Ubuntu 16.04
- CPU = Intel Core i7-6700@3.4GHz (物理コア=4、論理プロセッサ数=8)
- GPU = NVIDIA GeForce GTX 1070 (← GPUは無くても大丈夫です)
- 開発環境: Anaconda3 64-bit (Python3.6.8)
- TensorFlow 1.12.0
- パッケージ詳細はこちら Windows用、Linux用
今回の内容は、WindowsとLinux(Ubuntu)のどちらでも動きますが、本記事の説明はWindowsメインで行います。
Keras用モデル(.h5)をTensorFlow用モデル(*.pb)に変換する
https://medium.com/@pipidog/how-to-convert-your-keras-models-to-tensorflow-e471400b886a のサイトを参考にさせていただき、変換用スクリプトを作りました。現在、FastGFileは非推奨とのことなので、tensorflow.gfile.GFileに置き換えています。
convert_keras_to_tensorflow関数を呼ぶことで、Keras用モデル(.h5)をTensorFlow用モデル(*.pb)に変換できます。また、get_model_info関数を呼ぶことで、変換したTensorFlow用モデルの情報をJSONファイルに保存します。
このスクリプトをそのまま実行すると、前回作成したKeras用モデル(conv_mnist.h5)を、TensorFlow用モデル(conv_mnist.pb)に変換してくれます。keras_to_tensorflow.py# -*- coding: utf-8 -*- # Reference URL: https://medium.com/@pipidog/how-to-convert-your-keras-models-to-tensorflow-e471400b886a import tensorflow as tf from tensorflow.python.keras.models import load_model from tensorflow.python.keras import backend as K from tensorflow.python.framework.graph_util import convert_variables_to_constants import numpy as np import json def freeze_session(sess, keep_var_names=None, output_names=None, clear_devices=True): graph = sess.graph with graph.as_default(): freeze_var_names = list(set(v.op.name for v in tf.global_variables()).difference(keep_var_names or [])) output_names = output_names or [] output_names += [v.op.name for v in tf.global_variables()] input_graph_def = graph.as_graph_def() if clear_devices: for node in input_graph_def.node: node.device = '' frozen_graph = convert_variables_to_constants(sess, input_graph_def, output_names, freeze_var_names) return frozen_graph def convert_keras_to_tensorflow(keras_model_filename, tf_model_filename): model = load_model(keras_model_filename) model.summary() frozen_graph = freeze_session(K.get_session(), output_names=[out.op.name for out in model.outputs]) tf.train.write_graph(frozen_graph, './', tf_model_filename, as_text=False) def get_model_info(tf_model_filename): ops = {} with tf.Session() as sess: with tf.gfile.GFile(tf_model_filename, 'rb') as f: graph_def = tf.GraphDef() graph_def.ParseFromString(f.read()) sess.graph.as_default() _ = tf.import_graph_def(graph_def) for op in tf.get_default_graph().get_operations(): ops[op.name] = [str(output) for output in op.outputs] writer = tf.summary.FileWriter('./logs') writer.add_graph(sess.graph) writer.flush() writer.close() with open(tf_model_filename+'_param.json', 'w') as f: f.write(json.dumps(ops)) if __name__ == '__main__': # convert keras_model_filename = 'conv_mnist.h5' tf_model_filename = 'conv_mnist.pb' convert_keras_to_tensorflow(keras_model_filename, tf_model_filename) get_model_info(tf_model_filename)モデル情報を確認する
上記スクリプトを実行すると、TensorFlow用モデル(conv_mnist.pb)と共に、モデル情報を記した(conv_mnist.pb_param.json)も出力されます。
このモデル情報は非常に重要です。変換したモデルを使用する際に入出力の名前が必要になります。前回モデル作成時に、入力には
Inputを使い、出力は全結合をするDenseを使いsoftmaxを取るようにしました。また、グラフ名はデフォルトではimportになるようです。このような情報をヒントに入出力のTensorを探します。
今回は以下であることが分かります:
- 入力:
import/input_1:0- 出力:
import/dense_1/Softmax:0conv_mnist.pb_param.json{ "import/input_1": [ "Tensor(\"import/input_1:0\", shape=(?, 28, 28, 1), dtype=float32)" ], "import/conv2d_1/kernel": [ "Tensor(\"import/conv2d_1/kernel:0\", shape=(3, 3, 1, 8), dtype=float32)" ], ~略~ "import/dense_1/Softmax": [ "Tensor(\"import/dense_1/Softmax:0\", shape=(?, 10), dtype=float32)" ], ~略~ "import_2/training_1/Adam/Variable_11": [ "Tensor(\"import_2/training_1/Adam/Variable_11:0\", shape=(10,), dtype=float32)" ] }変換したTensorFlow用モデルを使って、入力画像から数字識別するアプリケーションを作る
Spyder上で
number_detector_tensorflow.pyというファイルを開き、以下のようなコードを実装します。
動作仕様は前回Keras用に作成したnumber_detector.pyと同じです。TensorFlow呼び出しもこの中でやっているので、少し複雑になっています。
get_tensor_by_nameに先ほど確認した入出力名を設定して、入出力Tensorを取得しています。number_detector_tensorflow.py# -*- coding: utf-8 -*- import cv2 import tensorflow as tf import numpy as np if __name__ == '__main__': img = cv2.imread('resource/4.jpg') cv2.imshow('image', img) img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) img = cv2.resize(img, (28, 28)) img = 255 - img img = img.reshape(1, img.shape[0], img.shape[1], 1) img = img / 255. with tf.Session() as sess: with tf.gfile.GFile('conv_mnist.pb', 'rb') as f: graph_def = tf.GraphDef() graph_def.ParseFromString(f.read()) sess.graph.as_default() _ = tf.import_graph_def(graph_def) tensor_input = sess.graph.get_tensor_by_name('import/input_1:0') tensor_output = sess.graph.get_tensor_by_name('import/dense_1/Softmax:0') probs = sess.run(tensor_output, {tensor_input: img}) result = np.argmax(probs[0]) score = probs[0][result] print("predicted number is {} [{:.2f}]".format(result, score)) cv2.waitKey(0) cv2.destroyAllWindows()次回は、今回作成したTensorFlow用モデル(conv_mnist.pb)を、C言語から使用してみます。