« LUT-Netの力技での学習部分について | トップページ | 先が見え始めた LUT-Network について再整理(中間報告) »

2018年9月13日 (木)

少し見えてきたLUT-Netの可能性

前書き
 このところバイナリネットワーク(ディープラーニングの一種)にかかりきりですが、ようやく少し希望が見えてくると同時に、私の中でも自分がやろうとしていることがどういう位置づけにあるのか整理できて来ました。結論を先に書くと、
  • 「XNOR-Netの性能をターゲットがFPGAの場合限定で大きく超えられるかも」
  • 「Adversarial Exampleなどの攻撃に耐性がある可能性があるかも」
 の2点となります。
  当サイトの以前の実験で得られたのは、バイナリネットにおいて、深層学習のアルゴリズムではなく、単に学習データの入出力の真理値表に近づけるだけの力技のアルゴリズムでも、評価用の別のデータセットの正解率がちゃんと上がったという事実にあります。
 これは深層学習のアルゴリズム枠を外れた追加の最適化や、深層学習の弱点を別のアルゴリズムで補える可能性を示していると考えた次第です。そこで真理値表の扱いに強いFPGAをメインターゲットにさらに検討を進めようとしている次第です。
 
XNOR-Netを超える高性能なネット(ただしFPGA限定)の可能性について
 
 まず、昨今のバイナリネットの状況としては、こちらの「バイナリニューラルネットとハードウェアの関係」という資料がとても分かりやすかったので、勝手ながらリンクさせて頂きます。
 歴史としては、「Binary Connect」で、重みがバイナリ化され、「Binarized Neural Network」で、活性化層もバイナリ化され、さらに深いネットに対応するためにXNOR-Netが考案されてきたようです。
 これらは、CPU/GPUでも高速化されますが、FPGAの高位合成ツールによってFPGA上でも効率よく実行できるので、FPGAユーザーにとっては現在のトレンドでもあるようです。
 が、今回の私の試みは発想が逆で、CPU/GPU上で進化したネットをFPGAに持ってくるのではなく、初めからFPGAのアーキテクチャに対して、それをそのまま機械学習させてしまう事で効率をさらに上げようというものです。CPU/GPU用のノードは、FPGAに持ってくると複数のLUTの組み合わせに展開されるので、どうしても規模も速度もダウンしてしまいます。ならばいっその事「LUTに1対1で対応するネットを学習させれば桁違いに性能が上がるのでは?」というアイデアから出発しました。
 この考えを進めるにあたっては、
  • 「FPGAの6入力LUTのような入力数が制限された、疎行列としてモデル化する」
  • 「積和を基本とするネットではなく、最後はLUTテーブルを学習させる」
 という2点が重要になってきます。
 
 FPGAのLUTは1段でXORが学習できてしまうという点で、既存の積和型のニューロモデルよりも表現力があります。しかしながら、力技の学習では学習時間がNP困難問題(要するに規模が大きくなると計算が終わらない)になってしまうのですぐに限界に達してしまいます。
 そこで、既存のディープラーニングの誤差逆伝播による巨大でディープなネットを学習できるモデルの手を借りてある程度の学習を行いつつ、追加最適化ができる方法を見出そうと言うのがこれまでの取り組みの流れです。
 目下取り組んできたのが、FPGAのLUTに1対1で対応する6入力1出力のノードを一旦積和型のニューロに置き換えてモデル化しして、誤差逆伝播で学習させることが出来るようにするといものです。これは最近ようやくうまくいき、下記のような動作となりました。
 
3
 
 上記はMNISTの28x28入力を、1080-360-60 の3段1800個の少ノードで学習させたものですが、初めは、実数重みで誤差逆伝播で学習を行っており、概ね80%の認識に満たないところで学習が飽和しています。その段階で、FPGAのLUTと同じモデルにパラメーターコピーを行っております。コピーによりバイナリの入出力対応をテーブル化して受け継ぐのですが、さらにここから力技で学習を追加することで、85%程度まで、引き上げが出来ております。力技の学習では、積和モデルを無視して、LUTテーブルがとりうる値を全て候補に探索するので、1つのノードがさらに表現力を持つことが出来ます。
 そして学習結果はそのままFPGA用のRTLとして出力可能です(ただし、高位合成言語向け出力ではない点は、RTLを読めないユーザーがすぐには使えない点で弱点かもしれません。上位ドライバとセットで開発が必要です)。
 
 なお、この6入力のノードが1800個というのがどれぐらい小規模かというと、まず重みが1800×6=10,800個しかありません。通常の全結線の層だと、例えば28x28のNMISTの画像を10個に分類する場合、中間層を仮に50個、出力を10個ノードとした場合でも、28x28x50 + 50x10 = 39,700 ですので、全結線の重みパラメータの量は結構インパクトを感じます。
 加えて、LUTネットの1ノードは本当の意味でFPGAのLUT1個に置き換わりますが、通常のネットは、XNOR-Netであっても1つ1つのノードで「28x28のノードを全てXNOR演算して、ビットカウントする演算が必要」なので、想像するだけでもFPGA向けに高位するとそれなりに肥大化すると思われます(floatやINT8でやるのと比べればそれでも激減と思いますが)。
 実数で作った積和のモデルは、通常の実数ニューロにBatchNormalizationとBinarizeを付与したものになっております。
 ここで今回作成したネットを既にあるバイナリ系のネットと並べて整理したものが下記の表になります。
 
Lutnet_jp
 
 
 LUTをモデル化したネットでは接続が6個などの数に制限されるため、疎行列となります。また当然ながら入出力はバイナリとなるので、活性化はバイナリである必要があります。
 一般に疎行列はグラフとして扱いますので、CPU/GPUで性能を出すのが密行列に比べて難しくなります。しかしながらFPGAに持ち込めば、ほぼそのままRTL化できるので非常に高い性能が出せます。
 一方で、表で「?」としている部分はまだ検証できておらず、今後の取り組みで明らかになっていくと思われます。
 LUT-Netの特徴として、他のネットは高速化のために重みを真っ先にバイナリ化しているのに、ここが実数のままと言うのがあります。入力M個、出力N個のニューラルネットを作る場合、重み係数はM×N個あるので重みの削減はCPU/GPUでの高速化には非常に重要です。しかしながら重みのバイナリ化で深いネットの学習が難しくなっています。XNOR-NETではスケーリング係数の導入など、バイナリ化による偏りを可能な限り取り除く工夫がされているようです。LUT-Netではそもそも重みが実数なので、この点では有利なはずで、活性化のときのバランスが重要になると思われますが、ここも実数版の従来どおりのBatch Normalization が投入可能です。
 Binary Connect で、バイナリ化すると認識率が逆に上がったという事象があったようですが、バイナリ化は(複雑になりすぎたらペナルティーを与えると言う意味での)ある種の正則化なので過学習防止になりえる気がしますし、Batch Normalizationとあわせて(平均値/分散を揃える意味で)正規化でもあるので伝播精度の欠落防止などにも効果が期待できます。要するにバイナリ化しやすい方向にネットのバランスを取るのは、学習時の実数/バイナリ問わず重要なことであり、基本に忠実なネットほど予測用の実装時にバイナリ化しやすいことを意味すると想像しています。
 重みが実数であっても、活性化層がバイナリだと、入出力ともにバイナリとなります。ここで入力が6個などの制限のある疎行列だと、必然的に入出力の関係が64パターンしかないので、実数重みであってもコンパクトにテーブル化できてしまいます。
 ここで、さらに、LUTの場合、一般的なAffine演算(積和演算の塊)で表せる範囲以上の表現が可能です。
 非常に分かりやすい例を出すと、従来のニューラルネットのモデルでは2層以上ないと表現不可能なXOR(排他的論理和)が1段で記述可能です。ニューラルネットモデルの限界を突破して、さらに学習が出来る可能性が少しですが見えてきたように思います。
 そして今回は、LUTに模した積和ノードを作ったのですが、身も蓋もない言い方をすれば、活性化層がバイナリなら、どんなネットもLUT型に写し取れる可能性があります。
 入出力がバイナリならば、各層を個別に学習していけば、一回のサイズが小さいのでNPクラスのアルゴリズムでも何とかできる可能性があります。
 これらはまだ大きなネットで試せていないので、いろいろと仮説ではあるのですが、実際に逆伝播での学習が動き始めて、期待感が出てきたのはその通りと思います。
 
 
Adversarial Exampleなどの攻撃に耐性がある可能性について
 まず、Adversarial Examples が何者かと言うところですが、私も数日前に知ったレベルです。こちらの記事で知りました。
 なるほどすごいことを考える人がいるのだな。と思った反面すぐに考えたのが、「力技学習させたLUT-Netはそもそも勾配の逆伝播が出来ないので、この攻撃に耐性があるのではないか?」というものです。
 勾配が直接求まらない以上、攻撃を行うには一旦何らかの勾配計算の出来る模倣ネットを作る必要があります。
 しかしながら、そもそも力技学習は、学習原理が勾配法とは異なるので、それで特性が写し取れる理由が思いつかないと言うのが現状です(実験しないと分かりませんが)。
 もっとも、今回のように、一旦勾配法で学習した後に追加学習した場合、どの程度元の性質が消えうるのかは謎です。しかしながら、勾配法ではない方式を学習結果に追加で掛けることには最適化だけではない、新しい意義が生まれる可能性も残っていると考えておりますし、LUTアーキ特有の面白いアイデアではないかと思っております。
 
 

おまけ

 実験として、256個の入力を持ったXNOR-Netのノードを仮定して実験を行ってみました。
 256個のXNORを行って、結果をカウンティングして出力を作ります。
 RTLでそのような回路を書いて、Vivadoでxc7z020clg400-1用に合成したところ LUT使用数は 382個でした。 XNOR×3組 + 8bit 加算器を 256回まわしても良いですが、その場合は11個のLUTを86回使うので、946個換算になるので、纏めて合成した方が効率は良さそうです。ちなみにこれが256個並ぶと、それだけで LUT が382x256= 97,792個消費されます。
 LUT-Netで256個の入力を裁くには、43 - 8 - 1 の3層構造が最小で  52個のLUTから、必要に応じて増強していけます。  52/382 = 0.136 なので、XNOR-NETの 13.6%ぐらいの規模から必要な認識率に応じて調整レンジが取れることにあります。
 
 さらに悪ノリして、NMISTの28x28=784個の場合も合成してみました。XNOR-NETの1ノードは1569個のLUTになりました(実は256個のときはカウンティング合計のMSBだけ見ればよかったのでコンパクトに出来ていたかも)。XNOR3組+10bitカウンタ 262回利用で2882個相当なので、あまりおかしくはない結果です。
 この場合、隠れ層無しの1層構造で、NMISTに10個の出力をつけるだけ(つまり殆ど何も認識できない)で、15,690個のLUTが消費されます。これでは層を組んでいくとFPGAに入らないのでやっぱりマルチサイクルでやると 28,820個のLUTの実装効率になります。
 LUT-Netは記事の通り LUTがたった1,800個で既に 85% の認識率が出せています。
  28,820 / 1,800 = 16.01

 めざせ、XNOR-Net の 16倍効率のネット!  (とはならんだろうなぁ)

--------
 なお、本ブログのコードは https://github.com/ryuz/BinaryBrain にあります(随時更新中)。
 Windowsな人間なのでVC++用ですみません。そのうちgccとかも考えます。

« LUT-Netの力技での学習部分について | トップページ | 先が見え始めた LUT-Network について再整理(中間報告) »

FPGA」カテゴリの記事

Deep Learning」カテゴリの記事

コメント

この記事へのコメントは終了しました。

トラックバック


この記事へのトラックバック一覧です: 少し見えてきたLUT-Netの可能性:

« LUT-Netの力技での学習部分について | トップページ | 先が見え始めた LUT-Network について再整理(中間報告) »