新・日々の暮らしに疲れてない?

一人バンド、火頭工房

【Tensorflow.js】Tensorflowがjavascriptにやって来た。

えーっ!! Tensorflowがjavascriptに来たってぇ!?

そりゃめちゃくちゃホットです。

 

マシンラーニングはずっと気になっていた分野ですが、私は基本的にjavascriptしか使えないので泣く泣く保留していたのです、あとなんか難しそうだし。


以前2つ目のプログラミング言語を学習する気になった時、Pythonも候補だったのですが、Goを選んでしまったんですよね、その後Haskellも。←どっちも今全く触っていないので本当に判断ミスです。


ついに、人工知能ライブラリのTensorflowがjavascriptで使えるようになりました、と。これはもう逃げ道がありません、やるっきゃない!


環境構築はめちゃくちゃ嫌いなので、かなり気合を入れて公式ページを開き、導入の仕方を見ることに。さて何をインスコさせられ、パスを通させられるのやら...


実際は

<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@0.11.7"> </script>

これをhtmlファイルに貼るだけ。衝撃の手軽さです。


ウキウキになった所で、色んな人のブログを見て学習を始めたものの、すごく難しい、全くついていけん。


幸い私、英語がそこそこわかるので、Youtubeチュートリアル的なのを探した方がいいな、ということでいくつか物色したところ、この人の動画が一番自分に合っていました。教え方、しゃべり方、動画のクオリティも素晴らしい。

 

動画をなぞる形でとりあえず真似をする。

インプットを与えて、ラーニングさせて、アウトプットを出す。という流れは再現できました。


今回のインプットはただの数字、例えば


const xs = tf.tensor2d([     

  [0], 

  [0.5],   

  [1]

 ]);


tf.tensor2dの部分は、こうしてデータを渡さないとtensorflowが読んでくれないからこういう書式にする。そりゃテンソル(テンサー)フローですからね。


人工知能界隈ではテストデータを「xs」で表現するのが慣習な模様。

xsは例えばトランプのカードの画像。
それに対してysは「ラベル」と呼ばれ、xsと対になる「答え」のリスト。

 

例えば、xsの最初の画像(カード)は「ハートの5」次は「スペードのジャック」ですよ、などとtensorflowに教えてあげるわけですね。


答えは適当に

const ys = tf.tensor2d([     

  [1, 0, 0], 

  [0, 1, 0], 

  [0, 0, 1]

 ]);


とりあえずこんな感じに。

xsと合わせて見ると、[0]を渡した時、答えは[1,0,0]で、[0.5]を渡せば[0,1,0]ですよ、と学習させて行く感じ。tensorflowは自分で予測を立て、ミスを繰り返しながら予測の精度を高めて行く感じでしょうか。

 

学習パラメータや方法などを指定して実行してそれでお終い。このあたりは動画のコピーで簡単に終わりました。ただしっかり理解するのは難しい、ってか自分には無理な気がします。


学習が終わったモデルさんに、xsと同じような形でデータを用意して渡してあげれば...

[0]に対する答えは [0.988889, 0.122112, 0.122343] ←こんな感じで返ってきます。

[1, 0, 0]に近い形になり、一応これでインプットに対して予想を返す、ということが出来ました。


んー、でも数字の羅列が返って来てもよくわかんないよな...

ゆくゆく実践したい画像認識を意識して、

[0]を渡す → 「犬」だと思います。

[0.5]を渡す → 「猫」だと思います。

と数字じゃなく文字で返してもらうことにしよう。というわけで私は無意味な地獄にはまって行ったのです。

 

f:id:hiatama:20180704214201j:plain

 

以下、無意味な地獄の話。改善したこちらのエントリーもどうぞ。


tensorflowさんが返してくれる [0.988889, 0.122112, 0.122343] こういうやつをまずテンソルではなく、普通の数値に変換する。

dataSync() でOK、これで手軽にいじれます。


ysと同じ内容の答えリストを用意する

const answerList = [     

  [1, 0, 0], //dog     

  [0, 1, 0], //cat     

  [0, 0, 1]  //fox

]

それぞれどういう意味なのかを別のリストに書く。

const answerWords = ['dog', 'cat', 'fox'];


さて、返ってくるデータは半端な数字なので、なんというか四捨五入的なことをして、[1,0,0]みたいな形に直す。ちなみにこういう[1]が1つだけ、他は[0]というデータの形をワンホットと言うそうです。


そのワンホットのデータとanswerListとを比べて一致するものを調べ、answerWordsから同じインデックスのモノを取って来て表示。

 

さて、ブラウザで実行してみると、以下のように徐々に数字が減って行きます。これが間違い率みたいなもので、低いほど学習が進んでいます。

 

f:id:hiatama:20180704213556p:plain

 

トレーニングが終わったモデルさんがどう予測してくれるか、チェック。

入力と出力をお忘れでしょうからもう一度書きます。

xs = [0, 0.5, 1]

ys = [     

  [1, 0, 0],  ←「dog」を意味します     

  [0, 1, 0],  ←「cat」を意味します     

  [0, 0, 1]   ←「fox」を意味します     

]

例えば、[0.1]を渡したらtensorflowさんが「それ[1, 0, 0]に近いよね」とテンソルで結果を返してくれて、その結果を先述のワンホットがうんたらとかをまとめた自作のcheck()関数で翻訳「答えはdogっぽいですよ」。みたいな感じ。

 

では「1」を渡してみましょう。

f:id:hiatama:20180704213559p:plain

わかりにくいですが、チェック関数に[1]を渡すとtensorflowがテンソルを返してくれます、なんとなく[0, 0, 1]に近い形をしていますね。これをワンホットに直し、自作した答えリストと照らし合わせ、「fox」にマッチする、と答えを出してくれています。

 

もうちょっと曖昧な数値を渡すとどうでしょう?

f:id:hiatama:20180704213601p:plain

「0.4」を渡してみれば、[0,1,0]に近い形で返してくれました。これはxsの0.5に近い入力なので、これで正解ということになります。

 

以上。


ムキになってワンホットを自作したりしましたが、たぶん気軽にラベルを設定する方法とかあるはずなんですよね。


tensorflowで大事なことは、データ(例えば画像)をどのようにインプットとしてフォーマットし、テンソルとして渡すのか、ここのように思えます。画像ならピクセルの数をテンソルに合わせる模様、[28×28]など、なるほどぉ~。


あとはアウトプットの読み取り方もよくわかっていませんが、何か簡単なラベルの操作の仕方がありそうな気がします。


ゆくゆくはリアルタイムの映像認識を学習して、自動販売機を作りたい、と思ったのですが...お金の映像認識は結構危ないな、カ○ーコピーされたらたぶん認識しちゃってアウトだよね 笑。

 

書いてしまうとあっさりですが、ここまで死ぬほど苦労しました。

f:id:hiatama:20180704221619p:plain

↑ こうです。