祝! LUT-NetworkのLUTモデルの逆伝播学習動作
前回メモで書いた内容がどうやら動作したようなので、速報レベルで記事を書いておきます。
上記はMNISTデータをFP32にて、入力値がそれぞれバイナリの1になる確率として計算した後に、実際にバイナリモデルにテーブルコピーを行って動作確認したものです。
まずは原理検証ということで、FP32精度で軽く accuracy 0.8379 まで学習した後、バイナリのLUTモデルにコピーして x15(4bit精度) のPWM変調で accuracy 0.8084 が確認できました。コピー先のモデルは普通にFPGAのLUTをバイナリで模擬しているモデルなので、ちゃんと機能していることが確認できます。
アナログ値を例えばPWM変調などを掛けてバイナリにすると、もとの値に応じて確率的に1と0になります。このときの1になる確率から各テーブルの引かれる確率にして、最終的な結果が1になる確率を求める素子を構成し、この組み合わせを誤差逆伝播で学習させることで直接LUTテーブルを求めています。
ソースコードは
https://github.com/ryuz/BinaryBrain/blob/ver3_develop/include/bb/StochasticLut6.h
を参照下さい、Forward と Backward を見ていただければよいかと思います。
6入力LUTのモデルであり、重みとして W のパラメータが64個のテーブルに相当します。
Forwardでは、64個あるテーブルのそれぞれの参照される確率を求めた後に、テーブルの内容を2値化したものを元に、出力が1になる確率を求めるという他愛の無い計算で、Backwardではその微分を計算しています。
やっていることはシンプルなのですが、「テーブル引き」というモデルをそのまま数式にしてしまったところが新しいかと思いますし、テーブル引き時点で従来のいわゆるパーセプトロンとはかなり異なるモデルであることがご理解いただけるかと思います。
これがうまく行けば、極めて効率的にLUT-Networkの学習が可能になります。
また、学習過程では、「バイナリ値が1になる確率」という形で、FP32値を forward でも伝播させますので、回帰問題も効率的に学習できます(FPGAポーティング後の予測でオーバーサンプリング必要なのは従来どおりです)。
今回作った素子モデルは別にバイナリである必要もなくて
- N入力に対して、2^N個の重み係数を持つ
- forwardもbackwardも乗算と加算のみ
- 単独でXORが解ける素子
- 重みをfoward時に二値化するとFPGAに出来る
Nが小さい(疎行列)ことだけ重要で、ひょっとすると2値化せずに普通のDLの素子として使っても情報密度は従来のパーセプトロンのモデルより高いかも知れません。
従来のパーセプトロンを組み合わせて作ったμMLPよりも、早く高密度に学習しているような気がします。このあたりもおいおい追加検証が必要になりそうです。
現在CNNも実験中ですが、順調に学習が進行しています。
実行中の画面のスナップショットを以下に張っておきます。
このアイデアはまだCUDA化していないので重たいですね。ただまだ2epoc目で92%まで来ています。その後、95%をあっさり超えました。保存したパラメータでLUTのモデルで実行したところちゃんと accuracy : 0.9441 の結果も得られました。
このモデルはメモリアクセスが少なくて、乗算が非常に多いので、CUDAにとても向いていると思います。
そもそも論として、FPGAに限らずに、ワーキングセットが小さく出来ればキャッシュのヒット率その他、計算機の効率が上げやすいという方向なので、ワーキングセットを小さくして代わりにfpsを上げて認識性能を出していくという試みは、いろいろと面白いのではないかと思います。
(2019/04/01追記)
DNNの学習だけではなく、もっと手広く使えそうな気がしてきたのでTwitterに書いたことも転記しておきます。
今回のモデルの計算グラフが下記です。6入力LUTを書くとテーブルが64個となり書くのが大変なので、2入力LUT(テーブルサイズ4)で書いてみました。
実際にはこれの6入力版をパーセプトロン素子の代わりに使ってLUTネットワークの学習に成功しているわけです。もはやニューラルネットと呼んでよいのか微妙になってきましたが、複数のパーセプトロン素子でも等価なものが作れるのでぎりぎり許してください。
各テーブル(W0~W3)が引かれる確率を求めているため、構造的にWを掛け算する前に、入力同士の乗算が発生しているのが特徴かと思います。また各テーブル値は回路化すると0か1しか取らないので、forward時は2値化して、backward時はそのまま使っています。FPGA化しないなら2値化自体不要と思います。
通常のパーセプトロンのモデルは入力同士が最終段の加算部でのみ結合するので、単素子の逆伝搬ではお互い干渉しません。今回のモデルはクロスバー的には乗算で絡まっていて激しく干渉するのですがちゃんと動いていて自分が一番信じられないですが、CNNの例のとおり学習に関しては効率的に動作しているようです。
このモデルは出力と他の入力値の両方の影響を受けるのでXORが学習できてしまいます。接続数が増えると破綻するので疎結合でしか利用できませんが、逆に言えば1段で全結合という手を取らなければ回避できます。生物の脳をモデルにしてたら思い付きようがないモデルと思っていまして、FPGAをモデルにしたからこその成果と思います。
で、今回のモデルはもともとがデジタル論理素子の直接学習なので、あらゆるデジタル電気回路を記述可能です。するとこれを逆に使うことで、デジタル回路をネットに置き換えて逆伝播を行うことが可能と思われます。
つまり、今回のモデルを使えばあらゆるone-way functionの逆解を求めるのに特別な知識なしにGPU回すだけの状態に変換可能な気がします。初期値依存なので実用的なパフォーマンスが出るか不明ですが、いわゆる暗号解読などの分野にDLの計算環境を活用できる可能性があります。
例えば、デジタル乗算器の回路をLUT-Networkに写し取って、テーブル固定して、素因数分解したい値を教師にして、逆伝搬を繰り返せば素因数分解が出来ることになります。
素因数分解などは、まだ、十分研究されている分野ですが、それ以外の複雑な系に関して、片方向の演算が定義できれば、簡単に逆計算がGPUを活用して探索できます。
このモデルの入力同士で逆伝播に相互干渉するというのは、一種の自己参照ループと思っていまして、OPアンプのフィードバックとか想像してもらうと分かりやすいかと思いますが、解が存在すればそこに向かって系が収束していきます。フラットなグラフで最適化したいたら自己参照ループがうまく解けないケースが多いのですが、今回はDNNのテクニックで非常にうまく微分値が反映できています。
かつて、チューリングらが、エニグマの暗号解読に自己参照ループを活用したチューリングボンベという非チューリングマシンを使って挑んだ話は有名ですが、こういったアプローチが、NP問題とか数学的にも解かれていない領域に対してあたらしい切り口が出来れば非常に面白いと思う次第です。
幸いBinaryBrainはこういう実験もやれそうな構造に作っているので、どこかで挑戦してみたいと思います。
« LUT-Networkの為の学習方法アイデアメモ | トップページ | LUT-Networkの最新資料更新 »
「FPGA」カテゴリの記事
- LUT-Networkの蒸留とMobileNet風構成とセマンティックセグメンテーション(2020.03.09)
- LUT-Networkの蒸留(Distillation)について(2019.12.29)
- FPGAでのDNN(Deep Neural Network)の整理(LUT-Netまとめ)(2019.12.15)
- LUT-NetのFPGAリソースについて(2019.12.08)
- MNIST認識のリアルタイム動作環境更新(2019.09.02)
「Deep Learning」カテゴリの記事
- Deep Learning の開発フロー(2020.03.23)
- LUT-Networkの蒸留とMobileNet風構成とセマンティックセグメンテーション(2020.03.09)
- LUT-Networkの蒸留(Distillation)について(2019.12.29)
- FPGAでのDNN(Deep Neural Network)の整理(LUT-Netまとめ)(2019.12.15)
- LUT-NetのFPGAリソースについて(2019.12.08)
この記事へのコメントは終了しました。
コメント