こんにちは、サイオステクノロジーの藤井です。
この記事では、ディープラーニングが具体的にどのようなアルゴリズムで動いているかを書いていこうと思います。ディープラーニングを使ったことのない方や、私と同じように動かしたことはあるけどなんで動いているかわからない方が、ディープラーニングを理解する助けになれれば良いなと思っております。
前回の「[AI入門] ディープラーニングの仕組み ~その1:ニューラルネットワークってなに?~」では、ニューラルネットワークの仕組みについて書きました。
今回は、ニューラルネットワークの学習を高速化するために計算量を減らす手法として、ミニバッチ学習と誤差逆伝播法について学んだので、その仕組みについて書いていきます。
ミニバッチ学習
ミニバッチ学習は、結果をあまり変えずに損失関数の値や勾配を求める時の計算量を減らす手法です。
ミニバッチ学習の概要
ミニバッチ学習を簡単に説明すると、
「汎化能力獲得のためにはたくさんの種類のデータが必要だが、損失関数の値や勾配を求めるためにはあまりたくさんのデータはいらない」というジレンマを解決するために、学習1stepで使うデータはデータセットのうち一部だけにする。
というものです。
汎化能力の獲得のためには
機械学習では、①学習用データ(データと答えのセット)を用いてモデルを学習、②学習されたモデルを用いてテストデータや実際のデータから答えを予測、という手順を踏みます。
この時、学習用データに含まれているデータなら答えが予測できるが、未知のデータ(テストデータなど)からは答えを予測できない状態になることがあります。これを過学習(over fitting)といいます。逆に、未知のデータに対しても答えを予測できる能力を汎化能力といいます。
基本的に、未知のデータに対して答えを予測するために機械学習を行うので、機械学習では汎化能力を獲得することが大きな目標となります。
過学習が起こる(=汎化能力が不足する)原因は、主に、モデルの複雑さに対して学習データ数が少ないことです。(学習データ数に対してモデルが複雑すぎるとも言えます) 特に、ディープラーニングのモデルは複雑になることが多いので、過学習が起きやすくなります。
これを防ぐ方法として、学習率を調整したり、正則化を行ったりなどいろいろありますが、最も効果があるのは、学習データの種類を増やすことです。
ということで、ディープラーニングで汎化能力を獲得するためにはたくさんの種類の学習データが必要です。
損失関数の値を求めるためには
損失関数の値を求める方法は前回書きましたが、データごとに予測結果と正解の誤差を求め、その平均を求めます。
この計算速度は、データ数が少なければ少ないほど速くなります。
ミニバッチ学習の仕組み
しかし、損失関数の値は平均値なので、ある程度のデータ数があれば、それ以上データ数を増やしても大きく変わることはありません。例えば、10種類に分類する学習データが10万個あった場合、「10万個のデータそれぞれの予測結果と正解の誤差の平均」と、10万個の中からランダムに1000個取り出してその「1000個のデータそれぞれの予測結果と正解の誤差の平均」は、ほとんど同じですが、計算にかかる時間は約100分の1です。
勾配を求める場合も同様です。
この性質を利用してミニバッチ学習では以下の手順で学習を進めます
①N個の学習データをn個に分けます。この時分けたそれぞれのデータをミニバッチといいます。
②n個のミニバッチをそれぞれ学習データとして順番に学習を行います。学習データに含まれるデータをすべて1回ずつ学習したとき(=すべてのミニバッチを1回ずつ学習したとき)、これを1エポックと呼びます
③これを繰り返します。何エポック繰り返すかは、損失関数の値の収束具合で変わります。
これがミニバッチ学習です
誤差逆伝播法
誤差逆伝播法は、結果を変えずに勾配を求めるときの計算量を減らす手法です。 前回の微分の定義に従った実装(数値微分といいます)では仕組みは理解しやすいですが計算量が多く、学習に時間がかかります。誤差逆伝播法では数値微分ではなく自動微分という方法で勾配を求めます。
自動微分
誤差逆伝播法で利用するのは自動微分のうちトップダウン型自動微分(リバースモード)と呼ばれるものです。
計算グラフ
自動微分の前に計算グラフについて書きます。
計算グラフは計算を関数と値のつながりとしてグラフにしたものです。
例えば(3+5)×10は以下のような図で表せます。
青い丸が値を、赤い四角が関数を表します。
連鎖律
自動微分では、微分法の連鎖律という性質を利用して微分を行っています。
連鎖律とは、合成関数の導関数はそれぞれの関数の導関数の積である、という性質です。
例:
この関数を計算グラフで表すと下の図のように表せます
計算グラフにおいて、合成関数の微分を求めるときは、それぞれの関数の微分を逆向きに順番に掛け合わせます。
それぞれの関数は、「右から来た値」に「その関数自身の微分」を掛け合わせて左に送り出します。これを右から順番に繰り返していくことで合成関数の微分を求めることができます。これを逆伝播といいます。逆伝播を開始する一番右は1から始めます。
ニューラルネットワークの逆伝播
ニューラルネットワークの計算もいくつもの単純な関数の合成関数だと考えれば、逆伝播で微分することができます。(=勾配を求めることができます)
前回のこのモデルでlossを求める場合、計算グラフは次のようになります。(今回の場合、青い丸はベクトルです)
x1*w1+x2*w2+x3*w3+bの計算をする部分をAffineとしています。
それぞれの関数(Affine,sigmoid,softmax,lossなど)の微分さえ求めてしまえば、ニューラルネットワークが何層になったとしても逆伝播で勾配を求めることができます。
数値微分では、「変数の個数」だけ順伝播を繰り返します。それに対して、自動微分では、「関数の個数」だけ掛け算を繰り返します。特にディープラーニングでは変数(=重み)の個数はとても多くなります。
ということで、自動微分を使うことで数値微分より高速に勾配を求めることができます。
私がした実験では、自動微分にすることで約1600倍速くなりました。(上のモデルよりもう少し複雑なモデルです)
まとめ
この記事で書いたこと
- ミニバッチ学習を使うと高速に学習できる
- 汎化能力のためにデータ数を増やしたいが計算速度のためにデータ数を減らしたいジレンマをミニバッチ学習で解消できる
- 自動微分では連鎖律を利用して複雑な関数を微分する
- 計算グラフという考え方
次回は、全結合層以外のニューラルネットワークについて書いていこうと思います。
ディープラーニングについて学ぶ上で「ゼロから作るDeep Leaning Pythonで学ぶディープラーニングの理論と実装」を参考にさせていただきました。
- [AI入門] ディープラーニングの仕組み ~その1:ニューラルネットワークってなに?~
- [AI入門] ディープラーニングの仕組み ~その2:学習を高速に行う仕組み~
- [AI入門] ディープラーニングの仕組み ~その3:CNNの仕組み~