タグ:ニューラルネット ( 16 ) タグの人気記事

4値アクセラレータ完成

4値アクティベーションのアクセラレータも完成しました。
必要な工夫はモデル作成時の想定通りだったので、昨日以上のコメントもなく…
テストベンチは別に良いけど、回路部分だけはBNNと共通にしたいんです。
でも今はBNNが使えなくなっているはずで、直さなくちゃいけないけど Github は更新しています。

[PR]
by tom01h | 2017-10-22 23:57 | Trackback | Comments(0)
とりあえず C 言語で書いたサンプルモデルが出来上がりました。
やはり精度低下はバグが原因で、途中の演算精度を落としたせいではなかったようです。
ちなみに4値アクティベーションは、学習時は±1/3,1を使っていましたが、推論時は全体を3倍して±1,3を使います。
それに合わせて、正規化用の平均と分散も3倍します(正確にいうと分散を3倍するのではないですが…)。また、入力値から平均を引くのは良いとして、偏差で割るのは大変です。前もって逆数を計算しておいて掛けるのだって、やはり大変です。なので、次段の活性化で比較に使う1/2の方に偏差を掛けておきます。これで、2値の時と比べても、計算量は倍にはならないと思っています。
Github 更新してます。

[PR]
by tom01h | 2017-10-21 23:15 | Trackback | Comments(0)

蒸留

アクセラレータの4値化もやってはいるのですが、(バグ?)精度の低下の原因がわからなくて…

しょぼいニューラルネットの学習の方法に蒸留という方法があるらしいです。
大雑把にいうと、あいまいな答えしか出しようがないような教師データで変な癖がつかないように?、自分より賢い学習済みのネット(教師ネット)の出した判断結果を教師データとして使った学習法です。
例えば、教師ネットが ”1” の可能性が 60% で ”7” の可能性 40% と言うならそれが教師データになります。真実がどうとかは気にしません。正義みたいなもんです。
バイナリ化したネットでは、バイナリ化する前のネットを教師ネットにしてみるのもありなんじゃないか。
ということで試してみた。
1%くらい良くなっているような、誤差のうちのような…
f0054075_00405195.png


[PR]
by tom01h | 2017-10-20 23:59 | Trackback | Comments(0)

入力データ加工

入力データを
0~1の実数→0~255の整数→-255~255の奇数
と変更して試してみた結果、最後のが一番良い結果を見せました。
そもそも認識精度のばたつきが気になっていたのですが、精度そのものもちょっと上がったみたいです。こんなことで…
f0054075_18034763.png
次こそ4値化のアクセラレータ作る。
[PR]
by tom01h | 2017-10-14 18:04 | Trackback | Comments(0)

4値化?

次はアクセラレータのテナリ化かな?とも思ったのですが、なんで4値じゃなくて3値なんだろうかと疑問を持っています。
まあ、3値だと掛け算しても3値のままだから便利なんだろうけど、ここでは掛け算の相手は2値だから4値でも良いよね。
で、試してみる前に、今まで気になっていた乱高下の原因を突き止めたいです。バイナリネットでは入力データの正規化は必要ないんじゃないかと思いついたので試してみました。
左がウェイトだけ2値化、右はアクティべーションも2値化。
f0054075_20365912.pngf0054075_21181478.png
まぁ多少はましになったのかな?では本番。左が3値化で右が4値化です。
f0054075_22371580.pngf0054075_23483700.png

テスト時の認識精度をまとめてみました。やっぱり4値を使った方が良いみたいですねぇ。人の真似しているだけじゃなくて、自分で考えないと駄目ですねぇ。
f0054075_23511832.png
ちなみにアクティベーション関数は下のような感じです。逆伝搬はどれも STE を使います。
f0054075_23583658.png

[PR]
by tom01h | 2017-10-12 23:59 | Trackback | Comments(0)
こんな感じでパイプ化しました。これを32個並列実行します。
実際には 1st Stage 前半は一つ上の階層にあります。
毎サイクル 1024bit のパラメータを読むのは電力的に良くないかな?
f0054075_10553750.png
アクセラレータの使い方です。
畳み込み層1階層分の計算例です。左の入力から右の出力を得る手順を説明します。奥行きがチャンネル方向で、面倒なので32の場合で説明します。
f0054075_17570377.png
入力データ幅の32ビットは入力チャンネルサイズなので、入力の青色の1本分のデータを一度に処理できます。面倒なので以降は平面で書きます。
カーネルサイズが3×3で、poolingでX,Y方向をそれぞれ半分にするので、入力16ドットから出力1ドットが得られます。
最初にInitで初期化します。次に、1から9の順にAccを実行して最初の畳み込みを計算します。Poolを実行すると、ACCの値がPOOLにコピーされます。
次に10から18の順にAccを実行し、さらにPoolを実行します。最初の畳み込みよりもACCが大きければPOOLが更新されます。つぎはY方向にずらして以下同様に…
f0054075_17573504.png
4回繰り返して最大値が求まったらNorm、Activの順に実行し、1個の回路から1粒の出力を得ます。回路は32個並列に実装されているので、最初の絵の出力の青色1本分のデータを一度に得る事が出来ます。
1本分の出力が終わったら、X方向に2個ずらして次の16ドットを繰り返します。X方向が終わったらY方向に2ドットずらして繰り返します。
全結合層とかチャンネルサイズが64とかでも上手く行くとは思うのですが、大変そうなので説明は省きます。


[PR]
by tom01h | 2017-10-09 20:33 | Trackback | Comments(0)
まだ非同期版ですが、とりあえず BNN のアクセラレータが動くようになりました。
全5層のうち第2,3,4層を Verilog 化して、C で書いた第1,5層があるテストベンチと組み合わせて BNN の推論が実行できます。全部 C で書いた推論実行環境と一致しているみたいです。こういうのって、Verilator が便利です。しかも速い。
次はちゃんとハードウェア化を考えて、同期メモリ化とパイプライン化したいと思います。

Github は ここ

[PR]
by tom01h | 2017-10-08 21:49 | Trackback | Comments(0)
昨日書いたように、バイナリアクティベーション環境にはないはずのデータ ”0” をパディングに使っていたので修正しました。面倒なことに、学習からやり直す必要がありました。

そしてとりあえず第2層だけ Verilog で書いてみました。
C で作った環境を元に Verilator でテストベンチを作っているのですが、C99 で使える可変長配列?なるものが C++ で使えません。仕方がないので、入力と第1層を可変長配列を使わないように書き直して、第2層に繋げました。
とりあえず出力は C で作った環境と一致している模様。
まずは動作確認のために、組み合わせ回路になっています。メモリも非同期アクセスです。正直、大変なのはテストベンチだけです。
いずれは、ちゃんとパイプライン化して、制御回路もある程度は Verilog にしたいですが…

置き場はここ。Python環境はこっち

[PR]
by tom01h | 2017-10-07 23:03 | Trackback | Comments(0)
データ型も2値化して結果が合わないと思ったら、パディングに0とかないはずの値を使っていた…
[PR]
by tom01h | 2017-10-06 23:59 | Trackback | Comments(0)

推論アクセラレータ構想

まずはBNNアクセラレータの妄想をしています。
パラメータは内蔵メモリ内に保持して、与えられたアドレスから読みだします。
入力データは外から与えます。
入力 x とメモリから読みだすウェイト WEIGHT は 32bit 幅で、入力の32チャンネルを一度に処理します。

以下のレジスタセットを持ちます。
  • WEIGHT(MEAN)
  • ACC
  • POOL

以下のコマンドを持ちます。
  • Init()
  • Acc(addr, x)
  • Pool()
  • Norm(addr)
  • Activ()

畳み込み1階層分の計算は以下をストライド繰り返し実行します。
Init
4回(POOL)繰り返す
ーAcc*9 (畳み込み回数=カーネルサイズ^2)
ーPool
Norm
Activ

こんなので上手く行くかな?なんだかデバッグにとっても手間取りそうな予感 (-ー)

[PR]
by tom01h | 2017-10-04 21:38 | Trackback | Comments(0)