えーっ!! 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]を渡す → 「猫」だと思います。
と数字じゃなく文字で返してもらうことにしよう。というわけで私は無意味な地獄にはまって行ったのです。
以下、無意味な地獄の話。改善したこちらのエントリーもどうぞ。
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から同じインデックスのモノを取って来て表示。
さて、ブラウザで実行してみると、以下のように徐々に数字が減って行きます。これが間違い率みたいなもので、低いほど学習が進んでいます。
トレーニングが終わったモデルさんがどう予測してくれるか、チェック。
入力と出力をお忘れでしょうからもう一度書きます。
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」を渡してみましょう。
わかりにくいですが、チェック関数に[1]を渡すとtensorflowがテンソルを返してくれます、なんとなく[0, 0, 1]に近い形をしていますね。これをワンホットに直し、自作した答えリストと照らし合わせ、「fox」にマッチする、と答えを出してくれています。
もうちょっと曖昧な数値を渡すとどうでしょう?
「0.4」を渡してみれば、[0,1,0]に近い形で返してくれました。これはxsの0.5に近い入力なので、これで正解ということになります。
以上。
ムキになってワンホットを自作したりしましたが、たぶん気軽にラベルを設定する方法とかあるはずなんですよね。
tensorflowで大事なことは、データ(例えば画像)をどのようにインプットとしてフォーマットし、テンソルとして渡すのか、ここのように思えます。画像ならピクセルの数をテンソルに合わせる模様、[28×28]など、なるほどぉ~。
あとはアウトプットの読み取り方もよくわかっていませんが、何か簡単なラベルの操作の仕方がありそうな気がします。
ゆくゆくはリアルタイムの映像認識を学習して、自動販売機を作りたい、と思ったのですが...お金の映像認識は結構危ないな、カ○ーコピーされたらたぶん認識しちゃってアウトだよね 笑。
書いてしまうとあっさりですが、ここまで死ぬほど苦労しました。
↑ こうです。