deeplearn.jsのplaygroundで遊んでみる。SqueezeNetのソース理解
最近、おやつをガムに変えてみたところ、1か月で4キロほど痩せてしまった。
いままでどんだけおやつ食べてたんだと反省。
deeplearn.jsの勉強にと、とりあえず簡単そうなところから入ってみる。
playground
環境設定とかで躓きたくないので、とりあえずデモのPlayGroundで遊んでみる。
ここだと、サーバとか用意せず書いたコードをそのまま動かすことができるようだ。
SqueezeNet
playgroupndのリンクに「SqueezeNet - basic usage」とあったので、これ元にいじくって遊んでみよう。 その前に、SqueezeNetってなんだ?
https://www.semiconportal.com/archive/contribution/applications/170418-neurochip5-2.html
うーん、わからん。
わかったのは、ネットワークモデルの一種だということと、正確性より処理応答性を重視していることくらい。
使う分にはわからなくてもよいので、とりあえず表面をサラッと理解してみる。
ソースの理解
javascriptのソースを少しづつ理解していこう。
画像情報の読み込み
const catImage = document.getElementById('cat');
HTMLのIMGタグの画像情報を取り込んでいる。右下の猫の画像がそれ。
なんか細長い猫だなと思ったら、元画像は 240x217 で、IMGタグ内で 227x227 に変更している。
なんでやねんって、IMGタグのwidth x heightを240x217に変更して[RUN]を実行したらエラーになった。
Error: The output # of columns (119.5) must be an integer. Change the stride and/or zero pad parameters
どうやらSqueezeNetに読み込ませる画像は227x227出ないといけないようだ。
SqueezeNetのロード処理
const math = new dl.NDArrayMathGPU(); // squeezenet is loaded from https://unpkg.com/deeplearn-squeezenet const squeezeNet = new squeezenet.SqueezeNet(math); await squeezeNet.load();
SqueezeNetの何かを読み込んでいるらしい。
いきなり「dl」と出てきているが、これはplaygroundがデフォルトでdeeplean.jsを読み込んでいるため使えている。(だと思う)。
次の「NDArrayMathGPU()」は多次元配列をGPUで処理するものという理解(であっているのか?)
以下にdeeplearn.jsのチュートリアルを日本語訳されたサイトがあった。とても参考になる。
http://tensorflow.classcat.com/2017/08/20/deeplearn-js-tutorials-introduction/
イメージデータの変換
// Load the image into an NDArray from the HTMLImageElement. const image = dl.Array3D.fromPixels(catImage);
何か変換しているのはわかるが、なんだろうこれ?よくわからないので「console.log()」で吐き出す。
console.log(catImage); ↓ [object HTMLImageElement]
console.log(image) ↓ Tensor dtype: int32 rank: 3 shape: [227,227,3] values: [[[255, 255, 255], [255, 255, 255], [255, 255, 255], ..., [255, 255, 255], [255, 255, 255], [255, 255, 255]], [[255, 255, 255], [255, 255, 255], [255, 255, 255], ..., [255, 255, 255], [255, 255, 255], [255, 255, 255]], [[255, 255, 255], [255, 255, 255], [255, 255, 255], ..., [255, 255, 255], [255, 255, 255], [255, 255, 255]], ... [[169, 193, 180], [165, 193, 178], [161, 196, 176], ..., [40 , 39 , 35 ], [55 , 51 , 48 ], [37 , 34 , 29 ]], [[150, 188, 173], [152, 190, 175], [158, 192, 175], ..., [27 , 26 , 22 ], [33 , 29 , 26 ], [30 , 27 , 22 ]], [[157, 194, 187], [164, 197, 186], [165, 198, 181], ..., [35 , 34 , 30 ], [49 , 44 , 40 ], [38 , 30 , 27 ]]]
IMGタグの画像情報をint32の3次元配列[227,227,3]に変換しているようだ。 画像が227x227なので、3はRGB情報だろう。
推論
// Predict through SqueezeNet. const logits = squeezeNet.predict(image);
[Predict:予測] なので、たぶん推論しているんだろうな。 logitsって何だろう。
console.log(logits) ↓ Tensor dtype: float32 rank: 1 shape: [1000] values: [14.1952286, 12.3713379, 13.3236885, ..., 1.7310563, 17.3527832, 17.3972549]
float32の1次元配列[1000]が入っていた。よくわからない。
結果表示
// Convert the logits to a map of class to probability of the class. const topClassesToProbs = await squeezeNet.getTopKClasses(logits, 10); for (const className in topClassesToProbs) { console.log( `${topClassesToProbs[className].toFixed(5)}: ${className}`); }
推論結果を出力。
squeezeNet.getTopKClassesの前にawaitが入っている。非同期処理を想定しているってことはそれなりに重い処理なのか?
想像するに、SqueezeNetには1000の答えがあり、上で求めた「logits」には、各答えの正解率が入っているのではないか?
「squeezeNet.getTopKClasses(logits, 10)」でそのうち上位10件を切り出している。そんなところだろう。
よくわからないこと
HTML部に
<script src='https://unpkg.com/deeplearn-squeezenet'></script>
とあるが、これはなんだ?削っても問題なく動くし。
アクセスするとよくわからないJavascriptソースが下りてきた。
まとめ
一番簡単そうなソースで遊んでみましたが、DeepLearningの知識がほとんどない自分には突っかかりまくりで大変でした。このソースを使って応用する場合、画像サイズは227x227にそろえることを覚えておこう。
以上