パーセプトロンに代わる素子の可能性について
新しい学習モデルの可能性
前回までFPGA回路の為に、FPGA内のバイナリLUT(ルックアップテーブル)の値を学習させることをターゲットにやってきました。
今日は、今日はその試行錯誤の副産物として、バイナリとかFPGAとかから離れた、普通のCPUやGPUでやるディープラーニング向けの新しい学習モデルについて可能性を提起してみたいと思います。
相変わらず、第三者の検証を挟んでいないという点でトンデモ科学の領域なのですが、ネタをネタとして楽しめればなと思っております。
(おさらい)Stochastic演算でのLUTモデル
本題に先立って、今日紹介するモデルの元となった、Stochastic演算でのLUT記述について記載します。
Stochastic演算についてはこちらの記事などが分かりやすいと思います。ハードウェア派の人にはD級アンプなど想像してもらうと分かりやすいかもしれませんが、オーバーサンプリングの世界では、実際の値を0/1を出現頻度に置き換えて取り扱うことが可能です。
AND/OR/NAND/XOR...など、すべてのデジタルゲートは、入力の0/1を出現確率として捉えた場合、その演算を確率演算に置き換えることが出来ます(前提として互いが無相関にバイナリ化されているとみなせることが前提ではありますが)。
要するに、デジタルの組み合わせ回路であれば、どんな電気回路でも入力を確率的な0/1の羅列として扱えるシーンであれば、すべて確率演算に置き換える事が可能であり、LUTもその例外ではありません。そして、重要なのはLUTはテーブル次第で非線形だろうがどんな計算でもフィッティングできる万能演算素子であるということです。
加えて、確率演算は基本的に単なる乗算なので、このレベルまで分解すれば、FPGAのLUTを含めたどんな回路でも置き換え可能であり、しかもそれは微分可能であり、誤差逆伝播で学習可能です。
そして、実際に現実世界のデータの多くは元々確率的に振舞いますし、そうでないデータもデジタル量子化の段階でそう振舞うように変調することは比較的容易なので、この手法は意外に応用性の広い技術となります。
6入力LUTのモデルを書くと大変なので、以下に2入力LUTのStochastic-LUTの演算グラフを書きます。
このグラフの理解はあまり難しくはありません。2入力LUTを仮定した場合、入力が2bitでテーブルが4個存在します。
テーブルの値が上の図のW0~W3の4個に対応します。2つの入力を持ち、入力0に1が入力される確率をx0,入力1に1が入力される確率をx1、出力が1になる確率をyとしています。それぞれ1になる確率なので、例えば入力0が、0になる確率は 1-x0 で計算できます。
テーブルの0番(W0)が参照される可能性は 入力がすべて0の時ときですから、(1-x0)*(1-x1)となります。このように
W0が参照される確率:(1-x1)*(1-x0)
W1が参照される確率:(1-x1)*x0
W1が参照される確率:x1*(1-x0)
W1が参照される確率:x1*x0
となり、これらの総和が出力が1になる確率で、二値化関数を Bin(x) とすると
y = Bin(W0)*(1-x1)*(1-x0) + Bin(W1)*(1-x1)*x0 + Bin(W2)*x1*(1-x0) + Bin(W3)*x1*x
のように表せます。
実際は4入力や6入力など実際に存在するFPGAの素子にあった式を実装しており、この式をGPGPUなどで計算することで、一定の条件下のLUT-Networkを非常に効率よく学習出来ております。
この演算の良いところは、LUTが取りうる値はXORも含めて単独で学習可能なことです。一般のパーセプトロンで同じことをするには隠れ層を持った2段以上のモデルにした上で、非線形な活性化層を加える必要があります。しかしこのモデルだと、単独でLUTが取りうるすべての値が学習対象となります。
バイアス項が無いのは気にはなっているのですがLUTに置き換わる以上は回路上の表現は十分なはずなのと、MNIST程度に関しては実によく学習してくれています。
バイナリでStochastic演算を行うには、例えば4bit精度が必要なら15倍のオーバーサンプリング、8bitで255倍、16bitで65535倍、とNbit精度に2^N-1倍のーバーサンプリングが必要になります。乗算器の規模は N^2 のオーダーなので、Nが比較的小さい場合に空間より時間に展開したほうが有利な領域が発生すると考えています。
(本題)パーセプトロンに代わる素子の可能性
さて、いよいよ本題です。では先のモデルから2値化項を取り払って、Stochastic演算という言葉も一回忘れて、計算グラフのモデルだけを「普通の実数空間のディープラーニングに応用したらどうなるか?」という話です。
要するに従来のパーセプトロンのモデルの箇所をこのモデルに入れ替えてどうなるか実験してみたというのが本記事の要旨です。
幸い、LUT-Networkの学習用に作成中のBinaryBrainという学習環境は、ベンチマークの為に従来からある普通のディープラーニングも出来るように作っており、実数も扱えます。また疎行列学習を目的にメモリ配置なども工夫しており、今回のような実験には最適です。
ここで、CIFAR-10のデータを使って、従来の普通のCNNと、この新モデルを使った学習とを行い比較してみました。
学習の概要部分を下記に示します。
[従来のDenseCNN]
SparseCNNはリソースを増やして2回試しています。
accuracy は testデータを使ったものと、trainデータを使ったものの2種計算していますが、testデータを使ったもの(test accuracy)を参照してください。train accuracy が高いのは単なる過学習であり、本来はDropoutなどを組み合わせて抑制が必要な項目です。
現在、疎結合な層間でランダム結線を採用しているのがSparseモデルで過学習を抑制できている原因と考えています。
また、実行は、すべてGoogle ColaboratoryのTesla T4 で実行したもので、計算時間も参考にしていただければと思います。DenseCNNはcuBLASを利用しており、Sparseの方は私がCUDAコードを記載しています。
(上記の画像はGoogle Colaboratoryの画面スナップショットなのですが、最後だけ色がおかしくなってしまいすみません)。
モデルの構造
下記に今回発案のモデルの計算モデルを記載します。
実際に実験に用いたのは6入力のモデルです。
なお、式は巨大ですが、実際は共通化できる演算が多く、プログラムに書き下ろして最適化すると大した計算量にはなりません。
このモデルの特徴としては
- 単独でXORのような問題が解ける
- 活性化層無しで非線形性を保有する
という点があります。
実際にはこの素子にBatchNormalizationを組み合わせています。BatchNormalizationは一般にバッチデータの平均(mean)と偏差(var)に対して、y=(x-mean)/sqrt(var) * gamma + beta という演算を行います。今回は gamma=0.2, beta=0.5 に固定して、平均と分散補正のみ行っています。学習時は平均と分散を求めるのでBackward含めていろいろな計算を行うのですが、推論時には単なる線形なスケーリング(y=ax+b)を行うだけの形に帰着するので、学習 の効率化に関しては非常に強力ですが、本質は違うところにあると考えています。
ただ、BatchNormalizationが無いと学習が進まないケースも多いのと、先に述べた既存モデルにバイアス項がないのがここで補われている可能性はあります(それならそれで大した計算ではないのでモデルに加えれば済む話ではありますが)。
計算量の話
今回の素子モデルは素子モデル内の計算量は固定でO(1)です。しかし入力数が固定なので実際にはカスケードに繋いで接続数を増やす必要があります。しかしながら、入力数をNとした場合の計算オーダーは O(n) となり、従来と変わりません。これは中央値の中央値などのアルゴリズムがO(n)に収まるのと同じですね。
層が増える分、接続方式にバリエーションが取れる分、今回のモデルには面白みがあるかもしれません。
なお、実際には上記のような構造化した接続はまだ考慮できておらず、今回のモデルを各層で適当な数ばらまいて、層の間をランダムに結線するという乱暴なことをやっています。が、このやり方がある程度過学習の抑制にもなっていそうな傾向が見れています。
またこのようなやり方の場合、層の段数は概ね入力数をNとするとlog N の深さになるかと思います。N対Nの場合、全結合だとO(N^2)になるのに対して、O(N・log N) のオーダーに近づくのであればそれはそれで面白いと思う次第です。
実行環境
なお、今回のコードは ver3_release3 というタグ名で github にpushしております。
お試しいただきたい場合は、Google Colaboratory上の Notebook にて下記のコマンドを実行いただければ今のところ実行可能です。
!git clone --recursive -b ver3_release3 https://github.com/ryuz/BinaryBrain.git
%cd BinaryBrain/sample/cifar10
!make all
!make dl_data
!./sample-cifar10 SparseCnn
私の環境では、今のところ運よく Tesla T4 が割り当てられていますが、K80などが割り当てられる場合もあるようですし、今後もnvccなどの環境が同一に提供されるかどうかは分かりませんが、ある程度メモリのあるGPU上でCUDAが動く環境があれば試すことは出来るかと思います。
(追記 平成31年4月30日)逆伝播の式について
逆伝播は難しくなく機械的に解けるのですが、一応、ざっと手元で今解きなおしたものを従来のパーセプトロンの比較もあわせて下記に追記しておきます。(平成最後の日ですね)。
個人的には、パーセプトロンと違い、入力への逆伝播の項に他の入力が現れるところに興味を持ってます。
入力に入力が戻るということは、逆伝播が自己再帰ループを組んでいることになるかと思います。
データを変えずに、forward->backward->updateの反復で値変化が進行する可能性があります。バイナリ素子の乗算器回路とかでやったら、素因数分解とか、暗号解析系とに使えないかなというのは前に書いたとおりですね。
おわりに
このような研究をされている方は多分沢山おられるのだとは思いますが、ある程度実用的にGPGPU上でプラットフォーム作成とあわせて行えたというのは珍しいのではないでしょうか?
Wikipediaを見るとXOR問題が示されたのが1969年のようなので、ぴったり半世紀後の今、XOR問題を持たない素子で、ある程度実用的な実験ができたのはなかなか面白いところに来れたように思います。
既存パーセプトロンのモデルの一つの課題は、全結線時の結線の多さであり、専用計算機を設計する際の工夫のしどころでもあるし、組み込みAIのような分野ではメモリ帯域を逼迫させる要因ではないかと思います。一つのアプローチとしてこういったやり方があっても面白いのではないかと思う次第です。
特に専用ASICなどを考える場合、疎結合であればメモリを解さずに直接結線できるかもしれませんし、ストレージの難しいアナログ系の素子を使ったLSIなどへの応用とかだとな面白そうな気がしています。
トランジスタやOPアンプ並べて色々実験したら意外に楽しいかもしれません。アナログ素因数分解器作れないかな (^^;
« LUT-Networkの最新資料更新 | トップページ | LUT-NetworkでAutoEncoder »
「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)
この記事へのコメントは終了しました。
コメント