2020年12月 3日 (木)

こんどは「はてなブログ」にお引越し

Markdownで技術記事が書きたいと思い Qrunch を使っていましたが、この度サービスが終了してしまいましたので、Markdownの 使えるはてなブログさんへ活動の場を移動ししました。


Qrunch にあった古い記事は

https://github.com/ryuz/qrunch_blog

に避難させております。

必要な方はこちらにアクセスください。

なお、あくまで技術ブログが彷徨ってるだけなので、駄文は引き続きこちらに書く可能性もあります(といいつつTwitterに駄文書く率が高いですが)。

Markdown だけなら、github でもいいのですが、Markdown は方言も多く、数式などはやはり最終の表示をプレビューしながら書きたいものです。

UIとしてはQiitaが秀逸なのですが、まとまる前からダラダラと過程や仮説を書いて公開していくスタイルの当ブログのやり方だと永遠に「公開する」ボタンが押せない記事が下書きに積まれ続けそうなので、やはり「ブログ」というスタイルはそれはそれで大切ですね。

 

2020年5月10日 (日)

Qrunchについて

最近、Qrunch に技術系記事書くことが増えてきております。

理由は 「Markdown で書けて楽ちんだから」です。

Qiita も便利なのですが、ある程度裏の取れたきちんとした技術記事以外書きずらいというのもあり、LUT-Net のような怪しげな技術は主にブログに書いていたのですが、Qrunchならブログ程度のものがMarkdownで書けてしまうのでそちらに偏り中です。

完全移行するつもりは当分ないですが、今回ついにLUT-NetネタもQrunchに書き始めてしまったので、こちらのブログに来られた方、よろしければ Qrunch の方も覗いてください。

2020年3月23日 (月)

Deep Learning の開発フロー

当方FPGAで遊ぶために少し齧っているレベルで、この分野はの専門でも何でもないのですが、自分用の整理も含めて少しいつもより上流の視点で簡単な資料にしてみましたので置いておきます。(将来の勉強会などでプレゼン書く時の素材用という意味も含めて)。

SlideShareに置いております。

PowerPiontのデータは ダウンロード - deep_learning_development_flow.pptx

(画像処理分野でしかも認識器に偏った記述になってますがご容赦ください)

 

私はLUT-Networkの開発で初めてDeep Learningに触れたわけですが、従来のアルゴリズムありきでそれをなんらかの計算機(FPGA含む)に実装していくやりかたと、Deep Learning ではどこがどう違うのかということはやはり整理しながら理解していきたいところではあります。

やはりデータトリブンなところを前提に、「欲しいものを手に入れるために用意しなければいけないもの」、「元から持っている人間の知見を入れ込むにはどうすればいいのか?」と言ったあたりが大きく異なるようには思います。

どうしても実用的な使い方を考えてみようとすると、もう少し幅を広げて取り扱っていく必要があり、また違ったスキルが必要になってくるようには思います。

 

 

2020年3月 9日 (月)

LUT-Networkの蒸留とMobileNet風構成とセマンティックセグメンテーション

はじめに

従来のパーセプトロンモデルを使った学習ではなく、回路そのものを微分してFPGAを直接学習してしまおうという当サイトオリジナルのディープラーニングLUT-Networkですが、ここのところ深いネットを学習させるために蒸留(Knowledge Distillation)に取り組んでいました。

その一つの成果として、MNISTデータを使ったセマンティックセグメンテーション(もどき)を試してみたのでブログに記録しておきます。

 

まずは先に結果

まず先に最新の結果を記載いたします。MNISTベースの画像を入力して、それぞれの数字領域を色塗りするセマンティックセグメンテーション(もどき)を学習させてみました。

入力画像
Mnist_test_640x480

 

出力画像

上記の入力画像をもとに Verilog のRTLシミュレーションで得た結果画像が以下です。
Result

 

FPGAリソース

下記が実際にRTLを合成した場合のリソース量です。DNN部のみですが、畳み込みの為のラインバッファなどの制御回路のLUTも含んでいます。

Resource

以上のように、ZYBO Z7-20 のリソースを半分も使うことなく、また外部メモリを使うこともなく、上に記載のリソースのみでスループット1のDNN回路が出来上がりました。MobileNet風の接続の導入で配線がスリムになったことで合成時のルーティングなどでの問題もまったく発生していません。
一応、学習済みのソースをここに置いておきます。

ダウンロード - mnist_seg.zip

 

本回路はビデオ伝送路にラインバッファ分の遅延のみで、ビデオ信号の経路にフィルタとして挿入可能です。またLUT-NetはLUT1段で1層ですので非常に高クロックで合成可能で、例えば300MHz程度で合成も可能です。ピクセルクロック300MHzといえば4k画像30fpsに相当しますといえば想像しやすいのではないかと思います。

細かい部分はまだいろいろチューニング余地がありますが、まずはフレーム単位でメモリに溜めないと演算できないGPUに対してリソース量もリアルタイム性も非常に高いFPGAでのAIの可能性が少しだけ広がったのではないかと思います。

 

ネットワーク構成

ちなみにFPGAリソースこそ少ないですが、depthwise CNV と pointwise CNV で合わせて57層という結構深いネットになっています。
一応、出力させたネット構造のみテキストファイルで置いておきます。

ベースモデル:ダウンロード - training_model.txt
蒸留後のモデル:ダウンロード - lutnet_model.txt

 

MobileNet風の構成と蒸留(Distillation)の小規模実験

今回の進展にあたり、大きな変化となったのが MobileNet v1 風の考え方の取り込みと、蒸留(Distillation)という考え方です。
まず、セマンティックセグメンテーション風の色塗りをやる前に行った、普通のMNITのクラス分類で適用したネットワークの構成が以下です。

Mnist99_net

MobileNet v1 を参考に depthwise/pointwiseの畳み込み層を準備しています。その際にLUT-Net特有の改善としてdepthwise層の出力チャネルを入力チャネルより多くし、同じチャネルを処理するノードを複数割り当てています(今回は各4個づつ)。
全結線のノードと違い、深さ方向に各1個だと1チャネルの属性を十分捉えらてないため、異なる成分をとらえることが可能になるように多様性を持たせています。なお、多様化した結果、結局使われなかったノードは後の蒸留時に消滅しますのでここは安心して増やすことが可能です。

ちなみにこのMobileNet風の構成は蒸留することなくランダム結線のままでも比較的効率よく学習してくれる模様で、以下がその学習時のログです。

Mobile_lut_net_train_graph

63epoch目で 99.08% の認識率まで確認しています。
特徴的なのが、train と test でほとんど挙動に差がなく、LUT-Net の汎化性能に関してはパーセプトロン型のDNN同等以上の可能性も感じています。

 

蒸留の効果確認

ちなみに先の例では蒸留の有無にかかわらず99%超えてしまい、効果がよくわからないのでもう少し回路を小さくして実験しました。
その際の回路構成が下記です。
Mobile_lut_net_little

LUT 3k個程度の小さな回路ですが、飽和するまで回したところ

蒸留した場合:98.42%
ランダム結線:97.06%

となり、蒸留によって結線の最適化をした方で若干の改善が見られました。

 

まとめ

LUT-Netの開発もしばらく停滞していた感もありましたが、MobileNet構成の実験と、蒸留の可能性が見えてきたことで適用可能性が一気に増えてきたように思います。
特に全結線層を使えばバイナリネットであっても、比較的深い層も通常のDNN同様に学習できることが見え初めてきましたのでそこからLUT-Netに持ち込めるというのは大きな成果に思います。
またその際もすべて全結線層にするのではなく、depthwise層は初めからLUT-Netにしていますので比較的相性良く組み合わせる手が見えてきたと思っております。

引き続き、もっといろいろな応用ができればと思う次第です。
今回のセグメンテーションは、Pooling層無しで行っており、すべてのノードが100%演算している反面、フィルタの段数分(ラインバッファの範囲)でしか判別ができません。よって小さな範囲を見て判定できるアプリにしか使えませんが、それでも小さい範囲で認識が完結する欠陥検知や異物検知系の見分け補助とか、線画やモノクロ写真の色付けとか、がリアルタイムでできないものか、とか、いろいろとワクワクする応用例は思いつくわけです(実用になるかは別として)。

広い領域を見るにはU-Net的なことをする必要が出てきますが、その場合は一度中間結果をメモリに入れないといけないのと、PoolingするとLUT-Netの場合演算器の利用効率が下がるので、やるなら並列して1frame前の画像を通常型の演算器でやって、最新フレームの入力に追加チャネルとして入れるのがいいのかなと思っていたりもします。まだまだ先が長いですのでのんびり取り組んで行ければと思います。

 

 


追記(2020/03/13)

セマンティックセグメンテーションについて動画を作りましたので置いておきます。
全体の合成でも配線混雑やタイミング収束などで苦しむことは全くなく、あっさり合成出来きました。MobileNetの効果は大きいです。
1msの遅延で1000fpsがAI処理付きでカメラからOLEDに通り抜けており、OLEDが画面がまるでガラスのように向こう側が遅延なくAI重畳されて映し出されています。
AI眼鏡の可能性の提示と、電脳コイルの世界への入り口となること祈りつつ。

 

 

2019年12月29日 (日)

LUT-Networkの蒸留(Distillation)について

今日は、Networkの蒸留(Distillation)について考察してみたいと思います。

LUT-Networkに限らないのですが、その課題に学習時のGPUのメモリの不足と、学習時間の問題があります。


例えばMobileNetという軽量なネットワークがあります。これは畳み込み層をpointwiseとdepthwiseに分けて行うことで係数の数を大幅に削減しています。
軽量にすると学習時も計算量も減るように思ってしまいますが、実際には処理を分割したことで層が増えてしまい、逆にGPUの消費メモリが増え、学習時のメモリへの読み書きも増えてしまいます。

この延長で、超SparseであるLUT-Netは大規模な学習が非常に困難です。そこで、大規模な学習がしやすいネットワークで学習してから、メモリに収まる範囲で少しづつLUT-Networkに写し取っていくというというアイデアを考えています。
これを蒸留(Distillation)と呼ぶそうです。

現在、取り組もうとしている流れが以下の図です。

 

Distillation

 

まず、一般的な畳み込み(Convotution)ネットワークの畳み込み層をバイナリ化する場合、ReLUなどのActivation層を2値化を行うBinary-Activation層に置き換えることになります。この時、2値化の手前で BatchNormalizationを行うのが効果的です。

BatchNormalizationは通常 Inferrence時には単なるスケーリングのみとなります。スケーリングのみであるため、2値化と組み合わせる場合、2値化の閾値自体をずらしてやればスケーリングも不要となります。

しかしながら、ここで前提として計算の中間結果が非バイナリであることが求められます。GPUを用いる場合、GPU内の内部演算が一時的に多ビットになることは特にデメリットはありません。しかしながらFPGA化する場合、そのままリソース規模に効いてくるのでこれは致命的です。
また、画素サイズ分のスケーリング係数が発生するので規模の点でも非常に厳しくなります。

そこで、LUT-Networkでは、当初より BatchNormalizationとBinary-Activationを畳み込み処理に取り込んでいます。これは工夫したというより、こうするしかLUT-Net は成立しないので、特に気にすることなく当初からこうしていたわけですが、LUT-Netの特徴の一つでもあります。
一般的な畳み込み(Convotution)は、効率化のためにGPUなどで一括で計算されますが、処理量やメモリを増やして良ければ、Loweringを行い、im2col と col2im の処理に挟まれる形でDenseAffine計算に分解することができます。

Loweringを行うと、学習時のメモリ消費や計算時間は増えますが、畳み込みの中にDenseAffine以外の処理が入れ込めます。

今回考えているのは、従来のネットワークに、LUT-Networkで行っているこれらの仕組みのみを適用して学習させ、学習後に蒸留して取り込もうというアイデアです。

蒸留は、今のところ

  • 元のDenseAffineの重み順で結線すると効果的
  • 元のDenseAffineの結線数が少ないと模倣しやすい(おそらくMobileNetは効果的)

などが、見えており、もうひと頑張りといったところです。

なお、今回は蒸留を目的に従来のネットワークを変形して学習させようとしていますが、おそらくこの変形は蒸留することなくそのままFPGAにしても効果的ではないかと考えています。

 

DenseAffine + BatchNormalization + Binary-Activation はInferrence時に XNOR-Net のような構造にできるので、そのままHLSなどで合成すれば効果的にFPGA化できる可能性があります。

 

先日の記事で、他のバイナリネットワークに対するLUT-Networkのリソース規模の大雑把な比較を行っていますが、その際に前提としてLUT-Networkに対して行っている上記のような技法を適用しているのを前提としていた部分がありました。

またXNOR-Netについてはかなり概算が入っていたので、実際にいくつか合成実験も行ってみました。
私自身XNOR-Netは試したことがないので理解不十分かもしれませんが、理解の範囲で実験しています。


Xnornet_20191229212001

思っていたよりXNORネットはFPGA化において高効率に思います。

一方で全結線という点ではNに対してO(N log N)で規模増大する可能性を有しているのと、従来のパーセプトロンモデル以上のことはできない(単段ではXORが解けない)など、LUT-Netに比べて非効率な部分はあるかと思いますが、如何せん、PyTorchなどの既存のプラットフォームで学習できる可能性がある点で、手が付けやすいのは事実かと思います。

LUT-Net が一般的なネットと遠いので、なかなか蒸留できる接点を作っていくのが難しいのですが、FPGA化時の高効率化のためのポイントを押さえていけば、その中間的なところも組み立てていけそうな気もしますし、それ自体もいろいろと面白い検討ができそうな気がしています。

2019年12月15日 (日)

FPGAでのDNN(Deep Neural Network)の整理(LUT-Netまとめ)

はじめに

 現在DNN(Deep Neural Network)の実装において、FPGAの活用はしばし議論の対象になっています。もちろんDNN分野全体からするとニッチな部類に入るとは考えますが、FPGAベンダーはここに非常に力を入れており、作成したネットワークのデプロイ先としてFPGAが選択しやすくなるような各種のソリューションが用意され始めており、日々進化しています。
 ここでのFPGAのメリットは、低消費電力であったり、コストであったりします。DNNの実行にはクラウドであっても電力というランニングコストは馬鹿になりませんし、エッジコンピューティング、特にバッテリー駆動のモバイル分野においては電力は極めて重要です。またイニシャルコストの重要性はどちらも同じでしょう。

 ここでFPGAベンダーはこぞって、「GPUと同じように開発できます」をキャッチフレーズに、GPUを使って研究開発をしている多くのAI技術者を取り込むソリューションの開発に力を入れています。学習(Training)自体はまだまだGPUの力を借りることが必須ですので、仕上がったネットワークを推論(Inference)専用に最適化してデプロイするときにGPUと同じように扱えるメリットは非常に大きいのです。

 一方で、これではFPGAにGPUと同じ計算を少し効率的にやらせているに過ぎないことになります。FPGAの面白さは「GPUと同じことが効率よくできる」だけではなく、「FPGAでないとできない」ことができることにあると私は考えます。
 ここ1年程、そのような観点でFPGAでのDNNに取り組んできましたので、ここで少し整理しておきたいと思います。


DNNをFPGAに実装する2つのアプローチ

 下記は、私の考えるDNNをFPGAに実装する際の2つのアプローチのイメージ図です。
 「GPUと同じように使う」のが右側、当サイトの主張する「FPGAらしく使う」のが左側です。
 ネットワークの探索や試行錯誤、学習自体はGPU上で行い、それをFPGAにインプリメントするという流れは同じです。
 ただし、おそらく左のアプローチは学習フェーズで右側以上にFPGAを意識しておく必要があり、より高い次元でのシステム最適化スキルが必要となります。開発も辛うじてHSLが使える程度で、本格的にやるとRTLがまだまだ必要な領域になります。

Dnnfpga

 

GPUのように使うという事

 先に図の右側のソフトウェア的なアプローチ、すなわち「GPU的に使う」場合のアプローチについて述べます。

 この場合、まずソフトウェアでのネットワーク記述ありきの状態で、これをFPGAを使ってどうアクセラレートするかという話になります。
 ですので使い方としてとてもGPUと似てきます。
 しかしながらGPUが汎用計算機であり、INT1からFP64まですべてに対応したエンジンが固定数だけ搭載されているのに対して、FPGAでは本当に必要な演算のみを必要な個数だけ構成することができます。特にINT8以下の領域などを狙った実装などではGPUに対して優位性が出しやすくなってきます。

 その一方で、システムのデータフロー自体はソフトウェア的であり、電力やコスト以外でFPGAならではの効果を付与するのは難しくなってきます。

 

FPGAらしさを活かす試み

 次に先の図の左側のハードウェア的なアプローチ、すなわちFPGAをFPGAらしく、得られたネットワークを計算する専用の回路、すなわちネットワーク構造そのものを計算構造としてインプリメントしてしまおうという試みについてです。

 こうなると既存のソフトウェアのデータフローはいったん置いておいて、「ニューラルネットワークを計算する計算機アーキテクチャをゼロベースで新規に考える」というところが出発点になりますので、大変な反面、とてもたくさん新しいことに取り組む余地が生まれてくると考えています。

 最大の利点は、低遅延やリアルタイム性だと考えます。入力に対して「計算」以上のことは何も行わずに出力に直結可能ですので、理屈上最短の遅延で結果を出力することができますし、計算以外ではメモリ転送用の回路などのリソースも不要になります。一方で、メモリを介さないため演算器は常にカメラやLCDなど外部機器と同期して計算できることも求められます。
 メモリと異なり、計算が追い付かない場合にカメラに対してready信号を下げて「ちょっと待ってくれ」といってもカメラは待ってくれません。このような計算機の外にあるデバイスとの連携しながら計算することこそがエッジコンピューティングの醍醐味であり、FPGAの得意とする領域と考えます。実際にFPGAが得意とする画像処理の中にはこのような仕組みの中で実装されているものも多数あります。今後ロボティクスなどとの融合でも一層重要になると考えます。その枠組みにそのままDNNを入れてしまうというのは「FPGAらしさ」を活かすための第一歩の取り組みかと考えています。

 

 

FPGAらしさを活かす為のテクニック

 ここでFPGAらしさを活かすのに有効な取り組みを考えてみたいと思います。これらは現在取り組み中のBinaryBrainにて順次実験中の内容です。

 FPGAに搭載されているリソースの量は決まっており、上げられる周波数もあらかじめ決まっていますので、時間当たりに割り当てできる回路リソースの上限はどのような手法をとっても大きくは変わりません。そうした「FPGAらしい使い方」を目指す中で、スループットを1サイクル1データを維持したいといったエッジコンピューティングならではの要件も出てきます。
 そこで、DMAなどの演算に使わない回路リソースを減らしたり、FPGAのリソースを有効利用できる演算方式を使った学習を行ったり、演算器を休まず稼働させるアーキテクチャを考えたりして、更なる付加価値性能を引き出すテクニックを考えていくことになります。

 

量子化(Quantization)

 量子化はあらゆる場面で役立ちます。単純に演算bit数が半分になれば回路規模は半分になりますので量子化の効果は大きいです。この方法をデータが1bitになるまで適用したものがバイナリネットワークとなります。そしてネットワークのバイナリ化はFPGAの性能を引き出すうえでは最もパワフルな手法の一つであります。
 DNNで最も演算量が多いのは乗算となりますが、重み(Weight)と活性化(Activation)のどちらか一方をバイナリ化すれば乗算が加算に置き換わり、両方をバイナリ化するとXNOR演算に置き換わります。

 しかしここで注意点があります。FPGAの場合、乗算は乗算器マクロを使うのに対して、加算やXNORは通常LUTを使うのでリソースバランス的に必ずしもメリットがないケースもあります。ハードウェアマクロとして持つ乗算機は数は変わらないので使わないともったいないという話にもなります。
 また、XNOR-Netなど乗算部をXNORに置き換えたものであっても、そのあとの加算(bitカウンティング)は複数bitで行う必要があるという点があります。例えば256個の接続がある場合、Binary Activation を行うまでの加算は最終的に8bitの出力が求められます。ソフトウェア的には積和演算のループでよいのですが、計算構造として空間展開すると特に加算部分がやや大きな加算器ツリーを構成することになってくるのでここは注意点です。

Sparse化/枝刈り(Pruning)

 私は、ニューラルネットワークのSparse化がGPUに比べてFPGAに特に効果が高い手法ではないかなと考えております。N個の入力にM個の出力を行う全線接続層(fully connected layer)を考えた場合、N×M の積和演算が発生し、バイナリ化しても内部では log2(N)のbit数の計算が求められます。
 したがって、接続数Nを減少させることができれば計算量は減少します。もともとDropoutなどの技法が通用する背景には学習させるときに必要な自由度確保のための接続数と、最後に本当に必要な接続数の乖離にあると思われますので、学習後に枝刈りが成立するのはある程度自然なことなのかと思います。
 接続数を抑えるという観点で MobileNet などのアプローチも有効である可能性は高いと思われます。

 しかしながら、ソフトウェア的アプローチを行う場合、しばしば「行列乗算のアクセラレータを作ってこれを共有演算器として使う」という事が行われます。その場合演算の対象が枝刈りなどで疎行列(Sparse Matrix)になったからと言って特別な仕組みを入れない限り「係数を0にしてそのまま計算した方が速い」ということになります。
 この点についてネットワーク構造をそのまま回路構造に反映させる手法においては、コストゼロでSparse化の恩恵に預かることができます。

 また、枝刈りとは異なるアプローチで、初めからSparse化して学習させるという点でFPFAでのSparse化の究極形が当サイトの主張するLUT-Networkだと考えております。LUT-Networkでは接続数を4や6などに固定して学習させることでFPGAのLUT構造そのものに学習結果を対応付けさせるので高効率にインプリメントが可能です(究極的には2に固定してゲートレベルの回路を学習で生成する可能性も秘めています)。

 

パーセプトロンよりFPGAに適したモデルの適用

 これもLUT-Network で主張するところであり、LUTで計算可能な範囲を効率するモデルとしてStochastic-LUTという構造を提案しています。パーセプトロンのモデルが複数層無いとXORが解けないのは有名な話ですがLUTは1層でXORが解けます。ですのでLUTの表現能力を活かせる学習の為にはパーセプトロンのモデルでは不足するわけです。
 Stochastic-LUTでは、各入力を0/1ではなく「1である確率」として扱い、LUTの値も「テーブルに1が格納されている確率」とし、「出力が1になる確率」を求める演算となります。一定条件下でこの演算はStochastic演算としてそのままバイナリ回路を学習できますし、そうでない場合でも演算モデル自体がLUTを汎用に学習させるのに使えることが見えてきました。
 このようにStochastic演算を考えていた時に見つけた計算モデルですが、計算式としては N次元の線形補間であり、バイリニア→トリリニア→ を4次や6次に拡張したモデルと等価です。
 多次元を絵にするのは難しいので簡単のために2入力LUTとして、XORを学習した場合を図にすると以下のようになります。
Stochastic_lut_xor
 ルックアップテーブル値で保持する内部の状態はXORも表現可能であり、これはそのまま誤差逆伝搬により学習され様々な形に変形可能です。

 つまるところDNNは、なにも積和演算器を中心としたCPU/GPUに合わせて学習する必然性はなく、微分可能な演算式であれば様々なモデルが学習可能です。FPGAなどを考える場合、先入観にとらわれずに、そのアーキテクチャゲートレベルで見たもっとも演算効率の良いモデルで学習するということは十分成り立つ話なのです。このような考え方は、そのデバイスのリソースの有効利用をして性能向上を図るうえで十分に効果的だと考えています。

オーバーサンプリングによるバイナリ変調(Oversampling Binary Modulation)

 当サイトの主張する第二の技術としてバイナリ変調に触れておきます。バイナリ化は回路削減に大きな効果がありますが、認識精度を低下させる要因でもあります。
 XNOR-Netなど、初段のいくつかの層は多値で扱うというアプローチも多いようですが、当サイトではフルバイナリに挑戦しています。

 一般に、回路効率を上げる方法として「係数を変えて回路を再利用する」というのがよくあるソフトウェア的なアプローチです。汎用的な行列演算エンジンを作っておいて、そこに次々と新しい係数+データのセットを投入することで1つの演算器を何度も再利用し、計算効率を上げます。
 ここでハードウェア的なアプローチとして「係数を変えずに回路を再利用する」というテクニックでアプローチしているのがバイナリ変調です。回路は同一のバイナリネットワークのまま、そこに投入するデータの方をオーバーサンプリングして複数の認識結果を得て再統合することで認識率を上げます。リアルタイムでのデータ水増し(Dynamic data augmentation)ともいえるかと思います。
 このテクニックはリアルタイム性の増加ともとても相性が良く、bit数を増やすという空間方向の演算拡張に対して、時間軸にデータを拡張しています。

 CNNが空間方向の係数の再利用であれば、この方法は時間方向の係数の再利用と言えるかと思います。

 

蒸留(Knowledge Distillation)

 これはまだまだこれからの取り組みなのですが、蒸留の技術は非常に重要だと考えます。というのもバイナリネットワークは深いネットワークを学習するのがまだまだ難しいからです。これはネットワークの構造的な問題と、学習時の演算リソースの両方の問題があります。
 そういった中で、一旦、従来型の方式で学習した結果を参考にFPGA向きの回路に結果を反映させていくという手法は今後重要になると考えます。

 蒸留については現在、全線接続されたバイナリネットで学習して、全線接続層を複数のSparse層に蒸留して写し取る実験を行っているところです。成果が出ればまたブログに書きたいと思います。

(2020/03/11追記:ある程度蒸留が効果を出し始めました

ストキャスティック演算(Stochastic Operation)

 量子化されたネットに、バイナリ変調のような時間軸拡張されたデータを扱う場合、これはとても面白い考え方だと思っております。
 実際量子化されたデータを確率的に扱うと、確率共鳴のように本来切り捨てられたはずの量子化単位以下の情報が浮かび上がってきます。これらに対する演算を確率値を確率値のまま扱うことができれば幅が広がりそうです。バイナリに関する扱いであれば、ストキャスティック演算は実装上は乗算機が単なるANDゲートになるなど非常に効率的です。
 実際、MNISTの学習ぐらいならそこそこまでうまくいくようです。まだまだ課題が多いのですが、リアルタイムイな処理系の中に信号処理として入れ込む場合、連続時間の中で様々な角度で信号を見ていくことができる例だと思っています。

 

おわりに

 今回、少しFPGAで行うDNN全般の視点からLUT-Netの位置づけを見直してみました。
 こうしてみると、LUT-Netに限定する必要なく、FPGAでDNNをやる場合に重要になる技術がある程度整理して見えてきますし、FPGAでDNNをやる新しいメリットを探索する場合の手掛かりになる部分も見えてくるのではないかと思います。

 「FPGAでDNNをやろう!」といったときに、「VitisやSDxでDNNをFPGA化して終わり」ではなく、もっともっとFPGAらしい面白い使い方を探索してみる余地があるのではないかと思っております。
 AIの時代もFPGAが活躍して、くれると嬉しいなと思います。計算機アーキテクチャを考えるということは引き続きとても楽しいことであってほしいと思います。

 LUT-Netの方も、まだまだ取り組み途中で、やることはたくさん残っていますが、引き続き、無理のない範囲で楽しくやっていきたいと思います。引き続きよろしくお願いいたします。

 

2019年12月 8日 (日)

LUT-NetのFPGAリソースについて

久しく作業が止まっていましたが、今日はLUT-Netと従来のネットワークとのFPGA化したときのリソース規模の違いを俯瞰しておきたいと思います。

あらかじめ断っておきますが、ここで行う比較は認識率が異なるので公平な比較ではありません。通常のNN(Neural Network)は、まずやりたいことができる認識率を確保して、その後に、「それをいかにして速く小さくインプリメントするか?」が命題となります。

一方で、LUT-Net は初めからFPGA内で使えるリソースとハードリアルタイムな時間要件を先に決めてから、「そのリソース範囲でどこまで認識率が上がるか?」というアプローチをとっています。したがってそもそも土台が違うので一概に比較できません。

しかしながら、LUT-Net がどういうオーダーでリソース追求型のネットワークであるかの規模間を可視化するうえで役立つと考えますので、このような比較を載せておきます。

まず、先にLUT-Netでの畳み込みによる32x32サイズの画像分類に用いているネットワークの概算が下記です。

Lutnet

トータルとして、LUT数 153k, BRAM21個 のみですので、既存のFPGAに入れ込むことが可能です。
特徴として、スループットが1であり、1cycle毎に1認識の結果を出力可能です。つまり画像処理において、FPGAの動作周波数=カメラピクセルクロックとすれば、リアルタイムにすべての画素一の認識が完了します。VGA程度であれば1000fps(1kHz)動作も可能であり、認識処理のリアルタイム活用が可能です。

 

次に、この1cycle毎に1認識の性能を、通常の INT8 の CNN などで、同じ構造のネットワークを組んだらどうなるかの試算です。


Cnn

基本的にConv(畳み込み)もFC(全結合層)も、行列演算ですので、N×M個の乗算機が必要になります。そしてそれらを積算するのに接続数に比例する加算器が必要となります。ですので、計算上は、現存するどんなFPGAにも入りきれない、超巨大なリソース規模になります。

 

 

次にXNOR-Netの場合です。XNOR-Netは接続も重みもバイナリなので、リソースを大きく削減してくれます。

Xnornet

しかしながら、基本的に 乗算機がXOR演算となり、各種演算が INT8 から 1bit 化しただけなので、オーダー的には各演算が 1/8 になった程度の効果しか得られません。

 

もちろんスループット1なんて考えなければこんなことにはならないわけですが、それでもFPGAを使うメリットとしてはこの領域が必要な信号処理は多いわけで、そういったケースにAI的な適用ができれば非常に面白いのではないかと思う次第です。

 

2019年9月 2日 (月)

MNIST認識のリアルタイム動作環境更新

先日MNIST環境強化したのですがTwitterに書き込んでそのままだったので今更ながら更新しておきます。

今回は

  • Data Augmentation により、若干のスケール/回転/併進/ネガポジ耐性を付与
  • 数字部分かを判定する2クラス分類器を追加し、判定できない箇所の判定を抑制
  • LPF(ローパスフィルタ)として、1-TAPのIIRを追加(exponential smoothingが可能)

の3点が変更点となります。

 

Mnist_ar

 

これがシミュレーションの結果です。上半分が入力データで、下半分が検出結果を重畳したものです。

色は抵抗のカラーコードでして

黒:0 茶:1 赤:2 橙:3 黄:4 緑:5 青:6 紫:7 灰:8 白:9 となっています。

Sim_result

 

合成後の回路規模です。システム全体の規模となります。

Fpga_result

こんな感じでモノクロ反転した文字も認識しています。

おかげで、手で書いた文字もまあまあ行けました。

 Photo_20190902215501

 

ローパスフィルタは下の図のような感じです。入力と出力の間には遅延素子はなく、あくまで過去のデータも加えて結果を作るというだけで、本質的な点でリアルタイムが可能なデータパスであることが重要です。

なお、1000fps駆動なのでフレーム間の連続性も高く、過去の結果も活用することで認識精度の向上が可能です。

ただし画像の場合は音声などの1次元のデータと異なり、1タップのフィルタを組むのに画像1フレーム分のメモリが必要なところが課題です。

Iir

で、シミュレーションだと、数%程度認識率が上がるのですが、90%越えたあたりで数%変わっても見た目は良くわからないですね。

Lpf

この実物が見たい方は是非ICCE BERLIN 2019にお越しください(私は行けませんが)。

 

なお、現在はさらにDVI出力も付与しております。

Dsc_1204

 

余談ですが、認識結果ではなく画像の方にLPFを掛けると1000fpsの画像を60fpsのモニタに出すときに美しく出来ます。

OLEDなどの1000fpsの表示装置だと人間の目がLPFの役目を果たしてくれるのですが、LCDモニタの場合、そのまま間引いて表示すると露光時間不足でザラザラになってしまうので。

Lpf_dvi

ただしこれもメモリを消費するので、使い方は限定的ですね。

 

ちなみに今、これらの学習を行う BinaryBrain の Python 対応を developブランチで進めております。

まだまだ掛かりそうですが、頑張ります。

 

<追記 2019/09/06>

そういえば最新のリソース状況とかUPできていなかったので追加しておきます。

あくまで合成まで確認できているネットの中での認識率です。ソフトのみの実験とかだともう少しいけてます。

Lutnetwork_resource

ICCE BERLIN 2019にてLUT-Network発表

引き続きのアナウンスとなりますが、ICCE BERLIN 2019 にて LUT-Network を発表頂きます。

例によって私は参加できないのですが、こちらは私も名前を入れていただいております。

 

Sunday, September 8 17:05 - 18:55  の Enabling CE Technologies での発表となります。

上記Webから論文もアクセス可能です。

 

現地には@FIssiki 様作成のデモ機の展示も予定しております。

私、殆ど何もしていないのに、あれよあれよと話が進み、このような場で機会を頂きましたこと、改めて御礼申し上げます。

 

SWEST21にてLUT-Networkを取り上げていただきます。

すっかりブログがご無沙汰になっておりました。

2019年9月5日(木)〜6日(金) の日程にて開催されるSWEST21の中で、LUT-Networkを取りあげて頂いております。

私は参加できずに大変心苦しいのですが、9/6(金) 14:10~15:20 セッションs5bとなりますので、この場をお借りしてお知らせさせていただきます。

心から御礼申し上げます。

«「夏のAI EdgeハードウェアMeetup in 福岡」でお話させて頂きます