ラビットチャレンジ - 深層学習 Day4 Section3 軽量化・高速化技術

# 0．概要
本記事は日本ディープラーニング協会認定の講座プログラムである「ラビット・チャレンジ」が提供している科目の1つである深層学習のレポートである。
記事タイトルに記載のとおり、Day4 Section3 軽量化・高速化技術について以下にまとめる。

# 1．分散深層学習
深層学習は多くのデータを使用したりハイパーパラメータのチューニング等に多くの時間を要すため高速な計算が求められる。
都度都度あまりに長時間学習に待ったりするわけにもいかないｔまえ、計算を高速化することは必要不可欠である。

つまり色んな工夫をして膨大な計算力を確保したり計算量を減らしたりすることを指す。

# 2．高速化

## 2.1．データ並列
親モデルを各ワーカー(いわゆるPC、またはGPU等の演算器)に子モデルとしてコピーし、分割したデータを与えて各ワーカーごとに計算させる。
たくさんワーカー(PC台数増やしたり、PC1台だけどGPUを複数載せたり)を用意してデータを分けて同時に学習させること。

同期型と非同期型があるが同期型が主流。

同じ構造のモデルでデータを分けて学習するため、データが多いほど速度向上が見込める(データが少ないならデータを分ける意味も薄くなる)。
つまり、データ並列化はデータが多い場合に選択すべきである。

また、GPUを複数用意するよりPCを複数用意することが多い。

参考：
https://logmi.jp/tech/articles/285424
https://serihiro.hatenablog.com/entry/2018/06/02/224748

### 2.1.1．データ並列：同期型
全ワーカーの学習が全て終わったらワーカーから出た勾配の平均を親モデルのパラメータに反映する。
これによって前より親モデルの性能が上がる。
さらに親モデルを子モデルとしてコピーして学習し、…という流れを繰り返す。

全ワーカーの学習が全て終わるのを待つため非同期型よりは遅いが、精度は同期型の方が高い。

### 2.1.2．データ並列：非同期型
同期型と違って全ワーカーの学習が終わるのを待たず、子モデルのパラメータを更新する。
学習が終わったらそのワーカーはパラメータ更新した子モデルをサーバにPushし、また新しく学習する時はサーバから最新のモデルを取得して使用する。

速度は同期型より速いが、非同期型の場合はタイミングによって使用されるモデルが最新でないため学習が不安定となりやすい。

## 2.2．モデル並列
親モデルを各ワーカーに分割してそれぞれ学習させる(モデルを途中で切って分ける)。
全てのデータでそれぞれのワーカーの学習が終わった後、各ワーカーのモデルを1つに復元する。

モデルによっては分岐があるものもあるので分岐のところで分けることが主流。

モデルを分けるので複雑なモデルほど速度向上が見込める(単純なモデルならそもそも並列化する意味がない)。
つまり、モデル並列化はモデルが大きい(複雑)場合に選択すべきである。

また、PCを複数用意するよりGPUを複数用意することが多い。

論文：Large Scale Distributed Deep Networks

参考：https://serihiro.hatenablog.com/entry/2018/06/02/224748

## 2.3．GPU

### 2.3.1．GPU
分岐等様々な処理を得意とするCPUと違い、並列計算を得意とする(ゲームの3Dグラフィックの演算等)。
膨大な行列計算を行うニューラルネットワークにとって並列計算できるGPUは高速化に役立つ。

### 2.3.2．GPGPU(General-purpose on GPU)
元々の使用用途であるグラフィック以外で使用されるGPUのこと。

### 2.3.3．CUDA
NVIDIAのGPUで使える並列コンピューティングプラットフォーム。

以前、CUDAを入れてTensorflowを使ったが速度がCPUだけの時とは雲泥の差で感動した覚えがあります(GeForce RTX 2070 SUPER使用)。
GPUにも固有のメモリがあるのでメモリ的にも余裕ができていました。

# 3．軽量化
参考：https://laboro.ai/activity/column/engineer/ディープラーニングを軽量化するモデル圧縮/

## 3.1．量子化(Quantaization)
ネットワークが大きくなるとパラメータ(重み等)も多くなっていくため、例えばパラメータの64bit浮動小数点を32bit等の下位精度に落とすことでメモリや計算量を削減する。
例えばBERTなら億単位のパラメータ数があったりするため1つ1つは数バイトでも合計すると大きなサイズとなる。
64bitを32bit量子化した場合、1/2のサイズとなる。

量子化で用いる精度は主に16bit(半精度), 32bit(単精度), 64bit(倍精度)の3種類。
下記のような欠点もあるが基本的に半精度を選ぶと良い。

### 3.1.1．量子化の利点
・計算の高速化
　bit数が減ることで計算量も減る(bit数はいわば桁数なので桁数が減る)。

・省メモリ
　bit数が減ることで桁数が減ることになるためデータ量が減る。

### 3.1.2．量子化の欠点
・精度の低下
　bit数を減らすと浮動小数点数で表現できる小数点数の精度が落ちる(より小さい桁の情報が表現できない)。
　ただ、実際には倍精度を半精度にしても精度はほぼ変わらない。

## 3.2．蒸留(Distillation)
精度の高い規模の大きなモデルから軽量なモデルを作ること。

下記に示すKnowledge DistillationやHint Trainingという手法がある。

### 3.2.1．教師モデル
精度の高い複雑なモデル。これをもとに軽量なモデル(生徒モデル)を作る。

### 3.2.2．生徒モデル
教師モデルを元に作る軽量なモデル。

### 3.2.3．Knowledge Distillation
教師モデルの重みは固定とする(すでに精度はあるためこれ以上学習させない)。
教師モデルと生徒モデルのそれぞれの誤差を使って生徒モデルの重みを更新していく。

既に精度が十分にある教師モデルの誤差を使うことで教師モデルの精度を生徒モデルへ反映していく。

## 3.3．プルーニング(枝刈り：Pruning)
複雑なモデルになるほどパラメータが膨大な数となっていくが、全てのニューロンが精度に寄与(役立っている)しているわけではないため、寄与が少ないニューロンを削除して有用なニューロンのみ残して再学習することでモデルの複雑さを軽減して軽量化につなげること。

### 3.3.1．ニューロンの削減
重みが閾値以下のニューロンを削除する。

ドロップアウトで一部のニューロンをないものとしたのと似たようなやり方(目的や対象をどう決めるかはもちろん違うが)のイメージ。

# X．ラビットチャレンジとは
ラビットチャレンジとは、日本ディープラーニング協会認定の講座プログラムの1つ。
E資格を受験するためにはこのラビットチャレンジ等、いずれかの講座プログラムを修了しなければならない。

ラビットチャレンジの特徴は「現場で潰しが効くディープラーニング講座」の通学講座録画ビデオを編集した教材を使用した自習スタイルであるという点。
サポートは他の講座より少なく、受け身ではなく自主的に学んでいく姿勢でなければ進められないが、その分、他の講座に比べると安価であり、手が出しやすい。
ある程度知識がある人、自力で頑張るぞというガッツのある人向けではないかと感じる。

![bnr_jdla.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/389699/bce66671-a2f5-a7f9-de6f-3f87e15c253b.png)