【AI】LobeからExportしたモデルの使い方

# ➊はじめに
前回は『[**`【AI】LobeでMNISTをやってみた`**](https://qiita.com/PoodleMaster/items/8829cfa9036b6c14ee27)』にて、AI側については一切プログラミングすることなく、推論エンジンをローカルPCにデプロイしました。また、[**Local API**](https://docs.lobe.ai/docs/export/export)を介してアプリと推論エンジンの通信を行いました。
![system](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405376/c4b2d953-7530-2e36-7e9d-46b2dbac0d23.png)

# ➋今回やること
Lobeから`TensorFlow(saved_model)形式`でエクスポートし、そのモデルを利用できるか確認してみたいと思います。今回はLobeが用意した[`➎Lobe-API`](https://qiita.com/PoodleMaster/items/af5630305df52bed0564#lobe-api%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%A6%E6%8E%A8%E8%AB%96%E5%AE%9F%E6%96%BD)を使用する方法と、[`➏tensorflowライブラリ`](https://qiita.com/PoodleMaster/items/af5630305df52bed0564#tensorflow%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E3%81%A7%E6%8E%A8%E8%AB%96%E5%AE%9F%E6%96%BD)を使用する方法の2種類を検証したいと思います。
![system](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405376/bc689b37-d400-9864-52d0-606607703393.png)


# ➌Lobeからエクスポート
### ■エクスポート形式
Lobeからのエクスポート形式は、以下4つに対応しています。
今回は「`TensorFlow 1.15 SavedModel`」を検証します。

|Export|説明|
|:-:|:-:|
|TensorFlow 1.15 SavedModel|TensorFlowのSavedModelは、TensorFlow 1.xを実行するPythonアプリケーションで使用される標準形式であり、TensorFlow Webサービスにデプロイして、APIとしてクラウド上で推論を実行できます。|
|AndroidまたはRaspberryPi|モデルをTensorFlowLiteとしてエクスポートして、モバイルおよびIoTアプリケーションで使用します。|
|Apple iOS|モデルをCoreMLとしてエクスポートして、iOS、iPad、およびMacアプリを開発します。|
|ローカルAPI|LobeはローカルAPIをホストして、RESTエンドポイントを介してモデルを呼び出します。このオプションを使用して、アプリの開発中に予測を実行するサービスをモックします。|

### ■エクスポート実施
■Lobeから対象PJを開いて、[`Export`]を押下します。
![Export001.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405376/2aa1bcd6-325a-8615-c773-27c8324b2a50.png)

■[`TensorFlow`]を押下します。
![Export002.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405376/acc6199e-cc0e-c72f-4c6a-2f21f2c19c03.png)

■書き出しフォルダを選択するとExportが始まります。
![Export003.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405376/22da26a4-ba9a-adb9-e5f4-68a88924ba5b.png)

### ■エクスポート結果
`SavedModel形式`については、[TensorFlow：「SavedModel形式の使用」](https://www.tensorflow.org/guide/saved_model?hl=ja)等をご参考ください。

```
export model
    │
    ├─example
    │     │
    │     ├─README.md
    │     ├─requirements.txt
    │     └─tf_example.py
    │
    ├─variables
    │     │
    │     ├─variables.data-00000-of-00001
    │     └─variables.index
    │
    ├─saved_model.pb
    └─signature.json
```

# ➍Lobe-APIとは
Lobeは、Exportしたモデルを**簡単に読み込むためのライブラリ**`Lobe-API`を用意しています。この`Lobe-API`を使うと以下の通り**イメージファイル、URL、画像データから直接推論が可能**となります。ただし、`Lobe-API`をインストールすると**tensorflowのバージョンが1.15にデグレード**されてしまうので注意が必要です。
> 詳細はここ → Lobe-API：https://github.com/lobe/lobe-python

### `OPTION 1`：イメージファイルから推論する場合
``` .py
from lobe import ImageModel

model = ImageModel.load('path/to/ExportFolder')
result = model.predict_from_file('path/to/file.png')
```

### `OPTION 2`：URLから推論する場合
``` .py
from lobe import ImageModel

model = ImageModel.load('path/to/ExportFolder')
result = model.predict_from_url('http://path/to/file.png')
```

### `OPTION 3`：Pillow imageから推論する場合
``` .py
from lobe import ImageModel
from PIL import Image

model = ImageModel.load('path/to/ExportFolder')
img = Image.open('path/to/file.png')
result = model.predict(img)
```

# ➎【使い方1】Lobe-APIを使用
では、早速`Lobe-API`を使って推論を実施させたいと思います。
### ■python仮想環境構築
まず、anacondaのcondaコマンドを使用して、python仮想環境[`lober1`]を作ります。
`Lobe-API`はpython=3.7以上でないと動かないため以下のように設定します。
> 2020/11現在、Google ColabのPythonバージョンは3.6.9なので、Google ColabではLobe-APIは使えませんでした。

``` :仮想環境［lober1］構築
C:\Lobe test>conda create -n lober1 python=3.7
C:\Lobe test>conda activate lober1
```

### ■Lobe-APIのインストール
依存関係にあるライブラリも合わせて自動でインストールされます。

``` :Lobe-APIインストール
(lober1) C:\Lobe test>pip install git+https://github.com/lobe/lobe-python
```

### ■Lobe-APIが返却する推論結果数を変更
`Lobe-API`のデフォルトでは、推論結果を「`認識率ベスト5までのクラスをソート`」して返却してきます。
推論結果をどの様に使うかによりますが、**今回は全クラス返却するように変更**します。
仮想環境[`lober1`]下にインストールされたライブラリを修正します。

> C:\Users\\[username]\anaconda3\envs\lober1\Lib\site-packages\lobe\_results.py
>「_results.py」のLine20を以下の様に修正します。

```.py:_results.py
 20:        top_predictions = confidences.argsort()[-5:][::-1]　← ベスト5のみに絞っている
                            ↓↓↓↓
 20:        top_predictions = confidences.argsort()[:][::-1]　　← 全クラスに変更
```

### ■サンプルプログラム

```.py:src01.py
############################################################
# Lobeで作ったモデルを使う方法 1
############################################################
import tensorflow as tf
from lobe import ImageModel


print("tensorflow : ", tf.__version__)


############################################################
# Export Model読込
############################################################
model = ImageModel.load('export model')


#-----------------------------------------------------
# OPTION 1: イメージファイルから推論する場合
#-----------------------------------------------------
print('■OPTION 1: Predict from an image file')
result = model.predict_from_file('sample.png')
pred = result.prediction
sorted_labels = sorted(result.labels)
conf = sorted_labels[int(result.prediction)][1]
print('predict   ：', pred)
print('confidence： {:1.010f}'.format(conf))

for label, conf in (sorted(result.labels)):
    print(label, '{:1.030f}'.format(conf))
print()


#-----------------------------------------------------
# OPTION 2: URLから推論する場合
#-----------------------------------------------------
print('■OPTION 2: Predict from an image url')
result = model.predict_from_url('https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405376/4f9c554d-f3f5-fc8d-2e08-30e8eb6079a4.png')

pred = result.prediction
sorted_labels = sorted(result.labels)
conf = sorted_labels[int(result.prediction)][1]
print('predict   ：', pred)
print('confidence： {:1.010f}'.format(conf))

for label, conf in (sorted(result.labels)):
    print(label, '{:1.030f}'.format(conf))
print()


#-----------------------------------------------------
# OPTION 3: Pillow imageから推論する場合
#-----------------------------------------------------
print('■OPTION 3: Predict from Pillow image')
from PIL import Image
img = Image.open('sample.png')
result = model.predict(img)

pred = result.prediction
sorted_labels = sorted(result.labels)
conf = sorted_labels[int(result.prediction)][1]
print('predict   ：', pred)
print('confidence： {:1.010f}'.format(conf))

for label, conf in (sorted(result.labels)):
    print(label, '{:1.030f}'.format(conf))
print()
```

### ■サンプルデータ
以下のサンプルデータを「sample.png」として「src01.py」と同じフォルダに保存してください。
> サンプルデータ：sample.png
> サンプル画像URL：https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405376/4f9c554d-f3f5-fc8d-2e08-30e8eb6079a4.png
> <img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405376/4f9c554d-f3f5-fc8d-2e08-30e8eb6079a4.png'>

### ■プログラミング実行結果
```:src01.py実行結果
(lober1) C:\Lobe test>python src01.py
tensorflow :  1.15.4
■OPTION 1: Predict from an image file
predict   ： 9
confidence： 0.9999991655
0 0.000000000000000000004691450972
1 0.000000000000000000000000000000
2 0.000000000000000000204086976737
3 0.000000000000000000000101685206
4 0.000000000000000012389047993676
5 0.000000000000000000010694401651
6 0.000000000000000000000000045193
7 0.000000881124378793174400925636
8 0.000000000000000404111716429163
9 0.999999165534973144531250000000

■OPTION 2: Predict from an image url
predict   ： 9
confidence： 0.9999991655
0 0.000000000000000000004691450972
1 0.000000000000000000000000000000
2 0.000000000000000000204086976737
3 0.000000000000000000000101685206
4 0.000000000000000012389047993676
5 0.000000000000000000010694401651
6 0.000000000000000000000000045193
7 0.000000881124378793174400925636
8 0.000000000000000404111716429163
9 0.999999165534973144531250000000

■OPTION 3: Predict from Pillow image
predict   ： 9
confidence： 0.9999991655
0 0.000000000000000000004691450972
1 0.000000000000000000000000000000
2 0.000000000000000000204086976737
3 0.000000000000000000000101685206
4 0.000000000000000012389047993676
5 0.000000000000000000010694401651
6 0.000000000000000000000000045193
7 0.000000881124378793174400925636
8 0.000000000000000404111716429163
9 0.999999165534973144531250000000
```


# ➏【使い方2】TensorFlowライブラリを使用
`Lobe-API`を使用せずに、`tensorflowライブラリ`を使って推論する方法です。
### ■python仮想環境構築
anacondaを利用してpython仮想環境[`lober2`]を作ります。

``` :仮想環境［lober2］構築
(lober1) C:\Lobe test>conda deactivate
C:\Lobe test>conda create -n lober2 python=3.7
C:\Lobe test>conda activate lober2
(lober2) C:\Lobe test>conda install tensorflow pillow
```

### ■サンプルプログラム

``` .py:src02.py
############################################################
# Lobeで作ったモデルを使う方法 2
############################################################
import json
import numpy as np
import tensorflow as tf
from PIL import Image
from tensorflow.keras.preprocessing.image import img_to_array


print("tensorflow : ", tf.__version__)
export_holder = 'export model/'


############################################################
# Export Model読込
############################################################
# https://www.tensorflow.org/guide/saved_model
# signature読込
sig_holder = export_holder + 'signature.json'
with open(sig_holder, 'r') as f:
    signature = json.load(f)

inputs = signature.get('inputs')
outputs = signature.get('outputs')

# モデルの学習画像サイズを取得
input_width, input_height = inputs['Image']['shape'][1:3]

# model読込
model = tf.saved_model.load(export_holder)
infer = model.signatures['serving_default']


############################################################
# 画像データ読込
############################################################
imgPIL = Image.open('sample.png')
imgPIL = imgPIL.convert('RGB')
imgPIL = imgPIL.resize((input_width, input_height))

x = img_to_array(imgPIL) / 255
x = x[None, ...]

############################################################
# 推論
############################################################
predict = infer(tf.constant(x))

# 推論結果
predict = infer(tf.constant(x))['Prediction'][0]
print('predict   ：', predict.numpy().decode())

# 確率
confidence = infer(tf.constant(x))['Confidences'][0]
confidence = confidence.numpy()
print('confidence： {:1.010f}'.format(confidence[int(predict)]))
print()

for i, conf in enumerate(confidence):
    print(i, '{:1.030f}'.format(conf))
print()
```
### ■サンプルデータ
以下のサンプルデータを「sample.png」として「src02.py」と同じフォルダに保存してください。
> サンプルデータ：sample.png
> <img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405376/4f9c554d-f3f5-fc8d-2e08-30e8eb6079a4.png'>

### ■プログラミング実行結果
```:src02.py実行結果
(lober1) C:\Lobe test>python src02.py
tensorflow :  2.1.0
predict   ： 9
confidence： 0.9999991655

0 0.000000000000000000004691540637
1 0.000000000000000000000000000000
2 0.000000000000000000204095532887
3 0.000000000000000000000101689472
4 0.000000000000000012389331716626
5 0.000000000000000000010694728000
6 0.000000000000000000000000045193
7 0.000000881154619492008350789547
8 0.000000000000000404117883887810
9 0.999999165534973144531250000000
```

# ➐手書きアプリケーション
せっかくなので、いつもの手書きwebツールの`mnister`をTensorflowモデルを読み込めるように改造してみました。こちらは【使い方2】のTensorFlowライブラリを使用する方法でモデルを利用しています。ダウンロードは以下から取得可能となっていますので、ぜひご参考ください。

※「mnister_for_tensorflow」アプリケーションを動作させる場合は、LobeのTensorFlow Exportモデルを**各自用意する必要**があります。モデルの作り方は『[`【AI】LobeでMNISTをやってみた`](https://qiita.com/PoodleMaster/items/8829cfa9036b6c14ee27)』と『[本項➌](https://qiita.com/PoodleMaster/items/af5630305df52bed0564#lobe%E3%81%8B%E3%82%89%E3%82%A8%E3%82%AF%E3%82%B9%E3%83%9D%E3%83%BC%E3%83%88)』を参考にすれば簡単に実行できます。

### ■システム図
![system](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405376/aebc357e-d302-efbd-23ba-29f6591e5960.png)

### ■ダウンロード
mnister_for_Tensorflowを格納するディレクトリに移動後、以下のgit cloneコマンドを打ち込んでmnister_for_TensorflowツールをGETしてください。実行方法などは[README.md](https://github.com/PoodleMaster/mnister_for_tensorflow/blob/main/README.md)をご参照ください。

```.bat:command
git clone https://github.com/PoodleMaster/mnister_for_tensorflow
```
> <img width=64 src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405376/3a342531-d030-6a66-678e-45f328de072f.png'><img width=120 src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405376/7e2c1f12-f920-922c-81f2-312da1406ad0.png'>
> Github : https://github.com/PoodleMaster/mnister_for_tensorflow

# ➑以上
LobeからエクスポートしたTensorFlowモデルは、APIなども用意されており、問題なく簡単に利用することができました。

microsoftの『[`Lobe`](https://lobe.ai/)』やGoogleの『[`Teachable Machine`](https://teachablemachine.withgoogle.com/)』など、AIプログラミングすることなく、誰でも簡単にモデルを構築できたり、推論結果からモデルの更新ができるようになってきました。これからは、益々AIでどんなサービスができるかが重要視される時代になっていくんでしょうね…

お疲れ様でした。