- 投稿日:2019-11-29T13:58:33+09:00
MacでTensorFlow Liteを実装する【2019年版】
MacでTensorFlow Liteを動かすまでの流れを解説していきます。
環境
動作確認済の環境は以下の通りです。
・macOS Catalina バージョン10.15
・Python 3.7.4
・conda 4.7.12
・TensorFlow 1.15.0
・keras 2.2.4環境構築
以下のURLよりAnacondaをインストール
https://www.anaconda.com/distribution/
ダウンロードしたインストーラパッケージをダブルクリックして起動します。 利用規約に同意し、保存先を決めてインストールします。
HomeからJupyter Notebookを起動します。
作業場所を決めて、NEW→Python3でipynbファイルを作成します。
ファイルを開くとこのようにプログラムを書ける画面に移ります。ここにプログラムを書いていきます。
次にTensorFlowを動作させるためのパッケージをインストールします。
「Enviroments」→「Create」で新しい環境を作ります。base(root)を使用する場合は不要です。
検索条件を「Not installed」に変更し、「tensorflow」と検索します。
そして出てきたパッケージの「keras」、「tensorflow」を選択し、Applyをクリックします。
先程のようにJupyterを起動して次のようにプログラムを書いて実行します。
実行は「control + Enter」もしくは「Shift + Enter」です。
エラーが出ていないことがわかります。使い方はざっとこんな感じです。追記
nomkl、matplotlib、pillowもインストールしておいてください。
nomklはtensorflowを実行する際にカーネルが死ぬのを防げるみたいです。
matplotlibは画像を表示するために使用します。
pillowは画像をロードするために使用します。モデルを構築する
TensorFlow Liteのモデルを生成するために、まずはTensorFlowのモデルを作る必要があります。
今回は、cifar10というデータセットを使用します。
https://www.cs.toronto.edu/~kriz/cifar.html
cifar10は、6万枚の画像にラベル付けされたデータセットです。飛行機、自動車、鳥、猫、鹿、犬、カエル、馬、船、トラックに分けられています。これを学習させ、画像分類できるモデルを作っていきます。以下、画像を学習させるためのコードです。
epoch数を20に設定しているのでかなり時間がかかります。""" 必要なライブラリのインポートと画像の前処理 """ from keras.models import Sequential from keras.layers.convolutional import Conv2D from keras.layers.pooling import MaxPool2D from keras.layers.core import Dense,Activation,Dropout,Flatten from keras.datasets import cifar10 from keras.utils import np_utils #cifar10をダウンロード (x_train,y_train),(x_test,y_test)=cifar10.load_data() #画像を0-1の範囲で正規化 x_train=x_train.astype('float32')/255.0 x_test=x_test.astype('float32')/255.0 #正解ラベルをOne-Hot表現に変換 y_train=np_utils.to_categorical(y_train,10) y_test=np_utils.to_categorical(y_test,10) """ TensorFlowのモデルを構築 """ model=Sequential() model.add(Conv2D(32,(3,3),padding='same',input_shape=(32,32,3))) model.add(Activation('relu')) model.add(Conv2D(32,(3,3),padding='same')) model.add(Activation('relu')) model.add(MaxPool2D(pool_size=(2,2))) model.add(Dropout(0.25)) model.add(Conv2D(64,(3,3),padding='same')) model.add(Activation('relu')) model.add(Conv2D(64,(3,3),padding='same')) model.add(Activation('relu')) model.add(MaxPool2D(pool_size=(2,2))) model.add(Dropout(0.25)) model.add(Flatten()) model.add(Dense(512)) model.add(Activation('relu')) model.add(Dropout(0.5)) model.add(Dense(10,activation='softmax')) model.compile(optimizer='adam',loss='categorical_crossentropy',metrics=['accuracy']) history=model.fit(x_train,y_train,batch_size=128,nb_epoch=20,verbose=1,validation_split=0.1) #モデルと重みを保存 json_string=model.to_json() open('cifar10_cnn.json',"w").write(json_string) model.save_weights('cifar10_cnn.h5') model.save('cifar10_cnn_model.h5') #モデルの表示 model.summary() #評価 score=model.evaluate(x_test,y_test,verbose=0) print('Test loss:',score[0]) print('Test accuracy:',score[1])実行すると
「cifar10_cnn.h5」と「cifar10_cnn_model.h5」というファイルが生成されているかと思います。
「cifar10_cnn.h5」はモデルの重みのみが保存され、「cifar10_cnn_model.h5」はモデル構造と重みが保存されています。精度は78%でした。
以下のサイトを参考にするとより精度を上げられそうです。CIFAR-10でaccuracy95%--CNNで精度を上げるテクニック--
10層の畳み込みニューラルネットワークでCIFAR-10のValidation Accuracy9割を達成する実際に画像分類してみる
保存したモデルを使って画像分類していきます。
まず、予測する画像を用意します。
コードに書かれている階層に合わせてフォルダを作成し、その中に画像を入れ、以下のコードを実行します。
""" 拾った画像を使って予測する """ from keras.models import model_from_json import matplotlib.pyplot as plt from keras.preprocessing.image import img_to_array, load_img from tensorflow.python.keras.models import load_model #画像読み込み temp_img=load_img("./images/airplane1.jpeg",target_size=(32,32)) #画像を配列に変換し0-1で正規化 temp_img_array=img_to_array(temp_img) temp_img_array=temp_img_array.astype('float32')/255.0 temp_img_array=temp_img_array.reshape((1,32,32,3)) #学習済みのモデルと重みを読み込む json_string=open('cifar10_cnn.json').read() model=model_from_json(json_string) model.compile(optimizer='adam',loss='categorical_crossentropy',metrics=['accuracy']) model.load_weights('cifar10_cnn.h5') # model = load_model('cifar10_cnn_model.h5') #モデルを表示 model.summary() #画像を予想 img_pred=model.predict_classes(temp_img_array) print('\npredict_classes=',img_pred) print('model=',model) plt.imshow(temp_img) plt.title('pred:{}'.format(img_pred)) plt.show() """ 0 - airplane 1 - automobile 2 - bird 3 - cat 4 - deer 5 - dog 6 - frog 7 - horse 8 - ship 9 - truck """上手くいくと、画像とインデックス番号が出力されます。
↑こんな感じ
インデックス番号と画像が一致していることがわかります。画像分類成功です。TensorFlow Lite用モデルに変換
そして、先程生成したモデルをTensorFlowLite用に変換します。
#既存のKeras用モデル(cifar10_cnn_model.h5)から、TensorFlow Lite用モデル(cifar10_cnn.tflite)を作成 import tensorflow as tf if __name__ == '__main__': converter = tf.lite.TFLiteConverter.from_keras_model_file("cifar10_cnn_model.h5") tflite_model = converter.convert() open("cifar10_cnn.tflite", "wb").write(tflite_model)こちらのコードを実行すると「cifar10_cnn.tflite」が生成されます。
これがTensorFlowLite用のモデルです。このモデルを使用して、画像分類してみます。
#TensorFlow Lite用モデルを使って、入力画像からジャンル識別する import tensorflow as tf import numpy as np from keras.models import model_from_json import matplotlib.pyplot as plt from keras.preprocessing.image import img_to_array, load_img from tensorflow.python.keras.models import load_model if __name__ == '__main__': # prepara input image #画像読み込み temp_img=load_img("./images/dog1.jpeg",target_size=(32,32)) #画像を配列に変換し0-1で正規化 temp_img_array=img_to_array(temp_img) img=temp_img_array.astype('float32')/255.0 img=temp_img_array.reshape((1,32,32,3)) # load model interpreter = tf.lite.Interpreter(model_path="cifar10_cnn.tflite") interpreter.allocate_tensors() input_details = interpreter.get_input_details() output_details = interpreter.get_output_details() # set input tensor interpreter.set_tensor(input_details[0]['index'], img) # run interpreter.invoke() # get outpu tensor probs = interpreter.get_tensor(output_details[0]['index']) # print result result = np.argmax(probs[0]) score = probs[0][result] print("予測した画像インデックス:{} [{:.2f}]".format(result, score)) plt.imshow(temp_img) plt.title('pred:{}'.format(img_pred)) plt.show() """ 0 - airplane 1 - automobile 2 - bird 3 - cat 4 - deer 5 - dog 6 - frog 7 - horse 8 - ship 9 - truck """TensorflowとTensorflowLiteの比較
以下の比較は画像データによって左右されますので参考程度にしてください。
画像を予測するためにかかった時間をそれぞれ計測しました。keras用のモデル 経過時間:0.8839559555053711 経過時間:0.6288352012634277 経過時間:0.5877768993377686 経過時間:0.5789699554443359 経過時間:0.5908827781677246 経過時間:0.7207329273223877 経過時間:0.7104830741882324 経過時間:0.6035618782043457 経過時間:0.5244758129119873 経過時間:0.5348677635192871 平均経過時間:0.636454225TensorflowLite用のモデル 経過時間:0.27948904037475586 経過時間:0.05380606651306152 経過時間:0.022572994232177734 経過時間:0.06809115409851074 経過時間:0.07050800323486328 経過時間:0.06940007209777832 経過時間:0.12052798271179199 経過時間:0.17615199089050293 経過時間:0.12544798851013184 経過時間:0.027255773544311523 平均経過時間:0.101325107TensorflowLiteの方が早いですね。
しかしその分精度に差があります。keras用のモデルで予測できなかった画像はCatのみでした。
一方でTensorflowLiteのモデルでは、airplane、Bird、cat、Frogが予測することができませんでした。
TensorflowLite用に変換したモデルはかなり精度が下がっているようです。99.4%の精度を持つMNISTのモデルで実行した場合はkeras用もTensorflowLite用も同じくらい予測することができました。TensorflowLiteを使用する場合は、かなり高い精度を持つモデルを用意する必要がありそうです。
参考
初心者に優しくないTensorflow Lite の公式サンプル
KerasでCNNを構築しCIFAR-10の画像分類をしてみよう