LUT-Netの力技での学習部分について
ここまでまだ十分に実験が進んでいないにもかかわらず期待と憶測だけで記事を進めてきました。
狸の皮算用になるかもしれませんが、まあサンデープログラマが趣味でやってることなので大目に見てください。
プロの研究者の方々は、成果が出るまでしっかり実験して、成果が出て初めて論文にして、査読を受けてやっと世の中に発表されるわけですので本当に頭が下がります。
が、うまくいっても、いかなくても、こういう試みをリアルタイムで発信していくのもウォッチしてくださる方がいるととても嬉しいものです。
さて、前置きはこれぐらいにして、今まで深く説明してこなかった「力技の学習」部分を解説しておきたいと思います。
力技(Brute Force)学習について
Brute Forceというと、パスワードを総当りで破るなどのケースでよく使われる言葉かと思います。
まさしく総当りというやつです。
とはいえ、6入力のLUTと言えど、内部には64bitのテーブルがあり、2^64 = 18,446,744,073,709,551,616通りあります。
これがちょっと 1000個ほどあると、2^64000 = (オーバーフローしました) となります。
流石に全体は総当りできません。量子コンピューターに期待です。
では、どうやっているかと言うとLUTの単位で総当りしています。
でもLUTの単位でも馬鹿探索をやると18,446,744,073,709,551,616通りになるので、ちょっとだけ工夫しています。
下記の手順となります。
1) まず全てのLUTのテーブルにランダムにbitを振る
2) あるLUTをターゲットにして計測テーブルを作る
3) 学習データを大量に流し、対象LUTの64種毎の入力毎にloss関数の総和を求める
4) 対象LUTのテーブルのbitを全て反転して同じ学習データを流し、入力毎にloss関数の総和を求める
5) 3と4を比較してbitを反転したほうがスコアが良くなるものは反転する
6) 対象を次のLUTにして、2に戻る
この繰り返しです。
畳み込み層がない場合、1つのLUTは1つのデータで一回しか演算に参加しませんので、このやりかたで、対象LUTについては、lossを最小にする64bitが求まります。これを繰り返していくわけです。
勾配を使うわけではなく、有無を言わさずハミング距離が6以内の範囲を全探索したのと同じことなので、小さな局所解であれば乗り越えることも可能です。
一方で畳み込みネットではこの手が使えません。演算器が再利用されてしまうので異なるbit同士が干渉してしまい、どちらのbitの反転が功を奏したのか判定できなくなるからです。
そこで一度、ハミング距離を1に限定して(つまり1bitづつ再計算して良くなったら採用というルールで)、本当の総当りをやったのですが、探索範囲が狭すぎで、「値がまったく変らない」という目にあいました。
次にやるなら探索範囲をもっと増やしてみようとは思っています。
一方で、現時点では、先日書いた記事のように、入力を6個に絞ったバイナリニューロモデルで勾配法で最適化できているので、まずはその範囲で最適化して、そこから力技に写るのが吉かと考えている次第です。その際には例えば4bitぐらいを束にして、16回データを流して一番いいものを採用とかになると思います。
遺伝的アルゴリズムとかが使えればよいのですが、先に書いたとおり、bit通しが干渉するので、一度に複数のbitを変えるとどちらが効いたのか分からなくなる世界なので、いいもの通しの交叉の類が難しいのではと予想しています。
まだまだ先は長そうです。
CPU/GPUとFPGA/ASICの違いについて
世の中の多くの機械学習の研究者やエンジニアはCPU/GPU上で日夜作業をされていると推測しています。
CPUやGPUは、はじめから決まった汎用演算ユニットを持っており、それを数GHzという速度で何度も再利用しながら計算を進めます。演算器の数ははじめから決まっており、計算機を買い換えない限り、増えたり減ったりすることはありません。ただし、このとき、倍精度実数だと一度に4個しか計算できないのに、単精度だと8個できるとか、バイナリ演算だと256個いっぺんに出来る、だとかはあります(バイナリ計算をやっている間は、高価な実数演算器は使われること無く休眠してしまうので、コスパが悪いとかか別の課題もあります)。また計算はメモリと演算器の間をデータが行き来することによって行われます。メモリからのデータの転送が間に合わないと演算器が待たされてしまうこともあります。
従って、これらの計算機で性能を上げるには、メモリからのデータ転送を滞らせない範囲でアルゴリズムを検討しつつ、演算回数を減らすか、一度に演算器により多くの情報をパッキングするためにバイナリなどにデータを縮退するかになります。
ディープラーニングの場合、少ない接続数でよい結果を出すネットを考えるのが前者向けで、バイナリネットなどが後者のアプローチになります。
一方で、FPGA/ASICの場合は、LUTやトランジスタなど、演算などを行う元となる論理スイッチの束を、どこにどう割り当てるかに自由度があります。
メモリの読み書きや通信に使う論理素子を減らして演算にまわしたり、実数演算を減らす代わりにビット演算機能を強化したりとかもできます。
従って、FPGAやASICで性能を上げるには、より多くの論理スイッチを演算に割り振り、かつそれらにより高密度なデータを供給することになります。
ここで「高密度なデータとは何か?」ということになるのですが、「bitあたりの情報エントロピー」と言い出してもきりが無いので、感覚として「同じ出所の値を32bitの単精度に入れるにに比べて、64bitの倍精度に入れたら、ちゃんと情報量が2倍になる」ことなどほぼないだろうというのはあります。元の数値の有効数字が非常に多くても、2倍以上にはなりえないし、そうでない場合は2倍未満にしかなりません。もともと単精度で十分なら完全に無駄です。
といったことを考えると、実はバイナリが最強ではないかと思ってみたりするわけです。
少なくともFPGA/ASIC的に考えるなら、「情報密度を最大化しつつ、演算以外の要素に極力リソースを裂かない実装の出来るアルゴリズム」というのがその方向性になります。従ってCPU向けの最適化が必ずしもそのままFPGA/ASICの最善にはならないと思うわけです。
FPGA/ASICの場合、ことディープラーニングに関しては、リソースの殆ど100%が演算に割り当て可能な気がしています。加えて演算濃度も重要に思います。限界点がどこにあるのか興味深いです。
今後の取り組み整理
まだまだ今後やることが多数あるので思いつくまま備忘録として書いておきます。
畳み込み層の作成
一度は力技学習のトライで失敗していますが、今回はLUTにパラメータコピー可能で逆伝播できるネットモデルが確立しています。
ただし、接続数を制限すると1層で完結しないので、演算層が数段入る畳み込み層が必要と思います。多層化すること自体はあまり心配していませんが、実装がテンソル積一発とは行かず、コーディングが要るので時間は掛かりそうです。
また、比較モデルとして、従来どおりの普通のCNNも同じプラットフォームで動くようにしておいた方が良さそうです。プラットフォームの動作確認も必要なので。 プーリング層も含めてまだまだ作るものが沢山あります。
MNIST以外のデータ
まだMNISTしか試せていません。いろいろ不安が残るのでせめてCIFAR-10ぐらいは早めに試せればと思います。
深いネットの作成
世の中にはいろんなネットがあるようです。例えば AlexNet とかの規模でこのやり方が通用するのかとか、ベンチマーク含めていろいろ必要と思います。
« LUT型のネットワーク考察のその後(途中経過) | トップページ | 少し見えてきたLUT-Netの可能性 »
「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)
この記事へのコメントは終了しました。
コメント