はじめに
TensorFlow興味あるんだけど触ってないみたいなところにTensorFlow.jsがリリースされていたので触ってみました。
今回は多分もっともわかりやすいTensorFlow 入門 (Introduction)で紹介されている線形回帰のサンプルをTensorFlow.jsで実装してみました。
下記にDEMOを用意しました。
DEMOはクローズしました(2019/08/28)
コード全体
let randomData = [];
for(let i=0;i<=100;i++){
randomData[i] = Math.random();
}
let xData = tf.tensor1d(randomData);
let yData = tf.add(tf.mul(xData,tf.scalar(0.1)),tf.scalar(0.3));
let W = tf.variable(tf.zeros([1]));
let b = tf.variable(tf.zeros([1]));
//y = W * x + b
let y = x => tf.add(tf.mul(W,x),b);
let loss = (y,yd) => y.sub(yd).square().mean();
let optimizer = tf.train.sgd(0.5);
for (let i = 0; i <= 200; i++) {
optimizer.minimize(() => loss(y(xData),yData))
if(i % 20 == 0){
console.log(`step: ${i}, W: ${W.dataSync()}, b: ${b.dataSync()}`);
}
}
※上記コードはメモリの開放を行っていないためメモリリークします。実際にTensorFlow.jsを使う際はdispose()やtidy()を使用してメモリを開放するようにしてください
参考:https://js.tensorflow.org/tutorials/core-concepts.htmlの「Memory Management: dispose and tf.tidy」の項
やってること
ちゃんとした解説は多分もっともわかりやすいTensorFlow 入門 (Introduction)を参照してもらうとして、ざっくり下記のようなことをしています。
1. $ y = 0.1 \times x + 0.3 $からトレーニングデータを作成
2. $ y = W \times x + b $をモデルとして用意したトレーニングデータで線形回帰して$W$と$b$を求めます。それぞれが$0.1$と$0.3$位になれば成功です。
コード解説
注意
下記は多分もっともわかりやすいTensorFlow 入門 (Introduction)に載ってるソースコードと見比べながら読む感じを想定してます。
トレーニングデータ生成
let randomData = [];
for(let i=0;i<=100;i++){
randomData[i] = Math.random();
}
let xData = tf.tensor1d(randomData);
randomな値を一気に100個用意できないのでforで回して作りました。
TensorFlow.jsでは生の値のまま使わず、tf.tensor1dやtf.tensor4dなどを一度通して扱う必要があるみたいです(Pythonは勝手にその辺やってるんでしょうか?)
let yData = tf.add(tf.mul(xData,tf.scalar(0.1)),tf.scalar(0.3));
オペレータをオーバーロードできないので普通の四則演算のように書けないのでちょっと書きづらいです。addやmulなどが用意されているのでそれを使って計算していきます。
モデル定義
let W = tf.variable(tf.zeros([1]));
let b = tf.variable(tf.zeros([1]));
//y = W * x + b
let y = x => tf.add(tf.mul(W,x),b);
Wとbの部分はほぼ同じです。Wの方もbと同じtf.zeros([1])で構わないとのことだったのでそのようにしています。
yの部分はxを引数とした関数になりました
コスト関数を定義
let loss = (y,yd) => y.sub(yd).square().mean();
let optimizer = tf.train.sgd(0.5);
lossもy同様関数として定義しています。
optimizerはtf.train.GradientDescentOptimizerではなくtf.train.sgdでした。tf.train.sgdのドキュメントをみるとstochastic gradient descentって書いてたので多分同じ処理してくれてるはず。
実行
for (let i = 0; i <= 200; i++) {
optimizer.minimize(() => loss(y(xData),yData))
if(i % 20 == 0){
console.log(`step: ${i}, W: ${W.dataSync()}, b: ${b.dataSync()}`);
}
}
tf.Session()などは見当たらずちょっと途方にくれたのですが、初期化などは必要なく実行してもいいのかなとやってみたら動いた感じです。
実行例
おわりに
ちょっと謎な部分もあったので公式ページをちゃんと読まないとなと思いました。
modelとかlayerとかをまったく使わなかったので、気が向いたらそのあたりを使うようなのを作れたらいいかなと思います。