TensorFlow.js : チュートリアル : TensorFlow.js の中心概念 (翻訳/解説)
作成 : (株)クラスキャット セールスインフォメーション
日時 : 04/03/2018
* 本ページは、TensorFlow.js サイトの Tutorials – Core Concepts in TensorFlow.js を翻訳した上で
適宜、補足説明したものです:
* サンプルコードの動作確認はしておりますが、適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
TensorFlow.js は機械知能のためのオープンソースの WebGL で高速化される JavaScripit ライブラリです。それは高性能な機械学習ビルディングブロックを貴方の手元にもたらし、ニューラルネットワークをブラウザで訓練したり事前訓練したモデルを推論モードで実行することを可能にします。
TensorFlow.js は機械学習のための下位ビルディングブロックとニューラルネットワークを構築するための高位の、Keras にインスピレーションを得た API を提供します。ライブラリの中心コンポーネントの幾つかを見てみましょう。
Tensor
TensorFlow.js のデータの中心的なユニットは tensor です : 一つまたはそれ以上の次元の配列へ shape された数値のセットです。Tensor インスタンスは配列 shape を定義する shape 属性を持ちます (i.e, 配列の各次元にどれだけの値があるか)。
主要な Tensor コンストラクタは tf.tensor 関数です :
// 2x3 Tensor const shape = [2, 3]; // 2 rows, 3 columns const a = tf.tensor([1.0, 2.0, 3.0, 10.0, 20.0, 30.0], shape); a.print(); // print Tensor values // Output: [[1 , 2 , 3 ], // [10, 20, 30]] // The shape can also be inferred: const b = tf.tensor([[1.0, 2.0, 3.0], [10.0, 20.0, 30.0]]); b.print(); // Output: [[1 , 2 , 3 ], // [10, 20, 30]]
けれども、low-rank tensor を構築するためには、コードの可読性を高めるために次の関数を使用することを推奨します : tf.scalar, tf.tensor1d, tf.tensor2d, tf.tensor3d と tf.tensor4d。
次のサンプルは tf.tensor2d を使用して上の一つと同値な tensor を作成します :
const c = tf.tensor2d([[1.0, 2.0, 3.0], [10.0, 20.0, 30.0]]); c.print(); // Output: [[1 , 2 , 3 ], // [10, 20, 30]]
TensorFlow.js はまた総ての値が 0 に設定されるか (tf.zeros) 総ての値が 1 に設定される (tf.ones) tensor を作成するための便利な関数も提供します :
// 3x5 Tensor with all values set to 0 const zeros = tf.zeros([3, 5]); // Output: [[0, 0, 0, 0, 0], // [0, 0, 0, 0, 0], // [0, 0, 0, 0, 0]]
TensorFlow.js では、tensor はイミュータブルです ; ひとたび作成されれば、それらの値を変更することはできません。代わりにそれらの上で新しい tensor を生成する演算を遂行します。
Variables (変数)
Variable は tensor の値で初期化されます。けれども Tensor と違い、それらの値はミュータブルです。assign メソッドを使用して既存の variable に新しい tensor を割り当てることができます :
const initialValues = tf.zeros([5]); const biases = tf.variable(initialValues); // initialize biases biases.print(); // output: [0, 0, 0, 0, 0] const updatedValues = tf.tensor1d([0, 1, 0, 1, 0]); biases.assign(updatedValues); // update values of biases biases.print(); // output: [0, 1, 0, 1, 0]
Variable は主としてモデル訓練の間に値をストアしてから更新するために使用されます。
演算 (Ops)
tensor がデータをストアすることを可能にする一方で、演算 (ops) はそのデータを操作することを可能にします。TensorFlow.js は、tensor 上で遂行可能な、線形代数と機械学習に適切な多種多様の ops を提供します。tensor はイミュータブルですから、これらの ops はそれらの値を変更しません ; 代わりに、ops は新しい tensor を返します。
利用可能な ops は square のような単項 ops を含みます :
const d = tf.tensor2d([[1.0, 2.0], [3.0, 4.0]]); const d_squared = d.square(); d_squared.print(); // Output: [[1, 4 ], // [9, 16]]
そして add, sub, と mul のような二項 ops です :
const e = tf.tensor2d([[1.0, 2.0], [3.0, 4.0]]); const f = tf.tensor2d([[5.0, 6.0], [7.0, 8.0]]); const e_plus_f = e.add(f); e_plus_f.print(); // Output: [[6 , 8 ], // [10, 12]] TensorFlow.js has a chainable API; you can call ops on the result of ops: ```js const sq_sum = e.add(f).square(); sq_sum.print(); // Output: [[36 , 64 ], [100, 144]] // All operations are also exposed as functions in the main namespace, // so you could also do the following: const sq_sum = tf.square(tf.add(e, f));
Model と Layer
概念的には、モデルは、与えられた何某かの入力が何某かの望まれる出力を生成する関数です。
TensorFlow.js ではモデルを作成する2つの方法があります。モデルが行なうワークを表わすために ops を直接的に利用できます。例えば :
/ Define function function predict(input) { // y = a * x ^ 2 + b * x + c // More on tf.tidy in the next section return tf.tidy(() => { const x = tf.scalar(input); const ax2 = a.mul(x.square()); const bx = b.mul(x); const y = ax2.add(bx).add(c); return y; }); } // Define constants: y = 2x^2 + 4x + 8 const a = tf.scalar(2); const b = tf.scalar(4); const c = tf.scalar(8); // Predict output for input of 2 const result = predict(2); result.print() // Output: 24
貴方はまた layers (層) からモデルを構築するために高位 API tf.model を利用することもできます、これは深層学習のポピュラーな抽象です。次のコードは tf.sequential モデルを構築します :
const model = tf.sequential(); model.add( tf.layers.simpleRNN({ units: 20, recurrentInitializer: 'GlorotNormal', inputShape: [80, 4] }) ); const optimizer = tf.train.sgd(LEARNING_RATE); model.compile({optimizer, loss: 'categoricalCrossentropy'}); model.fit({x: data, y: labels)});
TensorFlow.js で利用可能な多くの異なるタイプの layers があります。2, 3 のサンプルは tf.layers.simpleRNN, tf.layers.gru と tf.layers.lstm を含みます。
メモリ管理 : dispose と tf.tidy
TensorFlow.js は数学演算をアクセラレートするために GPU を使用しますので、tensor と variable で作業するとき GPU メモリを管理する必要があります。
TensorFlow.js はこれを手助けするために2つの関数を提供します : dispose と tf.tidy です。
dispose
tensor または variable 上でそれをパージしてその GPU メモリを解放するために dispose を呼び出すことができます。
const x = tf.tensor2d([[0.0, 2.0], [4.0, 6.0]]); const x_squared = x.square(); x.dispose(); x_squared.dispose();
tf.tidy
dispose の使用は多くの tensor 演算を行なうときには扱いにくいかもしれません。TensorFlow.js はもう一つの関数, tf.tidy を提供します、これは JavaScript の通常のスコープに対して同様の役割を果たしますが、GPU-backed tensor のためです。
tf.tidy は関数を実行して作成された任意の中間的な tensor をパージし、それらの GPU メモリを解放します。それは内部関数の戻り値はパージしません。
// tf.tidy takes a function to tidy up after const average = tf.tidy(() => { // tf.tidy will clean up all the GPU memory used by tensors inside // this function, other than the tensor that is returned. // // Even in a short sequence of operations like the one below, a number // of intermediate tensors get created. So it is a good practice to // put your math ops in a tidy! const y = tf.tensor1d([1.0, 2.0, 3.0, 4.0]); const z = tf.ones([4]); return y.sub(z).square().mean(); }); average.print() // Output: 3.5
tf.tidy の使用は貴方のアプリケーションでメモリリークを回避する助けとなるでしょう。それはまたメモリが再利用されるときにより注意深く制御するためにも使用できます。
2つの重要なノート
- tf.tidy に渡される関数は同期的であるべきで Promise を返すべきでもありません。UI の更新やリモート・リクエストを行なうコードは tf.tidy の外側で保持することを提案します。
- tf.tidy は variable をクリーンアップしないでしょう。Variable は典型的には機械学習モデルのライフサイクル全体を通して存続しますので、TensorFlow.js はそれらが tidy 内で作成された場合でさえもそれらをクリーンアップしません ; けれども、それらの上で dispose を手動で呼び出すことはできます。
以上