TensorFlow.js: Python SavedModel を TensorFlow.js 形式に変換する

1. はじめに

TensorFlow.js を使い始めたばかりの方、事前作成済みモデルを試したことがある方、あるいは独自のモデルを作成したことがある方もいるでしょう。Python で最先端の研究成果が発表されたのを見て、その成果をウェブブラウザで実行して、思いついたクールなアイデアをスケーラブルな方法で何百万人もの人々に届けられるかどうかを試してみたいと思っているかもしれません。皆様も心当たりはありませんか。この Codelab がおすすめです。

TensorFlow.js チームは、SavedModel 形式のモデルをコマンドライン コンバータ経由で TensorFlow.js に変換する便利なツールを作成しました。これにより、ウェブのリーチとスケールでこのようなモデルを使用できます。

学習内容

このコードラボでは、TensorFlow.js コマンドライン コンバータを使用して、Python で生成された SavedModel をウェブブラウザのクライアントサイドでの実行に必要な model.json 形式に移植する方法を学びます。

詳細:

  • 簡単な Python ML モデルを作成し、TensorFlow.js コンバータに必要な形式で保存する方法。
  • Python からエクスポートした SavedModel に TensorFlow.js コンバータをインストールして使用する方法。
  • 変換後のファイルを取得して、JS ウェブ アプリケーションで使用します。
  • 問題が発生した場合(すべてのモデルが変換されるわけではありません)の対処方法と利用可能なオプションについて説明します。

新たにリリースされた研究成果を基に、世界中の何百万人もの JS デベロッパーが利用できるモデルを作成できると想像してみてください。また、ご自身で作成したもので使用することもできます。ウェブブラウザで実行できるため、複雑な依存関係や環境設定は必要なく、世界中の誰もが体験できます。ハッキングの準備はできましたか?始める

変換したものを共有しましょう

今日の学習内容を活かして、お気に入りのモデルを Python から変換してみてください。モデルの動作をデモするウェブサイトを完成させることができたら、ソーシャル メディアで #MadeWithTFJS ハッシュタグを使用して、作成したプロジェクトを TensorFlow ブログや今後の Show & Tell イベントで紹介してもらうチャンスを掴みましょう。この素晴らしい例のように、より多くの優れた研究がウェブに移植され、より多くの人々が革新的かつ創造的な方法でこのようなモデルを使用できるようになることを願っています。

2. TensorFlow.js とは何ですか?

1aee0ede85885520.png

TensorFlow.js は、JavaScript が実行できる場所であればどこでも実行できるオープンソースの ML ライブラリです。これは Python で記述された元の TensorFlow ライブラリに基づいており、このデベロッパー エクスペリエンスと API のセットを JavaScript エコシステムで再作成することを目的としています。

どこで使用できますか?

JavaScript の移植性を考慮すると、1 つの言語で記述し、次のすべてのプラットフォームで簡単に ML を実行できます。

  • バニラ JavaScript を使用したウェブブラウザのクライアントサイド
  • Node.js を使用したサーバーサイドや Raspberry Pi などの IoT デバイス
  • Electron を使用するデスクトップ アプリ
  • React Native を使用するネイティブ モバイルアプリ

TensorFlow.js は、これらの各環境内で複数のバックエンドもサポートしています(CPU や WebGL など、実行可能な実際のハードウェア ベースの環境)。このコンテキストの「バックエンド」はサーバーサイド環境を意味するものではありません。たとえば、実行のバックエンドは WebGL のクライアントサイドになる可能性があります。互換性を確保し、高速な実行を維持するためです。現在、TensorFlow.js は以下をサポートしています。

  • デバイスのグラフィック カード(GPU)での WebGL 実行 - GPU アクセラレーションを使用して、より大きなモデル(サイズが 3 MB を超えるもの)を実行する最も高速な方法です。
  • CPU での Web Assembly(WASM)実行 - たとえば、古い世代の携帯電話など、デバイス全体の CPU パフォーマンスを向上させます。これは、グラフィック プロセッサにコンテンツをアップロードするオーバーヘッドにより、WebGL よりも WASM を使用して CPU で高速に実行できる小規模なモデル(サイズが 3 MB 未満)に適しています。
  • CPU 実行 - 他の環境が使用できない場合のフォールバック。3 つの中で最も遅いですが、いつでも利用できます。

注: 実行するデバイスがわかっている場合は、これらのバックエンドのいずれかを強制的に選択できます。指定しない場合は、TensorFlow.js が自動的に選択します。

クライアントサイドのスーパー パワー

クライアント マシン上のウェブブラウザで TensorFlow.js を実行すると、考慮すべきメリットがいくつかあります。

プライバシー

データを第三者のウェブサーバーに送信することなく、クライアント マシンでデータのトレーニングと分類の両方を行うことができます。たとえば、GDPR などの現地の法律を遵守するために、またはユーザーが自分のマシンに保持し、第三者に送信したくないデータを処理するために、この機能が必要になることがあります。

速度

リモート サーバーにデータを送信する必要がないため、推論(データの分類)を高速化できます。さらに、ユーザーがアクセスを許可すれば、カメラ、マイク、GPS、加速度計などのデバイスのセンサーに直接アクセスできます。

リーチとスケーリング

世界中の誰もが、あなたが送ったリンクをクリックしてブラウザでウェブページを開き、あなたが作成したものを利用できます。ML システムを使用するために、CUDA ドライバなどを含む複雑なサーバーサイドの Linux 設定は必要ありません。

費用

サーバーがないため、HTML、CSS、JS、モデルファイルをホストする CDN の料金のみを支払う必要があります。CDN の費用は、サーバー(グラフィック カードが接続されている可能性あり)を 24 時間 365 日稼働させるよりもはるかに安価です。

サーバーサイドの機能

TensorFlow.js の Node.js 実装を活用すると、次の機能が有効になります。

CUDA のフルサポート

サーバー側では、グラフィック カードのアクセラレーションのために、TensorFlow がグラフィック カードで動作するように NVIDIA CUDA ドライバをインストールする必要があります(WebGL を使用するブラウザとは異なり、インストールは不要です)。ただし、CUDA を完全にサポートすることで、グラフィック カードの低レベルの機能を最大限に活用し、トレーニングと推論の時間を短縮できます。どちらも同じ C++ バックエンドを共有しているため、パフォーマンスは Python TensorFlow 実装と同等です。

モデルのサイズ

研究の最先端モデルでは、非常に大規模なモデル(ギガバイト単位のサイズ)を扱うことがあります。これらのモデルは、ブラウザタブあたりのメモリ使用量の制限により、現時点ではウェブブラウザで実行できません。これらの大規模なモデルを実行するには、モデルを効率的に実行するために必要なハードウェア仕様を備えた独自のサーバーで Node.js を使用できます。

IoT

Node.js は Raspberry Pi などの一般的なシングルボード コンピュータでサポートされています。つまり、このようなデバイスで TensorFlow.js モデルを実行することもできます。

速度

Node.js は JavaScript で記述されているため、ジャストインタイム コンパイルのメリットがあります。つまり、Node.js を使用すると、実行時に最適化されるため、パフォーマンスが向上することがよくあります。特に、実行する可能性のある前処理については、パフォーマンスが向上します。この好例は、こちらのケーススタディで確認できます。このケーススタディでは、Hugging Face が Node.js を使用して自然言語処理モデルのパフォーマンスを 2 倍に向上させた方法が紹介されています。

TensorFlow.js の基本、実行場所、メリットについて理解できたので、実際に使ってみましょう。

3. システムのセットアップ

このチュートリアルでは、Ubuntu を使用します。これは、多くのユーザーが使用している一般的な Linux ディストリビューションであり、クラウドベースの仮想マシンで操作する場合は、Google Cloud Compute Engine でベースイメージとして使用できます。

このドキュメントの作成時点では、新しいバニラ コンピューティング エンジン インスタンスを作成するときに Ubuntu 18.04.4 LTS のイメージを選択できます。このイメージを使用します。もちろん、ご自身のマシンを使用することも、別のオペレーティング システムを使用することもできますが、インストール手順と依存関係はシステムによって異なる場合があります。

TensorFlow のインストール(Python 版)

おそらく、既存の Python ベースのモデルを変換しようとしているでしょう。Python から「SavedModel」ファイルをエクスポートするには、その「SavedModel」がまだダウンロードできない場合は、インスタンスに Python バージョンの TensorFlow を設定する必要があります。

上記で作成したクラウド マシンに SSH 接続し、ターミナル ウィンドウで次のコマンドを入力します。

ターミナル ウィンドウ:

sudo apt update
sudo apt-get install python3

これにより、マシンに Python 3 がインストールされます。TensorFlow を使用するには、Python 3.4 以降がインストールされている必要があります。

正しいバージョンがインストールされていることを確認するには、次のように入力します。

ターミナル ウィンドウ:

python3 --version

Python 3.6.9 などのバージョン番号を示す出力が表示されます。この値が正しく出力され、3.4 より大きい場合は、続行できます。

次に、Python のパッケージ マネージャーである Python 3 用の PIP をインストールして更新します。タイプ:

ターミナル ウィンドウ:

sudo apt install python3-pip
pip3 install --upgrade pip

次のコマンドで pip3 のインストールを確認できます。

ターミナル ウィンドウ:

pip3 --version

このコマンドを実行すると、執筆時点では pip 20.2.3 がターミナルに出力されます。

TensorFlow をインストールする前に、Python パッケージ「setuptools」がバージョン 41.0.0 以降である必要があります。次のコマンドを実行して、最新バージョンに更新されていることを確認します。

ターミナル ウィンドウ:

pip3 install -U setuptools

最後に、Python 用 TensorFlow をインストールします。

ターミナル ウィンドウ:

pip3 install tensorflow

完了するまでにしばらく時間がかかることがあります。実行が完了するまでお待ちください。

TensorFlow が正しくインストールされていることを確認しましょう。現在のディレクトリに test.py という名前の Python ファイルを作成します。

ターミナル ウィンドウ:

nano test.py

nano が開いたら、TensorFlow のインストール バージョンを出力する Python コードを記述します。

test.py:

import tensorflow as tf
print(tf.__version__)

CTRL + O を押して変更をディスクに書き込み、CTRL + X を押して nano エディタを終了します。

この Python ファイルを実行して、画面に TensorFlow のバージョンを表示します。

ターミナル ウィンドウ:

python3 test.py

この時点では、インストールされている TensorFlow Python のバージョンに対して 2.3.1 がコンソールに出力されます。

4. Python モデルの作成

このコードラボの次のステップでは、簡単な Python モデルを作成して、トレーニング済みのモデルを「SavedModel」形式で保存し、TensorFlow.js コマンドライン コンバータで使用する方法について説明します。この原則は、変換しようとしている Python モデルにも同様に適用されますが、ここでは、誰もが理解できるようにコードを簡素化します。

最初のセクションで作成した test.py ファイルを編集し、コードを次のように更新します。

test.py:

import tensorflow as tf
print(tf.__version__)

# Import NumPy - package for working with arrays in Python.
import numpy as np

# Import useful keras functions - this is similar to the
# TensorFlow.js Layers API functionality.
from tensorflow.keras import Sequential
from tensorflow.keras.layers import Dense

# Create a new dense layer with 1 unit, and input shape of [1].
layer0 = Dense(units=1, input_shape=[1])
model = Sequential([layer0])

# Compile the model using stochastic gradient descent as optimiser
# and the mean squared error loss function.
model.compile(optimizer='sgd', loss='mean_absolute_error')

# Provide some training data! Here we are using some fictional data 
# for house square footage and house price (which is simply 1000x the 
# square footage) which our model must learn for itself.
xs = np.array([800.0, 850.0, 900.0, 950.0, 980.0, 1000.0, 1050.0, 1075.0, 1100.0, 1150.0, 1200.0, 1250.0, 1300.0, 1400.0, 1500.0, 1600.0, 1700.0, 1800.0, 1900.0, 2000.0], dtype=float)

ys = np.array([800000.0, 850000.0, 900000.0, 950000.0, 980000.0, 1000000.0, 1050000.0, 1075000.0, 1100000.0, 1150000.0, 1200000.0,  1250000.0, 1300000.0, 1400000.0, 1500000.0, 1600000.0, 1700000.0, 1800000.0, 1900000.0, 2000000.0], dtype=float)

# Train the model for 500 epochs.
model.fit(xs, ys, epochs=500, verbose=0)

# Test the trained model on a test input value
print(model.predict([1200.0]))

# Save the model we just trained to the "SavedModel" format to the
# same directory our test.py file is located.
tf.saved_model.save(model, './')

このコードは、非常に単純な線形回帰をトレーニングして、提供された x(入力)と y(出力)の関係を推定する方法を学習します。次に、トレーニング済みのモデルをディスクに保存します。各行の処理の詳細については、インライン コメントをご覧ください。

このプログラムを実行した後にディレクトリを確認すると(python3 test.py を呼び出す)、現在のディレクトリに新しいファイルとフォルダが作成されていることがわかります。

  • test.py
  • saved_model.pb
  • アセット
  • variables

これで、TensorFlow.js コンバータがこのモデルをブラウザで実行できるように変換するために必要なファイルが生成されました。

5. SavedModel を TensorFlow.js 形式に変換する

TensorFlow.js コンバータをインストールする

コンバータをインストールするには、次のコマンドを実行します。

ターミナル ウィンドウ:

pip3 install tensorflowjs

簡単でした。

上記のウィザード バージョンではなく、コマンドライン コンバータ(tensorflowjs_converter)を使用していると仮定すると、次のコマンドを呼び出して、作成した保存済みモデルを変換し、パラメータをコンバータに明示的に渡すことができます。

ターミナル ウィンドウ:

tensorflowjs_converter \
    --input_format=keras_saved_model \
    ./ \
    ./predict_houses_tfjs

ここで何が起きているのかまず、インストールした tensorflowjs_converter バイナリを呼び出し、Keras 保存モデルを変換しようとしていることを指定します。

上記のコード例では、keras をインポートし、その上位レイヤ API を使用してモデルを作成しています。Python コードで Keras を使用していない場合は、別の入力形式を使用することをおすすめします。

  • keras - keras 形式(HDF5 ファイル形式)を読み込む
  • tf_saved_model - keras ではなく tensorflow core API を使用するモデルを読み込みます。
  • tf_frozen_model - 固定された重みを含むモデルを読み込みます。
  • tf_hub - tensorflow hub から生成されたモデルを読み込みます。

その他のフォーマットについて詳しくは、こちらをご覧ください

次の 2 つのパラメータは、保存されたモデルが配置されるフォルダを指定します。上記のデモでは、現在のディレクトリを指定し、最後に変換の出力先となるディレクトリを指定します。上記の例では、現在のディレクトリにある「predict_houses_tfjs」というフォルダを指定しています。

上記のコマンドを実行すると、現在のディレクトリに : を含む predict_houses_tfjs という名前の新しいフォルダが作成されます。

  • model.json
  • Group1-shard1of1.bin

これらは、ウェブブラウザでモデルを実行するために必要なファイルです。これらのファイルは次のセクションで使用するため、保存しておきます。

6. ブラウザで変換されたモデルを使用する

変換されたファイルをホストする

まず、生成された model.json ファイルと *.bin ファイルをウェブサーバーに配置して、ウェブページからアクセスできるようにする必要があります。このデモでは、Glitch.com を使用します。これにより、簡単に手順を確認できます。ただし、ウェブ エンジニアリングの経験がある場合は、現在の Ubuntu サーバー インスタンスでシンプルな HTTP サーバーを起動して、この処理を行うこともできます。お好きな声を選んでくださいね。

Glitch にファイルをアップロードする

  1. Glitch.com にログインします。
  2. このリンクを使用して、ボイラープレートの TensorFlow.js プロジェクトのクローンを作成します。これには、TensorFlow.js ライブラリをインポートしてすぐに使用できるスケルトン HTML、CSS、JS ファイルが含まれています。
  3. 左側のパネルで [assets] フォルダをクリックします。
  4. [アセットをアップロード] をクリックし、このフォルダにアップロードする group1-shard1of1.bin を選択します。アップロードすると、次のようになります。25a2251c7f165184.png
  5. アップロードした group1-shard1of1.bin ファイルをクリックすると、その場所の URL をコピーできます。次のようにパスをコピーします。92ded8d46442c404.png
  6. 次に、ローカルマシンのお好みのテキスト エディタを使用して model.json を編集し、その中に記載されている group1-shard1of1.bin ファイルを検索します(CTRL+F を使用)。

このファイル名を、ステップ 5 でコピーした URL に置き換えます。ただし、コピーしたパスから glitch が生成した先頭の https://cdn.glitch.com/ は削除します。

編集後は次のようになります(先頭のサーバーパスが削除され、アップロードされたファイル名のみが残っていることに注意してください)。d5a338f2dc1f31d4.png 7. 編集した model.json ファイルを保存して glitch にアップロードします。アセットをクリックし、[アセットをアップロード] ボタンをクリックします(重要)。物理ボタンを使用せずにドラッグ&ドロップすると、CDN ではなく編集可能なファイルとしてアップロードされます。このファイルは同じフォルダに保存されず、TensorFlow.js が特定のモデルのバイナリ ファイルをダウンロードしようとするときに相対パスが想定されます。正しく実行すると、assets フォルダに 51a6dbd5d3097ffc.png のように 2 つのファイルが表示されます。

これで、これで、保存したファイルをブラウザの実際のコードで使用する準備が整いました。

モデルを読み込む

変換されたファイルをホストしたので、これらのファイルを読み込んで予測を行う簡単なウェブページを作成できます。Glitch プロジェクト フォルダで script.js を開き、Glitch にアップロードした model.json ファイルの生成された Glitch.com リンクを指すように const MODEL_URL を変更したら、このファイルの内容を次の内容に置き換えます。

script.js:

// Grab a reference to our status text element on the web page.
// Initially we print out the loaded version of TFJS.
const status = document.getElementById('status');
status.innerText = 'Loaded TensorFlow.js - version: ' + tf.version.tfjs;

// Specify location of our Model.json file we uploaded to the Glitch.com CDN.
const MODEL_URL = YOUR MODEL.JSON URL HERE! CHANGE THIS!';
// Specify a test value we wish to use in our prediction.
// Here we use 950, so we expect the result to be close to 950,000.
const TEST_VALUE = 950.0

// Create an asynchronous function.
async function run() {
    // Load the model from the CDN.
    const model = await tf.loadLayersModel(MODEL_URL);

    // Print out the architecture of the loaded model.
    // This is useful to see that it matches what we built in Python.
    console.log(model.summary());

    // Create a 1 dimensional tensor with our test value.
    const input = tf.tensor1d([TEST_VALUE]);

    // Actually make the prediction.
    const result = model.predict(input);

    // Grab the result of prediction using dataSync method
    // which ensures we do this synchronously.
    status.innerText = 'Input of ' + TEST_VALUE + 
        'sqft predicted as $' + result.dataSync()[0];
}

// Call our function to start the prediction!
run();

MODEL_URL 定数を model.json パスを指すように変更してから上記のコードを 1 回実行すると、次のような出力が得られます。

c5e8457213058ec3.png

ウェブブラウザのコンソールを検査すると(ブラウザで F12 キーを押してデベロッパー ツールを表示)、読み込まれたモデルのモデルの説明も表示されます。

35e79d70dbd66f27.png

これをこの Codelab の冒頭の Python コードと比較すると、1 つの密入力と 1 つの密レイヤ(1 つのノード)で作成したネットワークと同じであることがわかります。

おめでとうございます!変換された Python トレーニング済みモデルをウェブブラウザで実行しました。

7. 変換されないモデル

コンパイルされてあまり一般的でないオペレーションを使用する、より複雑なモデルは、変換でサポートされない場合があります。TensorFlow.js のブラウザベースのバージョンは TensorFlow の完全な書き換えであるため、現時点では TensorFlow C++ API が持つすべての低レベル オペレーション(数千個)をサポートしていません。ただし、時間の経過とともに、コア オペレーションがより安定するにつれて、より多くのオペレーションが追加されています。

このドキュメントの作成時点では、SavedModel としてエクスポートされたときにサポートされていないオペレーションを生成する TensorFlow Python の関数は linalg.diag です。Python でこれを使用する savedmodel を変換しようとすると(Python は生成されるオペレーションをサポートしています)、次のようなエラーが表示されます。

5df94fc652393e00.png

ここでは、linalg.diag 呼び出しがコンパイルされて MatrixDiagV3 という名前の op が生成されたことが赤でハイライト表示されています。この op は、この Codelab の執筆時点ではウェブブラウザの TensorFlow.js でサポートされていません。

対応策

方法は次の 2 つです。

  1. TensorFlow.js でこの欠落している演算を実装します。TensorFlow.js はオープンソース プロジェクトであり、新しい演算などの貢献を歓迎します。TensorFlow.js の新しい演算の作成に関するガイドをご覧ください。この処理が完了したら、コマンドライン コンバータで Skip_op_check フラグを使用してこのエラーを無視し、変換を続行できます(この op は、作成した TensorFlow.js ビルドの新しいビルドで使用可能であると想定されます。このビルドでは、欠落している op がサポートされています)。
  2. エクスポートした savedmodel ファイルでサポートされていないオペレーションを生成した Python コードの部分を特定します。コードのセットが小さい場合は簡単に見つけられるかもしれませんが、より複雑なモデルでは、savedmodel ファイル形式で特定の op を生成した高レベルの Python 関数呼び出しを特定する方法が現在ないため、かなりの調査が必要になる可能性があります。ただし、特定した後は、サポートされている別の方法を使用するように変更できます。

8. 完了

おめでとうございます。これで、ウェブブラウザで TensorFlow.js を介して Python モデルを使用するための最初のステップを完了しました。

内容のまとめ

この Codelab では、次の方法について学習しました。

  1. Python ベースの TensorFlow をインストールするように Linux 環境を設定する
  2. Python の SavedModel をエクスポートする
  3. TensorFlow.js コマンドライン コンバータをインストールする
  4. TensorFlow.js コマンドライン コンバータを使用して必要なクライアントサイド ファイルを作成する
  5. 生成されたファイルを実際のウェブ アプリケーションで使用する
  6. 変換されないモデルと、今後変換できるようにするために実装する必要があるものを特定します。

次のステップ

#MadeWithTFJS ハッシュタグを使用して作成したものをタグ付けすると、ソーシャル メディアで取り上げられたり、今後の TensorFlow イベントで紹介されたりする可能性があります。ブラウザでクライアントサイドで変換して使用しているものがあれば、ぜひお聞かせください。

理解を深めるための TensorFlow.js のその他の Codelab

参考になるウェブサイト