FPGAのLUTで作るバイナリニューラルネットのアーキテクチャ考察
前回の続きの考察です。
まず、今やっているアプローチは既存FPGAでの実装都合観点からのアプローチであって、自由にLSIが設計できる状態でのトランジスタ効率を語っているわけではない点は最初に断っておきます。
まじめにFPGAでDNN(ディープニューラルネット)をやると、それだけで回路やメモリ帯域の大半を持って行けれてしまうので、もっとお気軽に既存のシステムの中で、余ってるロジックの片隅に入れ込める程度の分類器が組めると面白いなと言うのが当初の動機です。
現在、まだまだ試行錯誤中ですが、MNISTの認識がLUT 1260個(ZyboのXC7Z020で2%程度)で、84.81% まで来ており、単体ならXC7Z020で400MHzなどでも配置配線できていたりします。
ソースコードはいろいろ汚いですが随時githubには上げています。まだまだ、ネットワークの設計(結線)や、学習方法で山ほど考えるところが残っていますが、もうすこしやってみる価値がありそうな可能性は見えてきた気がします。
(2018/08/20追記: githubのプロジェクト名を変更して BinaryBrain としました。少し汎用性のあるライブラリに整理したいと思います。本ブログ実験時のコードは ブランチ https://github.com/ryuz/BinaryBrain/tree/prototype-20180820 に退避しております。)
もともとが、技術的思いつき(シーズ指向)でスタートしているので、システムアーキテクチャの観点での考察が殆どできていなかったので、少し整理していきたいと思います。
なお、今回も一旦、Learning は置いておいて Prediction に焦点を当てます。
(LUTも SRLC32E などを工夫すれば、テーブルを動的に書き換えるLUTも作れるので、高速Learning環境も作れるかもですが、それはまあ今後の話)。
(LUTも SRLC32E などを工夫すれば、テーブルを動的に書き換えるLUTも作れるので、高速Learning環境も作れるかもですが、それはまあ今後の話)。
まず考察にあたり、従来の普通のDNNをFPGAでやろうとしたらどうなるかを考えて見ます。今回参考にしているのが、O'REILLYの「ゼロから作るDeep Learning」本の3章のネットですが、全層接続で単精度乗算+sigmoidなどの計算で、784-50-100-10 のノード数での層構成になっています(導入の章であり、素直なネットなので手法のベンチマークには良いと思います。精度は93.52%)。
層間が全結線と言うこともあり、例えば、最初の784個の入力と、50個のニューロノードとの間の接続数は 784×50 = 3,920個もあり、全体では 45,200の接続があります。
この接続すべてに単精度実数の重みパラメータがあり、乗算が実施されます。45,200個の乗算器を静的に割り当てると言うのはFPGAだとまだ非現実的なので、必然的にもっと少ない個数の乗算器を割り当てて、そこに動的に重みパラメータを都度再ロードしながら実行することになります。
MNISTの場合、入力データは784画素ですので、1枚だけのPredictionを行う場合、画像データの供給よりも、パラメータのロードの方が遥かにデータ帯域を消費するということになります。
実際には再ロードの個数を減らすために、入力データをある程度溜めてから流す「バッチ処理」というテクニックがあるようですが、Prediction の場合、入力データを溜めてしまうとリアルタイム性を失いますので、例えばロボット制御の画像認識とか流行の自動運転のような分野ではバッチ処理は適用困難になります(CNNのように1枚の画像内での重みパラメータの再利用もありますが、トータルで見ると1フレームで使うパラメータはすべて再ロードという点では同じです)。
実際には再ロードの個数を減らすために、入力データをある程度溜めてから流す「バッチ処理」というテクニックがあるようですが、Prediction の場合、入力データを溜めてしまうとリアルタイム性を失いますので、例えばロボット制御の画像認識とか流行の自動運転のような分野ではバッチ処理は適用困難になります(CNNのように1枚の画像内での重みパラメータの再利用もありますが、トータルで見ると1フレームで使うパラメータはすべて再ロードという点では同じです)。
何より認識対象のデータの他にパラメータロードのためのデータ帯域が追加で必要になることが最大の課題です。これは、はじめからDNNやるつもりで設計したシステムではまだ良いのですが、例えば画像処理用のシステムに後から認識機能を足そうとしたときに、急に大きなパラメーター用のデータ帯域が必要になるので、それが機能拡張の足枷になりかねないことを意味します。
こういった観点から考えると、小さなロジックに静的にパラメータを割り付けて(再ロード不要で)動作できる識別器の可能性は応用範囲を広げてくれる可能性があります。
次にロジックの密度について考えておきます。先の例では単精度実数を用いていましたが、実際調べてみると既存のDNNに関しては、INT8程度までは縮退できる可能性を有しているようです(まあ、元の画像が8bitなので、有効数字的にそんなもんじゃない? という直感もありますが)。sigmoidなどはランプ関数などもっと軽いものがあるので一旦積和に注力してLUT換算で従来手法の演算密度を考察しておきます。
先だって、符号なし8bitの乗算をDSP(FPGAの乗算器)を使わずにLUTのみで合成させてみたところ70個の消費だったとTwitterに書いたのですが、符号付き8bitで a*b+c の演算をVivadoで合成させてみたところ符号付きが効いたのかLUT 69個の結果となりました。
一旦、この条件で、計算すると、先の45,200個の積和演算は、LUT換算だと 3,118,800個分ということになります。演算リソース量(情報密度とも違うし、回路の演算濃度ってなにか良い言葉無いのかな?)という観点で比較してみたいと思います。
先だって、符号なし8bitの乗算をDSP(FPGAの乗算器)を使わずにLUTのみで合成させてみたところ70個の消費だったとTwitterに書いたのですが、符号付き8bitで a*b+c の演算をVivadoで合成させてみたところ符号付きが効いたのかLUT 69個の結果となりました。
一旦、この条件で、計算すると、先の45,200個の積和演算は、LUT換算だと 3,118,800個分ということになります。演算リソース量(情報密度とも違うし、回路の演算濃度ってなにか良い言葉無いのかな?)という観点で比較してみたいと思います。
今回のLUT型2値DNNはLUT 1260個ですが、入力データを乱数で水増しして64回通して集計しています(実際16回ぐらいに減らしても認識率が数%落ちるだけでしたが)。LUT換算で 1260×64 = 80,640個分の演算になります。
- O'REILLY本の多値DNN : LUT換算 3,118,800個分の演算で、認識率 93.52%
- 今回のLUT型バイナリDNN : LUT換算 80,640個分の演算で、認識率 84.81%
というのが、現在時点の状況になります。
リソース量は圧倒しているので、そもそもリソース的に従来手法では実装不可能な分野に適用する場合にはメリットがあると思います。
あとは、
- 認識率を加味したときに費用対効果としてどうなのか?
- このやり方でオリジナルに近い認識率に迫れるのか?
- 迫れたとしてその際にもリソースの優位性を保てるのか?
などが今後の課題となりそうです。
再度ここで6入力LUTについて少し考察しておきます。昔は4入力LUT(16bitテーブル)が主流でしたが、現在は大規模FPGAの主力2社とも6入力LUT(64bitテーブル)が主流な様です。
(詳しい理由は知りませんが、LUTのトランジスタ数が増加して適用アプリケーションの変化があったり、ルーティングやクロックスキューなど技術観点で別のボトルネック要因がでてきたり、乗算器/SRAMや高速シリアルなどのハードマクロ部分との比率との按配など、いろいろあってのことだとなのだと思います。)
6入力ともなると64bitのテーブルを持ちますので、1入力あたり10bit以上の情報を割り当てていますので、これだけ見るとINT8乗算の係数より多い情報を1bitに割り振れるとも考えることが出来ます。
バイナリニューロンを考えた場合、入力数が6に固定されていることを除けば万能素子なので、十分に活用できるネットワークを考えることが出来れば、意外にいい線までいけるのではないかと思います。CNNのような構成もありだと思いますし、現状の多値DNNは多くの点で参考に出来ます。
バイナリニューロンを考えた場合、入力数が6に固定されていることを除けば万能素子なので、十分に活用できるネットワークを考えることが出来れば、意外にいい線までいけるのではないかと思います。CNNのような構成もありだと思いますし、現状の多値DNNは多くの点で参考に出来ます。
また、今回、入力を水増しすることで、静的なコンパクトな回路で認識率を上げていますが、例えば、画像認識の場合、高速度カメラ映像を使うと、露光が減って天然のノイズが乗る上に、当然フレーム数が増えるので、何もしなくても適用できる可能性もあるかと思っています。当サイトでは既にZybo上でIMX219(Raspberry Pi Camera V2)の1000fps動作実験が出来ていますので、これが活きてくる可能性もあります。
音響もデジタル化で、オーバーサンプリングでの1bit⊿ΣやD級アンプが発展しました。画像データも高速度撮影+バイナリニューラルネットで新しい世界が開ける可能性を感じています。
最後に現状のシステムを少しまとめておきます。
- 認識率はまだ実用性考える際に微妙
- 回路はLUTのみに閉じて高速&コンパクトに実装できそう
- 回路のレイテンシは数10サイクルと超リアルタイム
- 回路のスループットは1なので毎サイクル新データが入れられる(400M fpsとか)
- 回路の1動作では認識できないので、複数データの集計が必要
(データを水増すのか、オーバーサンプリングするのかはシステム次第) - ある意味高速すぎるので、演算回路を休ませないようにデータ入力できる入力ソースが何か疑問
そして最後が実用検討の際に結構難問な気がしています。
画像データをソースとする場合、MNISTのような28x28などというようなデータは早々無いので、カメラ画像を部分的に分解するなど例えばCNN的な発想も織り交ぜつつ、画像各部をさまざまな括りで縮退を行いながら投込んでいくことになる気がしますが、有意義な方法が確立できるかは謎です。
ストレージにあるビッグデータを一気に処理するとかの用途が多くのDNNの世間での使い方なのでしょうが、今回の当初の発想は、「エッジコンピューティングでリアルタイムに認識がしたい」が出発点なので、やはり外界からこのレベルのデータをリアルタイムに取得したいわけです。
エッジ端末には様々なセンサーがついています。例えば今回のネット程度なら、入力に求めるのは、数百Gbps程度であって、DDR3-SDRAMの帯域にも劣る世界で、水増しも含めれば今時のイメージセンサなら十分に持ち合わせている帯域ではあります。
エッジ端末には様々なセンサーがついています。例えば今回のネット程度なら、入力に求めるのは、数百Gbps程度であって、DDR3-SDRAMの帯域にも劣る世界で、水増しも含めれば今時のイメージセンサなら十分に持ち合わせている帯域ではあります。
要するに前処理が重要と思っていて、アナログ値を如何に情報の沢山のったバイナリに
落とすアーキを考えるかが重要な気がしています。
多値で扱う場合、ここも含めて機械学習でやるのでしょうが、今回2値特化なので、2値化時に情報が欠落してしまうと如何ともしがたくなるので、ここは引き続き悩みどころとなりそうです。
« FPGAアーキテクチャ上でのバイナリDNNについての考察 | トップページ | 続・FPGAのLUTで作るバイナリニューラルネットのアーキテクチャ考察 »
「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)
この記事へのコメントは終了しました。
« FPGAアーキテクチャ上でのバイナリDNNについての考察 | トップページ | 続・FPGAのLUTで作るバイナリニューラルネットのアーキテクチャ考察 »
コメント