見出し画像

バッチ正規化とは

この記事では、バッチ正規化(Batch Normalization)の仕組みや利点の解説をします。

バッチ正規化は画像系のモデルでよく使われます。入力データの正規化や標準化とは異なり、隠れ層の間で使われます。特に畳み込み層と活性化関数の間で使われることが多いです。

まず、バッチ正規化には次の効果があります。

  • 訓練が速く進む(損失値がはやく収束する)

  • 重みの初期化に神経質にならなくとも良い

  • 学習率を大きめに指定できる

バッチ正規化では以下の問題点もあります。

  • 小さいバッチでは効果が出ない

  • 回帰型ニューラルネットワークでは使えない

本記事では、上記の利点や問題点の理由を解説していきます。

バッチ正規化はバッチによる訓練をするところから始まるので、まずはその話から始めます。

バッチによる訓練

画像を使ったモデルの訓練を想定して話を進めます。

訓練用の画像がたくさんあるとします。メモリに収まりきらないので画像データを一定数のグループに分けて、それぞれのグループに対して処理を行うことにしたとします。

画像のバッチ

このように画像をまとめたものを一つの単位とし、バッチ(Batch)あるいはミニバッチ(Mini Batch)と呼びます。今記事では単にバッチと呼びます。また、分割する大きさをバッチサイズと呼びます。バッチサイズは色々と試して学習中の損失率の変化の具合などを見て決めます。

例えば、画像が16万枚あり、それを16枚ごとに分割したとするとバッチサイズは16で、データセットは1万個のバッチに分割されます。もっと大きなデータセットでもバッチ単位の処理になるので問題ありません。

またバッチ単位に小分けにすることによってニューラルネットワークのパラメータ(重みやバイアスなど)をより頻繁に更新することになるので学習が速く進みます。仮にバッチを使わずにデータセット全体を一度に処理できたとしてもパラメータの値を大幅に更新することはできないので、バッチ毎に処理しながら少しづつパラメータの更新をした方が結局は速く訓練が終わります。

つまり、ディープラーニングではバッチ処理を使用することで、大量のデータを効率的に処理することができます。

なお、バッチサイズとしては16、32、64、128、256…などがよく使われます。

ちなみに、16は2の4乗、32は2の5乗、64は2の6乗でありバッチサイズとして2の乗数がよく使われます。よく言われるのはCPUやGPUでのデータ交換では2の乗数のサイズが使われるためコンピュータのデータ処理の効率がよくなるというものです。しかし、PyTorchやTensorFlowなどはCPUやGPUの使用を最適化しており、バッチサイズが2の乗数でなくとも速度に影響はないという事例もあります。いずれにせよ、バッチサイズに関しては、ほぼ常識のように2の乗数が使われています。特にそうでない数字を使う理由もありません。

画像モデルを訓練するときはバッチ単位での入力を行います。よって、画像モデルはバッチ形式での入力データを想定した作りになっています。そのため、テストやプロダクションで一つの画像だけを使って推論を行う場合は、1画像のみのバッチを作って入力します。

入力データのシャッフル

なお、バッチ毎にモデルの訓練を始める前に、訓練用の画像の順番をシャッフル(Shuffle)します。シャッフルとは順番をランダムに並び替えることです。これは画像の並び順に不自然な規則性がないようにするためです。

例えば、データセット内で犬の画像が160枚連続で順番に並んでいたすると、バッチサイズが16ならば10個のバッチで連続して犬の画像ばかりになります。このようにデータに偏りがあると学習がスムーズに行えません。犬ばかりたくさん現れたらモデルが犬の確率が高くなるようにパラメータを変更するでしょう。その後に猫ばかりが続いたら今度は猫の確率が高くなるようにパラメータを変更して犬のことは忘れてしまうかもしれません。こういう問題は実際によくあることです。よって訓練データは必ずシャッフルします。

なお、シャッフルしても偶然によって偏ったバッチが生じる可能性はあります。なので、エポックが終了(すべてのバッチを処理)したら、再び訓練データをシャッフルします。こうすることでエポックをたくさん繰り返してもバッチの中身は毎回異なるものになります。つまり、偶然の偏りがあるバッチが生じてもそれが次回のエポックへと継続することはありません。

画像の標準化

さて、入力画像をモデルへと渡す前に正規化や標準化をします。画像データでは標準化を行うことが多いです。訓練用のデータセットのすべての画像の平均と標準偏差を使います。また、標準化は画像の各チャンネルごとに行われます。

標準化によって訓練用の画像データの各チャンネルは平均が0で標準偏差が1の分布に従うように変換されます。

なお、テストデータなどで推論を行う際も訓練データセット全体からの平均と標準偏差を使って標準化を行います。これはテストやプロダクションのデータも訓練画像と同様の分布に従っていると想定しているからです。逆に言うと訓練用のデータセットは最終的な使用環境での画像データの分布を代表するように集めたものである必要があります。

共変量シフト

ここまでの話をまとめると、入力データはシャッフルされ、標準化され、バッチごとにモデルへと渡されます。さらに、モデルの隠れ層(畳み込み層など)が画像データを処理してから活性化関数を適用し、次の層へと渡していきます。

入力データの標準化

ところが、ここで問題が生じる可能性があります。隠れ層によってデータの分布が変わります。それが次の隠れ層を通過すると、さらに分布が変わります。つまり層を通過するたびにデータの分布が変わります。つまり転がる雪のように分布の変化が積み重なっていきます。

ニューラルネットワークのパラメータ(重みやバイアス)が更新され、次回のバッチが中間層を通り抜けると、データの分布は以前とは異なる変化をすることになります。つまり、ニューラルネットワークの中間層から見るとバッチ毎にデータの分布が大幅に変更されることになり学習を困難にします。

わかりやすく言い切ってしまうと、毎回分布が変化し続けるデータを渡されて「特徴量を抽出しろ」と言われているようなものです。大きくランダムに変化するデータの分布から役に立つ特徴を引き出すのは困難です。

つまり、せっかく入力データを標準化したとしても中間層から見るとデータの分布が毎バッチごとにスケールが異なったり平均が上下のシフトしていることになります。

共変量シフト

これを内部共変量シフト(Internal Covariate Shift)あるいは単に共変量シフト(Covariate Shift)と呼びます。「内部」とつけるのは、分布のシフトがニューラルネットワークの内部で起きていることを強調しています。

「内部」ではない共変量シフトは外部の要因で起きます。例えば、若い年齢の男性のデータで訓練したモデルを年配の女性のデータに適応した場合は、外部要因による共変量シフトが生じます。これは訓練用のデータセットが最終的な使用環境での画像データの分布を代表するように集めたものであれば問題ありません。

よって、この記事では解説する共変量シフトは「内部」である前提なので、単に「共変量シフト」と呼びます。

バッチ正規化はこの共変量シフトを解決する手法として提案されました。

ここから先は

4,502字 / 1画像

キカベン・読み放題

¥1,000 / 月
初月無料
このメンバーシップの詳細

この記事が気に入ったらサポートをしてみませんか?