射撃しつつ前転

ニューラルネットを高速化する手段としてのスパース化

近年の大規模ニューラルネットワークを用いたシステムの運用には、GPUがほぼ必須であると考えられている。

しかし、プロダクションシステムがAWSなどのクラウド上に置かれている場合、GPUを使ったニューラルネットワークは使いづらい。AWS EC2のGPUインスタンスは高額だし、AzureやGCEは今のところGPUインスタンスを提供していない。という訳で、学習時にはGPUを使っても構わないのだが、テスト時にはCPUでもそこそこ高速に動いてくれるネットワークが構築できると嬉しい。

最近のニューラルネットワークの計算が重たいのは、2D Convolutionの計算量がとても大きいからである。高速に動かすためには、とにかく計算量を減らさないといけない。

考えられる方向は3つ存在する。1つ目がConvolution自体の高速化、2つ目が計算の低精度化、3つ目がスパース化である。

Convolution自体の高速化については、今のところの最速はWinograd Algorithmである。Winogradを使ったConvolutionのCPU実装にはnnpackが存在する。しかし、この方向は、極めても現状の数倍程度の高速化にしかならないようである。もう少し速くしたい。あと、strideのサポートに制限があったり(論文の計算式を見てもstrideのサポートは難しそうな雰囲気に見える)とか、実用上はちょっとやっかいな所がある。

(余談だが、Winograd Algorithmの二次元への拡張、論文だと「ネストするとこんな感じ」でいきなり計算式が出てくるのだが、導出がまったく理解できない。どなたか知ってたら教えて下さい。)

2つ目、計算の低精度化については、CPUで計算する場合は、2値化、3値化ぐらいにまで極端な低精度化をしないと、メリットが薄い。そして、そこまで極端に低精度にしてしまうと、現状では精度が犠牲になってしまう。その割にはAVX命令を使った場合と比べてせいぜい数倍程度の高速化にしかならない。FPGAやASICを使って自分で回路を組めるなら効果は劇的だが、CPUの場合はそこまで華々しい効果は得られない。

3つ目、今回のテーマのスパース化は、値が0の部分の計算を省略できるので、高速化につながる可能性がある。ニューラルネットワークには膨大なパラメーターが存在するが、そのすべてが本当に必要なのかというと疑わしい。実際、重み行列のほとんどを0にしてしまっても、ニューラルネットワークはうまく動作するのである。

Learning both Weights and Connections for Efficient Neural Networks

Hanらは、以下の様な手法で学習したニューラルネットは、スパースであり、かつ精度もほとんど落ちない(それどころか、場合によっては精度が多少向上する)ことを実験的に示した。

  1. 普通にニューラルネットを学習する。この際に、L1正則化もしくはL2正則化を行う
  2. パラメーターのうち、しきい値以下のものを削除する
  3. 削除してスパース化されたネットワークで再学習を行う

3.のステップがないと、精度はかなり低下するそうである。また、いきなり極端にスパース化してしまうより、1〜3を繰り返して徐々にスパース化した方が、精度はよくなる。ただし学習にかかる時間は伸びる。

LeNet, Alexnet, VGGNetについて実験を行い、パラメーター数は概ね1/10程度に削減できることを示した。ただ、計算量も1/10まで減らせるかというとそうではなく、最初の方のConvolutionはあまりスパースにできない(論文中にはレイヤーごとにスパース化した場合の精度低下を表すグラフがあるが、前段の方はスパース化による精度低下が激しい)ので、高速化としては3〜5倍程度の効果になるようだ。

Winograd Algorithmとスパース化の組み合わせ

らはWinogradやFFTを使った場合のConvolutionのスパース化の組み合わせを実験している。この結果によると、Winograd Algorithとスパース化は問題なく組み合わせられるようである。WinogradでConvolutionが2倍ぐらいに高速化できるとして、スパース化と組み合わせると、6〜10倍程度の高速化が実現できるわけだ。

http://cs231n.stanford.edu/reports2016/117_Report.pdf

なぜNVIDIAがスパース化を研究するのか?

Hanらのスパース化の論文は、著者の半分がNVIDIAに所属している。GPUではスパース化は効果が薄い。Intelがこの論文を出すなら納得できるのだが、NVIDIAがこういうものに関わるのはちょっと不思議に感じられる。

この謎は、同グループによる次の論文で解けた。内容は、スパース化を含む様々な工夫を凝らしたハードウェア実装である。通常のCPU実装と比べて189倍、GPU実装と比べて13倍高速で、電力効率もGPUと比べて数千倍以上が達成できたとしている。これだけ効率化が進めば、モバイルデバイスに載せるのも現実的と言えそうだ。NVIDIAは車載向けを本気で狙ってるっぽいし、次のTegraか次の次のTegraぐらいには、このような機能が実装されていたとしてもおかしくない。

  • [1602.01528] EIE: Efficient Inference Engine on Compressed Deep Neural Network

SqueezeNetを読み返す

SqueezeNetはニューラルネットワークのサイズ削減のための有望な手段である。改めてSqueezeNetの論文を読み返してみると、Hanらのスパース化のアイディアや、ResNetにインスパイアされたバイパスの導入など、多くの工夫を組み込むことで、最終的にはモデルサイズを通常の1/500程度にまで削減することに成功している。Squeezeによる計算量の削減は、論文から読み取れる設定(1/4にsqueezeして、同数の1x1と3x3でexpandする)で計算すると13.5倍の高速化になる。

やや余談だが、この論文、4月に出ている第3版でページ数が9ページに増えていて、Sensitivity Analysisとか、いくつか情報が増えている。その中に、Densifying Sparse Modelsという項目が増えているのだが、これがシンプルな割に劇的に効くようである。

  1. 普通にスパース化する。つまり、小さな値のパラメーターを削除して再学習、を繰り返す。
  2. 1で削除したパラメーターを復活させる。この際、復活したパラメーターは0に初期化する。
  3. 再学習をかける。

これだけで、ImageNetのtop1-accuracyが4%も向上したと報告している。ということは、オリジナルのAlexNetよりも4%も精度が高いということである。これはかなり驚くべき話である。

SqueezeNet + ResNet

らは、SqueezeNetにResNetを組み合わせるアイデアをさらに推し進めた実験を行っている。オリジナルのSqueezeNetと比べ、ResNet化によって、Tiny ImageNetの分類精度が、top-1 accuracyで44ptから58ptと、大幅に向上した。また、彼らの実験設定では、Batch Normalizationを使っているのだが、そこにDropoutを組み合わせることで、オーバーフィットを大きく軽減することができたと述べている。

http://cs231n.stanford.edu/reports2016/410_Report.pdf

積み重ねるとどうなるか

Winogradとスパース化の組み合わせを効率的に実装するのは大変なのであきらめるとして、WinogradとSqueezeNet、もしくはスパース化とSqueezeNetを組み合わせることで、27倍〜39倍程度の高速化が期待できる。これぐらい高速化できれば、CPU実装でもそれなりに使い物になるだろう。

参考文献