TensorFlow.js : ガイド : Keras ユーザのための TensorFlow.js 層 API (翻訳/解説)
作成 : (株)クラスキャット セールスインフォメーション
日時 : 04/14/2018
* 本ページは、TensorFlow.js サイトの Guides – TensorFlow.js Layers API for Keras Users を翻訳した上で
適宜、補足説明したものです:
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
TensorFlow.js の層 API は Keras に追随してモデル化されています。貴方がチュートリアルとサンプルから気が付いているかもしれないように、層 API を (JavaScript と Python の間の違いが与えられらたもとで) 合理的に Keras に似せる努力をしています。これは Python で Keras モデルを開発した経験を持つユーザに JavaScript の TensorFlow.js 層へマイグレートすることを容易にします。例えば、次の Keras コードは JavaScript へと翻訳されます :
# Python: import keras import numpy as np # Build and compile model. model = keras.Sequential() model.add(keras.layers.Dense(units=1, input_shape=[1])) model.compile(optimizer='sgd', loss='mean_squared_error') # Generate some synthetic data for training. xs = np.array([[1], [2], [3], [4]]) ys = np.array([[1], [3], [5], [7]]) # Train model with fit(). model.fit(xs, ys, epochs=1000) # Run inference with predict(). print(model.predict(np.array([[5]])))
// JavaScript: import * as tf from '@tensorlowjs/tfjs'; // Build and compile model. const model = tf.sequential(); model.add(tf.layers.dense({units: 1, inputShape: [1]})); model.compile({optimizer: 'sgd', loss: 'meanSquaredError'}); // Generate some synthetic data for training. const xs = tf.tensor2d([[1], [2], [3], [4]], [4, 1]); const ys = tf.tensor2d([[1], [3], [5], [7]], [4, 1]); // Train model with fit(). await model.fit(xs, ys, {epochs: 1000}); // Run inference with predict(). model.predict(tf.tensor2d([[5]], [1, 1])).print();
けれども、このドキュメントで集めて説明したい幾つかの違いはあります。ひとたびこれらの違いとそれらの背後の理論的根拠を理解すれば、貴方の Python-to-JavaScript マイグレーション (あるいは逆方向のマイグレーション) は比較的スムースな経験になるはずです。
コンストラクタは JavaScript オブジェクトをコンフィギュレーションとして取る
上のサンプルからの次の Python と JavaScript 行を比較してください : それらは両者とも Dense 層を作成します。
# Python: keras.layers.Dense(units=1, inputShape=[1])
// JavaScript: tf.layers.dense({units: 1, inputShape: [1]});
JavaScript 関数は Python 関数のキーワード引数と同等のものを持ちません。私達はコンストラクタ・オプションを JavaScript の位置引数として実装することは回避したいです、これらは巨大な数のキーワード引数 (e.g., LSTM) を伴うコンストラクタのためには覚えて使用することは特に扱いにくいでしょう。これが JavaScript コンフィギュレーション・オブジェクトを使用する理由です。そのようなオブジェクトは Python キーワード引数と同じレベルの位置普遍性と柔軟性を提供します。
Model クラスの幾つかのメソッド、e.g., Model.compile(), もまた入力として JavaScript コンフィギュレーション・オブジェクトを取ります。けれども、Model.fit(), Model.evaluate() と Model.predict() は少し異なることに留意してください。何故ならばこれらのメソッドは入力として必須の x (特徴) と y (ラベルかターゲット) データを取るからです ; x と y は、キーワード引数の役割を果たすすぐ次のコンフィギュレーション・オブジェクトとは別の位置引数です。例えば :
// JavaScript: await model.fit(xs, ys, {epochs: 1000});
Model.fit() は async
Model.fit() は主要なメソッドで、それを用いてユーザは TensorFlow.js でモデル訓練を遂行します。このメソッドはしばしば長時間実行の可能性があり、数秒または数分間続きます。それ故に、この関数がブラウザで実行されるときにメイン UI スレッドをブロックしない方法で使用されるように JavaScript 言語の async 特徴を活用します。これは async fetch のような、JavaScript の他の潜在的に長時間実行される関数と同様です、async は Python には存在しない構成物であることに注意してください。Keras の fit() メソッドが History オブジェクトを返す一方で、JavaScript における fit() メソッドの相対物は History の Promise を返します、これは (上のサンプル内のように) await されるか then() メソッドで使用されます。
TensorFlow.js のために NumPy はありません
Python Keras ユーザは上のサンプルで 2D tensor を生成するような、基本的な数値と配列演算を遂行するためにしばしば NumPy を使用します。
# Python: xs = np.array([[1], [2], [3], [4]])
TensorFlow.js では、この種の基本的な数値演算はパッケージそれ自身で成されます。例えば :
// JavaScript: const xs = tf.tensor2d([[1], [2], [3], [4]], [4, 1]);
tf.* 名前空間は配列と行列操作のような線形代数演算のための多数の関数もまた提供します。更なる情報のためには TensorFlow.js Core ドキュメント を見てください。
コンストラクタではなく、ファクトリメソッドを使用します
(上のサンプルからの) Python のこの行はコンストラクタ呼び出しです :
# Python: model = keras.Sequential()
厳密に JavaScript に翻訳された場合、同等なコンストラクタ呼び出しは次のように見えるでしょう :
// JavaScript: const model = new tf.Sequential(); // !!! DON'T DO THIS !!!
けれども、私達は “new” コンストラクタを使用しないことを決定しました、何故ならば 1) “new” キーワードはコードをより膨らませまて 2) “new” コンストラクタは JavaScript の「バッド・パート」と見做され、潜在的な落とし穴です。
TensorFlow.js でモデルと層を作成するためには、lowerCamelCase 名を持つファクトリメソッドを呼び出します、例えば :
// JavaScript: const model = tf.sequential(); const layer = tf.layers.batchNormalization({axis: 1});
オプション文字列値は lowerCamelCase です、snake_case ではありません
snake case が一般的な (e.g., Keras で) Python と比べて、JavaScript では、シンボル名のために camel case を使用することがより一般的です (e.g., Google JavaScript Style Guide を見てください)。そのようなものとして、次を含むオプションの文字列値のために lowerCamelCase を使用することを決定しました :
- データフォーマット, e.g., channels_first の代わりに channelsFirst
- Initializer, e.g., glorot_normal の代わりに glorotNormal
- 損失とメトリクス, e.g., mean_squared_error の代わりに meanSquaredError, categorical_crossentropy の代わりに categoricalCrossentropy。
例えば、上のサンプル内のように :
// JavaScript: model.compile({optimizer: 'sgd', loss: 'meanSquaredError'});
モデル・シリアライゼーション デシリアライゼーションについて、安心してください。TensorFlow の内部メカニズムは JSON オブジェクトの snake case が正しく処理されることを保証します、 e.g., Python Keras から事前学習されたモデルをロードするとき。
層オブジェクトは apply() で実行します、それらを関数としては呼び出しません
Keras では、層オブジェクトは定義された __call__ メソッドを持ちます。そのためユーザはオブジェクトを関数として呼び出すことにより層のロジックを起動できます、e.g.,
# Python: my_input = keras.Input(shape=[2, 4]) flatten = keras.layers.Flatten() print(flatten(my_input).shape)
この Python シンタックス・シュガーは TensorFlow.js では apply() メソッドとして実装されます :
// JavaScript: const myInput = tf.input{shape: [2, 4]}); const flatten = tf.layers.flatten(); console.log(flatten.apply(myInput).shape);
Layer.apply() は具体的な tensor 上で命令型 (eager) 評価をサポートします
現在、Keras では、call メソッドは (Python) TensorFlow の Tensor オブジェクト上で作用するだけで (TensorFlow バックエンドを仮定してます)、これはシンボリックで実際の数値は保持しません。けれども、TensorFlow.js では、層の apply() メソッドはシンボリックと命令型モードの両者で作用できます。apply() が SymbolicTensor (tf.Tesnor の密接な類推) で呼び起こされる場合、戻り値は SymbolicTensor です。これは典型的にはモデル構築の間に起こります。しかし apply() が実際の具体的な Tensor 値で呼び起こされた場合には、それは具体的な Tensor を返します。例えば :
// JavaScript: const flatten = tf.layers.flatten(); flatten.apply(tf.ones([2, 3, 4])).print();
この特徴は (Python) TensorFlow の Eager Execution の想起 (= reminiscent) です。それは動的ニューラルネットワークを構成するためのドアを開けることに加えて、モデル開発の間より偉大な対話性とデバッグの容易さを与えます。
Optimizer は train. 下、optimizers ではありません
Keras では、Optimizer オブジェクトのコンストラクタは keras.optimizers.* 名前空間のもとにあります。TensorFlow.js 層では、Optimizer のファクトリメソッドは tf.train.* 名前空間のもとにあります。
例えば :
# Python: my_sgd = keras.optimizers.sgd(lr=0.2)
// JavaScript: const mySGD = tf.train.sgd({lr: 0.2});
loadModel() は URL からロードします、HDF5 ファイルではありません
Keras では、モデルは通常は HDF5 (.h5) ファイルとしてセーブされ、これは keras.models.load_model() メソッドを使用して後でロード可能です。メソッドは .h5 ファイルへのパスを取ります。HDF5 はブラウザ-friendly なファイル・フォーマットではありませんので、tf.loadModel() は TensorFlow.js-specific フォーマットを取ります。tf.loadModel() はその入力引数として model.json ファイルを取ります。model.json は tensorflowjs pip パッケージを使用して Keras HDF5 ファイルから変換されます。
// JavaScript: const model = await tf.loadModel('https://foo.bar/model.json');
tf.loadModel() は tf.Model の Promise を返すことにも注意してください。
以上