Keras学習済みモデルをTensorFlow.jsモデルに変換して推論を実行

2018.10.11

tfjs_convertを試す

Tensorflow.js公開当初は、学習済みTensorFlow.jsモデルが殆ど用意されておらず、他のディープラーニングモデルからモデル生成が必要でした。

モデル変換には、tfjs_converterというスクリプトを使います。TensorFlow.jsをインストールすると、同梱されており、使用方法は公式GitHubにあります。

現在、TensorFlow.jsモデルに変換可能な形式は、TensorFlow及びKerasで出力される形式に限られるようです。

今回は、当初からTutorialに書かれていた、Kerasモデル変換手順を試しつつ、推論結果表示までの手順をまとめます。

Kerasとmnist

Kerasとは、Pythonで書かれたニューラルネットワークライブラリであり、Tensorflow上で実行できます。

mnistとは、28×28ピクセル、白黒画像の 手書き数字 のデータセット(画像およびラベル)の呼称です。各ピクセルは0(白)~255(黒)の値をとり、6万枚の学習用画像と1万枚のテスト画像が入っています。
様々な機械学習のチュートリアルでよく出現するサンプルデータになります。

Kerasにも、既存のmnist学習済みモデルがあるという事もあり、こちらを題材にします。

mnistモデルによる推論までの手順

今回は、既存のminist学習済みKerasモデルをTensorFlow.jsモデルに変換し、新しく入力した手書きの数字を推論させ、結果を出力させることを目標とします。

学習済みモデルを使用して推論を行うには、大元の入力データを、モデルに入力可能な入力データに変換する準備が必要です。 今回使用するモデルが期待する入力データは、以下です。

  • 28×28サイズのグレースケール画像
  • 画像1枚が推論対象
  • Tensor形式

以上より、入力データの準備の流れは下記の通りになります。

  • Canvasからの手書き文字を2D画像に変換
  • 画像をグレースケール化
  • 画像28×28にリサイズ
  • リサイズ画像をtf.Tensorオブジェクトに変換
  • 0~255で表現されているのを255で割ってあげて0~1に正規化する
  • 入力は1枚として、モデルで推論

KerasモデルをTensorflow.jsモデルへ変換

1. 環境構築

本手順には、pythonの環境が必要なのですが、記事のメインはpythonによるモデル構築ではないため、Google Colaboratoryを使用して、環境構築を短縮します。

Google Colaboratoryは、ノートブック形式を取ります。 ノートブックとは、名前の通りで、メモとコードと実行結果が同時に残しておけるアプリケーションです。Google Colaboratoryの本家サイトはこちらです。(Colaboratoryで記述されています。) Googleドライブ上に保存されますので、共有も容易です。

また、制約はありますが、Google Colaboratoryでは無料でGPUも使用できます。
どんな制約で何ができるのかは、Googleのよくある質問を読むと、概要が掴めると思います。
今回の手順に関係する項目を例に挙げると、GPUを使うには、python3で実行する必要があります。

2. Colaboratory新規作成

GoogleColaboratoryは、GoogleDriveに作成します。

新規作成すると、以下の表示になります。

黒丸に三角のマークは、実行ボタンになります。これが付いているセル内に、コードを書きます。実行ボタンを押下すると、セル内のコードのみが実行されます。
[+テキスト]で、テキストセルを追加。メモに使います。
[+コード]で、コーディングセルを追加します。
[↑/↓セル]で、セルの位置を前後させます。

3. ノートブックの環境確認

各種確認用コマンド

TensorFlowのバージョン確認は、以下のコマンドになります。


実行結果サンプル:


現在のノートブックにGPUがアサインされているかは、以下のコマンドになります。


実行結果サンプル:


CPU/GPUについてのメモリ割当など詳細は、以下のコマンドで確認できます。


実行結果サンプル:

ノートブックでGPUを有効化

[ランタイム]>[ランタイムのタイプを変更]

ランタイムにPython3を、ハードウェアアクセラレータにGPUを設定し、保存

GPUを有効にしておけば、ここでのTensorFlowは、処理の記述上で断りがなければ、GPUを優先するようです。

4. モデル変換(Keras->TensorFlow.js)

Colaboratoryのコードセルに、以下、記述していきます。
番号毎にセルは分けてみてください。

4-1. mnist_cnn.py取得、modelの保存処理を追加

Kerasの中でもmnist学習済みモデルはいくつかありますが、精度の高さが期待できる、CNNモデルを採用しました。ソースコードはこちらから参照できます。


4-2. トレーニング&学習済みmnistモデル生成


4-3. tfjs_converterを手に入れ、モデルをコンバート


4-4. 生成モデルをダウンロード


実行結果サンプル:

推論実行

1. 実行手順

TensorFlow.jsを扱いますので、実行手順は以下の通りです。

  1. XAMPPによるローカルApacheサーバを起動
  2. ブラウザからローカルサーバ経由でアクセス

2. ファイル構成

ファイル構成は以下の通りです。


以下、ディレクトリや各種ファイルの概要です。

index.html

推論対象の手書き数字入力画面及び、結果出力画面の表示

index.css

index.htmlの見た目を調整

conversion2gray.js

手書き画像をグレースケールに変換

drawcnvs.js

Canvasへの手書き入力検出処理

mnistfromdraw.js

入力画像生成、推論実処理、結果出力

model/

先述の「4.モデル変換」で生成したファイル一式を、zipから展開して本フォルダ直下に全て格納。Kerasのバージョンによって、生成数が異なるようです。

3. 結果出力イメージ

結果は以下の様に表示して示す事にします。
右側の表が、推論の出力値です。入力された手書き数字が、0~9までの各数字にどの程度近しいかを0~1の値で示しています。

4. 入力データの準備

推論に到達するまでに、入力データの下処理が必要です。
TensorFlow.js APIの他、画像処理やHTMLの話も含みますが、どの様に実現したか、説明しておきます。

4-1. Canvas手書き入力検出

手書き入力を検出するには、Canvas内で以下の描画イベント検出を行います。

マウス描画の検出

[drawcnvs.js]</>

タッチ描画の検出

[drawcnvs.js]</>

4-2. グレースケール化

Canvasに入力する段階で、描画色を白、背景色を黒にしておけば完全二値になるのですが、一応、何色で描画されても推論に掛けられる様に、ここでは、描画色/背景色を白黒以外の色に設定して、グレースケール化を試した内容をまとめます。

白黒以外の色にするといいますが、一応、余計な処理を省く為、背景色は暗く濃く、描画色は明るく薄い色を選びました。

[drawcnvs.js]</>

RGB画像を単純にグレースケール化するには、下記の計算式に当てはめるのが一般的なようです。

出力画素 = (0.299 * R + 0.587 * G + 0.114 * B)

Canvasに対する処理は、以下の様になります。

[drawcnvs.js]</>

出力結果は下記になります。

グレースケール化

画像

変換前

変換後

4-3. リサイズ

リサイズには、Canvasのメソッドを使います。

[mnistfromdraw.js]</>

4-4. tf.Tensorオブジェクトに変換

最後に、TensorFlow.jsのAPIを用いて、モデルに入力可能な入力データに変換します。

[mnistfromdraw.js]</>

各メソッドは、それぞれ以下の処理を行っています。

入力は1枚

[mnistfromdraw.js]</>

テンソル形式に変換([batchSize, width, height, colorChannels])

[mnistfromdraw.js]</>

出力をfloat32にキャスト

[mnistfromdraw.js]</>

0~1に正規化

[mnistfromdraw.js]</>

以上で、推論にかける入力データの用意ができました。

5. 推論

変換済みのモデルをロードして、生成した入力データで推論をかける処理が、以下です。

[mnistfromdraw.js]</>

ここで気を付けるのは、モデルのロード先の指定方法についてです。例えばモデルをJavascriptファイルと同じローカルディレクトリに格納していたとしても、URL指定によるローカルサーバ経由での呼び出しが必要です。

以上が、推論実行の一連の手順となります。

ソースコード

最後に、今回作成したソースコードを参考として載せておきます。

[index.html]</>
[index.css]</>

[drawcnvs.js]</>

[conversion2gray.js]</>

[mnistfromdraw.js]</>

まとめ

推論の結果が低くなる数字もあるようですが、これは学習済みモデルの精度も関連すると思います。
モデルの精度を上げるには、モデルを訓練するしかありません。
ここまでは、既存のモデルの利用に留まっていましたが、今後は、モデル構築~学習をさせてみる一連の手順や、転移学習について、使い方を理解する必要があると感じています。