エクサウィザーズ Engineer Blog

株式会社エクサウィザーズのエンジニアチームブログ

Tensorflow.jsを用いたブラウザで動く物体認識

こんにちは。エクサウィザーズAIエンジニアの須藤です。 この度exaBaseの「物体名判別」モデルの紹介ページに、その場で試せるデモ機能を追加しました。

f:id:kentaro-suto:20181029164025p:plain

前回の「写真に写っていないところを復元する」とともに、実装にあたってはTensorflow.jsというフレームワークを使っています。 この記事では、Tensorflow.js導入までの簡単な解説と注意点、および新しいデモの操作方法を紹介したいと思います。

Tensorflow.jsとは

TensorflowもしくはKerasで書かれた機械学習モデルを、JavaScriptで扱えるようにするフレームワークです。 学習済みモデルによる推論が主な応用と考えられますが、モデルの構築や再学習も可能です。 WebGL経由でGPUを利用するので、計算は十分に高速です。

公式サイト

www.tensorflow.org

特徴

Webブラウザ上でAIモデルが動くようになります。 以下の特徴を持ったアプリケーションが作れます。

  • ライブラリ等のインストールが不要
    • (最新の)Webブラウザさえあれば動作します。
  • GUIが利用可能
    • Webアプリの技術がそのまま使えます。
    • ローカルファイルの選択などもOSやブラウザが面倒を見てくれます。
  • スマートフォンでも動作
  • サーバの負荷が少ない
    • 計算はクライアント側で行われるため
  • 細かいカスタマイズはできない

開発環境

pipでインストールできます。

pip install tensorflowjs

モデルの書き出し

モデルデータの書き出しには、コマンドtensorflowjs_converterまたは、Pythonフレームワークtensorflowjsが使えます。 後者で、既存の推論スクリプトに一時的に以下の行を書き足す方法が、手軽でおすすめです。

import tensorflowjs as tfjs
# モデルオブジェクトmodelを、ディレクトリ'tfjs'に、8ビットの量子化を用いて書き出す。
tfjs.converters.save_keras_model(model, 'tfjs', quantization_dtype=np.uint8)

実行すると、書き出し先ディレクトリに次のようなファイル群が生成されます。ファイルの名前と数はモデルのサイズや構成によって変わります。 総ファイルサイズは、重み(.hdf5)ファイルにほぼ比例します。量子化しなければそのまま、16ビットで半分、8ビットで4分の1になります。

model.json
group1-shard1of3
group1-shard2of3
group1-shard3of3

モデルの読み込み

HTML側でフレームワークをインポートします。

<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@0.13.0"></script>

モデルの読み込みを開始するには、JavaScriptで次のようにします。結果はPromiseオブジェクトを通して非同期にハンドラ関数に渡されます。

tf.loadModel('./model.json').then(handleModel).catch(handleError);
function handleModel(model) {
    // 正常に読み込まれた時の処理
    // 必要なら入出力shapeを保存
    height = model.inputs[0].shape[1];
    width = model.inputs[0].shape[2];
    // modelの操作...
}
function handleError(error) {
    // エラー処理
}

実行

Pythonで書かれた前処理や後処理を、頑張ってJavaScriptに翻訳します。実行そのものはモデルのpredictメソッドを呼ぶだけです。 predictを呼び出してから結果データを受け取るまでの流れは、形式上非同期ですが、Mac版Safariの場合、結果を待つ間もJavaScriptに制御が戻りませんでした。

var data = new Float32Array(height*width*3);
// dataの前処理...
var inputs = tf.tensor(data).reshape([1,height,width,3]); // テンソルに変換
var outputs = model.predict(inputs);
outputs.data().then(handleData).catch(handleError);
function handleData(data) { // Float32Arrayを受け取る    
    // dataの後処理...
}

モデルを読み込めない場合

原稿執筆時のバージョン(0.13.0)では、モデルに以下のものが含まれていると、書き出せても読み込めませんでした。 動作に影響しないものなら、model.jsonを書き換えることで解決する場合もあります。 どうしても必要な演算の場合、行列演算や畳み込みで代用するなどの工夫が必要です。

  • Subtract
    • AddやMultiplyは大丈夫なのに何故かこれはダメです。
  • Merge
  • Lambda
  • カスタマイズされたinitializer、regularizer、constraints
  • 名前の重複したレイヤー

物体名判別デモ

Kerasに同梱されている学習済みXceptionモデルを用いたデモです。 同モデルの重みはMITライセンスの下で公開されています。

こちらのページでお試しいただけます。 https://base.exawizards.com/view/modelDetail?id=6

操作方法

f:id:kentaro-suto:20181023183149p:plain 画面左下のリンクをクリックしてください。モデルのダウンロードが始まります。
f:id:kentaro-suto:20181023183216p:plain ダウンロードが終わると、プルダウンとファイル選択ボタンが表示されます。
f:id:kentaro-suto:20181024134942p:plain サンプル写真をプルダウンから選択するか、
f:id:kentaro-suto:20181023183415p:plain ローカルのファイルを選択してください。
f:id:kentaro-suto:20181023183443p:plain 計算が始まります。
f:id:kentaro-suto:20181030165119p:plain 最も確率が高い1〜3カテゴリに関するコメントと、上位10カテゴリの確率が表示されます。

結果

いくつか興味深い結果をご紹介します。なお、この記事で用いた写真およびデモページのサンプル写真は、私が個人的に撮影したものです。

画像 コメント
f:id:kentaro-suto:20181029143853p:plain バターナット・スクウォッシュを調べたら、確かに似ていました。ヒョウタンは学習データにありませんでした。
f:id:kentaro-suto:20181029160544p:plain どうやら本当はキジバトのようです。このように、知らないものに対しては、学習した中で似ているものを返します。
f:id:kentaro-suto:20181029144117p:plain 食べ物というところまでは合っています。
f:id:kentaro-suto:20181029144847p:plain 猫判別能力は概ね高いのですが、これは見破れなかったようです。
f:id:kentaro-suto:20181029144431p:plain メインの被写体について何も分からない場合、小さくても隅っこでも、知っているものに反応する場合があります。
f:id:kentaro-suto:20181030165004p:plain 右下の黒くて四角い何かに強く反応しました。比べると左上の生き物については、いまいち確証が無かったようです。
f:id:kentaro-suto:20181029144914p:plain 見えない何かに反応することも。生き物に関しては、それがいそうな背景でも判断しているようです。
f:id:kentaro-suto:20181029144722p:plain かたくなに犬と言い張ります。どうも縞模様で猫を判別しているようです。
f:id:kentaro-suto:20181030165034p:plain やっぱり。しかしこれだけ抽象化されたデザインに反応するのは珍しいです。
f:id:kentaro-suto:20181030165342p:plain 例えばシマウマは知っています。
f:id:kentaro-suto:20181029161711p:plain しかしこれはシマウマとは判定されません。
f:id:kentaro-suto:20181029144814p:plain 納得しかけましたが、よく見たら貯金箱じゃありませんでした。

まとめ

Tensorflow.jsの使い方と、それを用いたデモを紹介しました。 前処理があまり必要ない場合は、想像より簡単にモデルを動かせるようになります。 exaBaseの他の既存モデルのデモもおいおい追加して行きたいと思っています。

尚、エクサウィザーズは優秀なエンジニア、社会課題を一緒に解決してくれる魔法使い”ウィザーズ”を募集しています。ご興味を持たれた方はぜひご応募ください。 採用情報|株式会社エクサウィザーズ

ExaWizards Engineer Blogでは、定期的にAIなどの技術情報を発信していきます。Twitter (https://twitter.com/BlogExawizards) で更新情報を配信していきますので、ぜひフォローをよろしくお願いします!