こんにちは、スマートニュースの徳永です。深層学習業界はGANだとか深層強化学習だとかで盛り上がっていますが、今日は淡々と、スパースなニューラルネットワークの話をします。
要約すると
- ニューラルネットのスパース化によって、精度はほとんど犠牲にせずに、計算効率は3〜5倍程度まで向上できる
- スパース化にはまだ課題が多く、ニューラルネットの高速化という意味では、次の戦場はたぶんここになる
スパースとは、スパース化とは
スパースであるとは、値のほとんどが0であることです。例えば、ベクトル$a,b$の内積を計算する際に、$a$のほとんどの要素の値が0であるとしましょう。0になにをかけても0ですから、$a$の値が0でない次元についてのみ、$a_i b_i$の値を計算して足し合わせればよいわけです。このように、内積を計算する際に、どちらかのベクトルがスパースであれば計算が高速化できます。0という値をメモリ上に律儀に保存しておく必要もありませんから、同時に省メモリ化もできます。
スパース化とは、元のベクトルや行列の性質を残しつつ、値のほとんどを0にしてしまうことです。ニューラルネットのスパース化といった場合には、通常はネットワークのパラメーターのほとんどを0にする事を指します。
なぜスパース化が重要なのか
ニューラルネットは画像処理、音声処理、自然言語処理など、様々な分野で広まっていますが、メモリ消費量や時間計算量がこれまでの手法よりもべらぼうに大きく、高価なGPUがないと扱いづらい点が課題となっています。
クラウド上のGPUはどれもいいお値段なので、サービスのコア部分ならともかく、周辺機能に「ニューラルネット使うとちょっといい感じじゃない?」ぐらいのノリでは、なかなか導入までたどり着けません。このため、ニューラルネットの効率化は、産業応用において非常に重要なテーマであると言えます。
スパース化は、先日紹介した量子化と並んで、ニューラルネットの効率化のために有望な手法の1つであると言えるでしょう。
スパース化の歴史は長い
ニューラルネットの歴史は非常に長く、スパース化についてもかなり昔から研究されているようです。ちょっと検索しただけでも、簡単に1988年の研究とかが見つかります。膨大な積み重ねがある分野なわけですが、今回は調査時間の都合上、最近の研究を一部紹介するにとどめます。
研究紹介
Learning both Weights and Connections for Efficient Neural Networks
Hanらは、ネットワークを普通に学習した後、値の小さな重みの部分をネットワークから取り除き、さらに再学習を行いました。ImageNetを用いた実験において、VGG-16をスパース化することで、精度を落とさない(むしろ上がっている)ネットワーク中のconnectionの数を約1/12に削減し、計算量も約1/5に削減しました。ただ、注意深く実験結果の表を読むと、FLOPsが1/5程度になったと書いてありますが、これは添字の計算などを含んだトータルの計算コストを表したものではなく、純粋に浮動小数点演算の回数のようです。(添字の計算は整数なので、たしかに、FLOPsには入りません。)5倍速くなるわけではないという事には留意したほうが良いでしょう。もちろん、それでも素晴らしい結果ではあります。
また、スパース化→再学習のプロセスは何度か繰り返したほうが、最終的な精度が上がるそうです。
DSD: Dense-Sparse-Dense Training for Deep Neural Networks
この研究は最終的なスパース化を目指しているわけではなく、効率化とは方向性が少し違いますが、面白いので紹介します。
Hanらは、スパース化した状態で再学習した後、一度取り除いた重みをもう一度ネットワークに戻して再学習を行う(HanらはこれをDSDと呼んでいます)ことで、元のネットワークよりも精度が向上することを発見しました。ImageNetをデータセットとして使った実験で、GoogLeNet やResNet-50のtop1 accuracyが1.1%も改善しました。また、音声認識や機械翻訳など、幅広いのタスクでDSDが有効であることを示しました。
ResNet-50のtop1 error rateはもともとが24.0%で、それが22.9%になるわけですから、精度向上のための手法として、かなりの効果があると言えるでしょう。なんでこんなに精度が良くなるのか、理由はよくわかりませんが、論文では、これまでの手法とは違った正則化の効果があるのではないか、と述べています。
Pruning Filters for Efficient ConvNets
Liらは、L1ノルムが小さなフィルタをネットワークから削っていくというシンプルな手法が、実際のactivationの統計量を使ってフィルタの重要度を測る複雑な手法と比べてcomparableである(場合によっては上回る)ということを示しました。group Lassoとは比較していないので、その辺りが気になります。
The Power of Sparsity in Convolutional Neural Networks
Changpinyoらは、畳み込みニューラルネットにおいて、一度学習したネットワークをpruningするのではなく、最初からランダムにフィルタを削った状態から学習を始めても、それなりにうまく学習できることを示しました。これは他の実験結果と矛盾しています。例えば、彼らはその他にも、非常に少ないフィルタ数で学習をはじめて、徐々にフィルタ数を増やしていくという手法が機能することを示した。GPUで実装した場合にどれぐらい高速になるのかについては実験結果がありませんが、pruningと比べた場合、少ない学習時間で精度が出ることが期待されます。非常に大きな、pruningでは学習が難しいぐらいのサイズのネットワークを作りたい、というような場合には有用でしょう。
Training Sparse Neural Networks
Srinivasらは、あるパラメーターを使うかどうかをベルヌーイ分布からのサンプリングで決定するという手法を提案しました。ベルヌーイ分布のパラメーター自体も学習します。ベルヌーイ分布からサンプリング結果は離散的(0か1しかない)であるため、そのままではバックプロパゲーションでの学習ができませんが、Straight Through Estimatorを使って学習します。学習時のパラメーターが通常の倍に増えてしまうという難点がありますが、単純なL1スパース化と比べて、より少ないパラメーター数でより高い精度を実現できました。具体的には、ImageNet上の実験でVGG-16をスパース化した場合、非ゼロのパラメーター数を既存の手法よりも5%程度減らしながら、Top-1 accuracyを68.66%→69.04%へと向上しました。また、再学習にかかる時間も、Hanらの手法と比べて大幅に短い時間(数分の一)で済むそうです。
フィルタ単位でのスパース化と組み合わせると面白いんじゃないか(パラメーターもそんなに増やさないで済むし)と思いました。
Pruning Convolutional Neural Networks for Resource Efficient Transfer Learning
Molchanovらは、最も影響の少ないfeature mapを削ってfine-tuningする、という操作を繰り返すことで、pretrain済みモデルから転移学習したモデルが効果的にpruningできることを示しました。畳み込みのフィルタを削るのではなく、アクティベーションの方を削っている点が珍しい研究と言えるでしょう。
どのfeature mapを削るとよいのかは、実際にすべてのfeature mapを(1つずつ)削ってみて目的関数の値を計算してみれば、理屈上は比較できます。しかし、feature mapはたくさんあるので、この方法は現実的ではありません。そこで、目的関数を一次のテイラー展開で近似することで、目的関数の変化を近似的に計算する手法を提案しました。Taylor展開を用いた提案手法は、他の手法と比べて、スパース化による性能低下が遅いことを示しました。
Taylor展開を使った近似では、勾配とアクティベーションの値の積(の平均値)が小さいものから削られていくことになるので、直感的にも良い手法に見えます。
Liらの実験結果(単純にL1ノルムが小さいフィルタを削れば十分である)と矛盾している印象を受けますが、フィルタを削っているのかfeature mapを削っているのかで実験設定が大きく違うため、直接は比較ができません。Taylor展開を使った目的関数の変化度合いの近似はフィルタに対しても計算できるので、畳み込みフィルタをTaylor展開ベースでスパース化する追試が近いうちに出てきそうな気がします。
Learning Structured Sparsity in Deep Neural Networks
Wenらは、計算の効率化のために、Structured Sparsityという概念を導入しました。例えば、入力チャンネルが$n$個、出力チャンネルが$m$個のレイヤーでは、畳込みフィルタは$n \times m$個必要になりますが、この畳み込みフィルタが1つ不要になったとすると、計算量を$\frac{1}{n \times m}$だけ減らすことができます。フィルタをなくすだけなので、スパース化についてまわる添字の計算によるオーバーヘッドがほぼないというメリットがあります。また、GPUでも高速化が見込めます。
以下の3パターンのstructured sparsityがあります。
- あるフィルタのすべての値を0にする。そのフィルタが関わる計算をすべて省略できる。
- フィルタのある位置の値をすべて0にする。例えば、すべての3x3フィルタの右上を常に0にすると、計算コストを8/9に減らせる。
- あるレイヤー中のフィルタの値をすべて0にする。そのレイヤーの処理を全部省略できる。(これはResNetのみ)
まとめて値を0にするためにはgroup lasso正則化を用いています。
AlexNetを用いたImageNetでの実験で、約2%のtop-1 validation errorの上昇と引き換えに、CPUで4〜6倍、GPUで約3倍の高速化が可能であることを示しました。実際に高速化できたという実験結果を載せている論文は少ないので、貴重な結果です。
Group Sparse Regularization for Deep Neural Networksもタイトルは似ていますが、こちらはあるニューロンに紐づく重みをグループ化して正則化することで不要なニューロン自体を削除する、みたいな方向性でした。また、グループ単位での正則化の場合に、L1だけではなくL2も使ってElasticNetみたいな正則化をしたほうが効果が高いそうです。
Variational Dropout Sparsifies Deep Neural Networks
Molchanovらは、 Sparse Variational Dropoutという手法を提案し、これまでの手法よりも高いスパース化が行えることを示しました。CIFAR-10にVGG-likeネットワークを適用した際、Denseなものと同精度(7.3%)を達成しつつ、非ゼロパラメーターの数を1/48まで削減できたそうです。
数字が書いてある実験結果がMNISTとCIFAR-10に対するものしかなく、より幅広いタスクでの検証が必要ではありますが、有望な手法と言えるでしょう。
SCNN: An Accelerator for Compressed-sparse Convolutional Neural Networks
Parasharらは、既存の密なニューラルネット向けのアクセラレータと比べて、2〜3倍程度、速度と電力効率を改善できるスパースなニューラルネット用のアクセラレータアーキテクチャを提案しました。シミュレーターを使ってモデルを評価しているようなので、まだFPGAやASICで実物が動いているわけではなさそうです。
論文著者陣の半分ぐらいのメンバーはNVIDIA所属なところが興味深いです。
違った視点から:Mixture of xpertsによる計算のスパース化
最初に、スパース化は計算をサボってメモリ消費量も減らせる手法であるという話を書きましたが、その話にはちょっと嘘が混ざっていて、常に計算量の削減とメモリ消費量の削減の両方を達成できるわけではありません。例えば、メモリ消費量の削減インパクトは比較的小さいが高速化には寄与する、みたいな手法もあります。ここでは、Mixture of Experts (MoE)という手法を、スパース化の観点から眺めてみましょう。
MoEは、複数のエキスパート(=学習器)を用意して、それらを切り替えながら処理を行う手法です。1991年のJacobらの論文でも、いくつかのエキスパートと、どれを使うかを切り替えるGating Networkがあるので、入力に応じてエキスパートを切り替える部分が、単にアンサンブルと言った場合との一番大きな違いであると考えてよさそうです。
Outrageously Large Neural Networks: The Sparsely-Gated Mixture-of-Experts Layer
Shazeerらは、MoEを使った超巨大なニューラルネットを構成し、言語モデルや機械翻訳の分野において、これまでよりも高性能なモデルが高速に学習できることを示しました。ネットワークの切り替えにおいては、sparse noisy top-k gatingという手法を用いており、選択されたk個のエキスパート以外の重みは0になります。重みが0ということは計算する必要もなくなるので、この工夫により、計算コストを大幅に削減できています。
個々のエキスパート自体は既存のモデルよりも小さなものを使っていますが、エキスパート数が2048など非常に大きい数になっているので、結果としてパラメーターの数は何十倍にも増えてしまっています。8.7Bのパラメーターがあるので、それぞれのパラメーターを16bit浮動小数点で表現するとしても、$8.7 \times 10^9 \times 4$ = 約35GBのメモリが必要になるので、1台のGPUでは学習できません。学習には数十枚のGPUを使ったそうです。一般的には、複数台のサーバーでGPUを使うと、サーバー間での通信部分を効率よく処理するのが大変になりますが、MoEの場合は勾配の情報をサーバー間で通信する必要がないので、実装の難易度はだいぶ下がりそうです。
スパース化の要諦は、「いい感じに計算式中に0が出てくるところを増やす」ことであり、本手法では、sparse noisy top-k gatingが「計算式中の0を増やす」操作に対応します。スパース化をうまく使った精度向上のための手法であると言えるでしょう。
余談ですが、Googleから出たことで少し前に話題になった画像の高解像度処理技術RAISRも、一つ一つのフィルタはシンプルなもの(単なる畳み込み演算)にしておき、フィルタをうまく使い分けることで目的を達成しています。これも一種のMoEだよなぁという感想を持ちました。
さらに、単なる夢や願望の話になってしまいますが、人間はタスクによって明らかに脳の使い方が変わるので、脳はMoE的な情報処理をしていると言えるでしょう。もしかしたら、人間の脳を模倣することで、より優れたMoEのアーキテクチャを作ることができるかもしれません。
まとめ
本稿では、スパースなニューラルネットワークの構築や、ハードウェアでのアクセラレーションについて、近年の研究を紹介してきました。ネットワークの構築では、多くの場合、まずはスパースではない(=密な)ネットワークを構築して、それから刈り込みを行う手法が大半を占めます。スパース化を行う手法は、どこでもいいから削れそうな重みを0にして刈り込んでしまう手法と、フィルタ単位など高速化しやすい単位でパラメーターを刈り込む手法に大別できます。後者でないと高速化が難しいですが、精度は前者のほうが高い(前者はむしろ精度が向上することすらある)という状態で、現状では、精度と速度のいいとこ取りは難しいようです。
ところで、数か月前に、ニューラルネットの量子化について書きましたが、先日、Googleの第1世代TPUは8bit単位と16bit単位のデータをサポートしていることが明らかになりました。また、第2世代TPUが既に実用化されていることも明かされました。第2世代TPUでニューラルネットの学習の全てがまかなえるのかどうかはまだよくわかっていませんが、いずれにせよ、Miyashitaらの研究で、低精度表現での学習も可能なことは既にわかっています。ニューラルネットの量子化の研究は、終わったとは言いませんが、終わりが近づいており、今後のフォーカスは実用化に移っていくでしょう。
一方で、スパース化については、まだまだこれからできることがいっぱいありそうだな、という印象を受けます。ぱっと思いつくだけでも、次のように重要な課題があります。
- スパースなネットワークの学習は難しく、pretrain済みモデルのスパース化であっても、学習時間が長い
- 最初からスパースなネットワークを学習することはもっと難しく、学習した後に刈り込む方式と比べると精度が出しづらい
- この問題が解決できないと、スパース化によってできた余剰リソースを大規模化に回してより高精度化を図る、という方向に行けない
- 単純にスパースにするよりは、ある程度の規則性をもったスパース化の方が、高速化の観点からは好ましい
一方で、ニューラルネットの高速化、低消費電力化については、今後もどんどんと需要が大きくなることが予想されます。例えば、自動車の自動運転はその典型例ですが、サーバー側ではなくデバイス側で高度な処理を行いたい、という需要は確実にあります。Google Glassのようなメガネ型デバイスが常に環境を認識し続けて、状況に応じていろんな情報を提示してくれると便利ですが、そのようなデバイスを実現するためには、センサーから得られたデータをすべてサーバーに送っていては回線がパンクしてしまうので、デバイス側で環境認識を行う必要があるでしょう。
そんな夢のようなメガネ型デバイスはまだまだ出てこない(Google Glassも販売中止になったし……)と思っていたのですが、SIGGRAPH2017のマイクロソフトのメガネ型ARディスプレイの研究を見ていると、考えを改める必要が出てきたように思います。表示側のデバイスは今後数年で実用化され、環境認識のほうがボトルネックになる未来は十分にありえるでしょう。デバイス上での継続的な環境認識のためには低消費電力化は必須要件であり、この極端にシビアな要求にこたえるためには、総力戦で効率化を図っていく必要があります。
次のニューラルネット高速化のフロンティアはスパース化にある、と言っても過言ではありません。今からやるなら量子化はもう遅い、これからはスパース化だ!