noteのタイトル画像

JavaScriptにもTensorFlowがやってきた

目次
・TensorFlow見参
・チュートリアルをやってみる
・テンソル・・・?
・オペレーション

●tensorflow.js見参

機械学習を学習する上で必須であるフレームワークと言えば「tensorflow」という具合に相場が決まってしまった感はあります。

ネットを調べても本屋に行っても、そこらじゅうtensorflowの記事・書籍ばかり。

tensorflow(テンソルフロー)についてはwikipediaで大体の概略は知ることができます。

googleさんが開発したもののようです。

ver1.0のリリースが2017年2月というわけで、非常に新しいプロダクトですね。
それなのに、もうかなりの人気です。

おそるべしGoogle。

また、こちらのサイト

でも概要が説明されています。

●チュートリアル

がここにあります。

さっそく、読み進めましょう。

まずは「TensorFlow.jsのコアコンセプト」からです。

TensorFlow.jsは

「TensorFlow.jsは、マシンインテリジェンスのためのオープンソースのWebGLアクセラレーションされたJavaScriptライブラリです。それはあなたの指先に高いパフォーマンスを発揮する機械学習のビルディングブロックをもたらし、ブラウザでニューラルネットワークを訓練したり、事前に訓練されたモデルを推論モードで実行することができます。」

だそうです。

なるほど、遥か永劫の昔に聞いた「ニューラルネットワーク」という言葉が出て来ました。当時としてはSF的な匂いがしたことを覚えています。

しかし、WebGLってなんでしょう?

wikipediaによれば、

だとか、、、わかったようなわからないような。
OpenGLの派生規格みたいですね。ふむふむ。

機械学習といいつつ、ブラウザ上での描画を意識するあたりがJavaScriptっぽいところもありますが。

また、

「TensorFlow.jsは、機械学習用の低レベルビルディングブロックと、ニューラルネットワークを構築するための高レベルのKeras風のAPIを提供します。」

だそうです。

ここでまた「Keras」という言葉が登場します。

またwikipediaのお世話になります。

「Kerasは、Pythonで書かれたオープンソースニューラルネットワークライブラリである。MXNet(英語版)、Deeplearning4j、TensorFlow、CNTK、Theano(英語版)の上部で動作することができる。」

とのこと。

TensorFlowの上部で動作できるライブラリのようですね。
今回はまだお世話にならないので、先に進みましょう。

●テンソル・・・?

聞きなれない言葉が出て来ました。

「TensorFlow.jsのデータの中央単位は、テンソルです。数値の集合は、1つ以上の次元の配列に整形されています。Tensorインスタンスが有するshapeアレイ形状を定義する属性(すなわち、多数の値は、アレイの各次元です)。」

らしいです。「データの単位」くらいに覚えておけば良いでしょうか。

次元だかなんだかよくわからないので、次の例文が載ってます。
まあ、見たからと言ってすぐに理解できるものではないですが、

// 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]]

どうやら、テンソルとは数学で習った「行列」のようですね。
大昔、行列計算、状態方程式で頭がパニクった記憶が蘇ります。

大抵、学校で習う数式って意味がわからずに計算しているので、社会人になって仕事の上で「状態方程式」が登場したときに、めちゃくちゃ感動した記憶があります。
名刺のCMではないですけど、「(こんなところで使うなら)早く言ってよぉ〜」って思いました。

このテンソルを作成をするメソッドとして、tensorではなく「scalar、tensor1d、tensor2d、tensor3dとtensor4d」のような特化したメソッドを使うように推奨されています。

こんな感じに

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]]

うーん。どうなんだろ?
この程度だったら、可読性が高まったというほどの効果があるのかわかりませんが、メソッドに「2d」って書かれているので、確かに2次元配列なんだとはわかりますが。

3dでは、

const z = tf.tensor3d([1,2,3,4,5,6],[3,2,1]);
z.print();
// Output: 
/*
    [[[1],
      [2]],

     [[3],
      [4]],

     [[5],
      [6]]]
*/

みたいな感じになりました。
4dは、、、何に使うんでしょう?(笑)

このテンソルは

「テンソルは不変です。作成されると、その値を変更することはできません。代わりに、新しいテンソルを生成する演算を実行します。」

とのこと。ここがただの配列とは違うってことのようです。
一度作ったテンソルは変更することはできない(=イミュータブル)のですね。

でも、プログラムを書いていて、全部がイミュータブルだったら困ることも多々あります。
そのため、TensorFlowでは次のような変数も用意しています。

「Variablesはテンソルの値で初期化されます。テンソル とは異なり、その値は変更可能です。assignメソッドを使用して、既存の変数に新しいテンソルを割り当てることができます。」

例として次のプログラムが載っていました。

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]

随分と遠回しな記述のように思えますが、うっかり値を更新してしまわないように、あえて(?)厳格に記述するのでしょうか。

●オペレーション

定数と変数が出て来たら、やっぱり操作(オペレーション)ですね。

「テンソルを使用するとデータを格納できますが、操作(ops)ではそのデータを操作できます。TensorFlow.jsは、テンソルで実行できる線形代数と機械学習に適したさまざまな操作を提供します。テンソルは不変なので、これらの演算子は値を変更しません。代わりに、オプスは新しいテンソルを返します。」

とのことなので、さっそく例題を見ましょう。

単項演算「square」の例です。

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という足し算の例です。

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]]

なるほど、確かに行列要素が足し算されています。
うーん。オブジェクト同士の演算なので、素直に「+」ってできないところが面倒って言えば面倒ですね。
(C++とかだったら、オペレータオーバライドで+演算子を定義しちゃいそうですが)

演算を連続して実行するともできるようです。

const sq_sum = e.add(f).square();
sq_sum.print();
// Output: [[36 , 64 ],
//          [100, 144]]

みたいに。

さて、定数、変数、操作が登場したことで、やっと面白くなってきました。
少し長くなったので「モデルとレイヤー」については次回以降でご紹介します。

ソフトウェア・エンジニアを40年以上やってます。 「Botを作りたいけど敷居が高い」と思われている方にも「わかる」「できる」を感じてもらえるように頑張ります。 よろしくお願い致します。