web-dev-qa-db-ja.com

keras BatchNormalization軸の明確化

Keras BatchNormalization layer はデフォルト値として_axis=-1_を使用し、フィーチャ軸は通常正規化されていると述べています。これはなぜですか?

私は StandardScaler のようなものを使用することに慣れているので、これは驚くべきことだと思います。これは_axis=0_を使用することと同等です。これにより、機能が個別に正規化されます。

機能とは対照的に、サンプルがケラでデフォルトで個別に正規化される(つまり、_axis=-1_)理由はありますか?

編集:具体性の例

各フィーチャの平均および分散がゼロになるようにデータを変換することは一般的です。このモックデータセットの「ゼロ平均」部分を考えてみましょう。各行はサンプルです。

_>>> data = np.array([[   1,   10,  100, 1000],
                     [   2,   20,  200, 2000],
                     [   3,   30,  300, 3000]])

>>> data.mean(axis=0)
array([    2.,    20.,   200.,  2000.])

>>> data.mean(axis=1)
array([ 277.75,  555.5 ,  833.25])
_

_axis=0_の平均とは対照的に、_axis=1_の平均を減算するほうが理にかなっているのではないでしょうか。 _axis=1_を使用すると、単位とスケールが完全に異なる場合があります。

編集2:

(このペーパー のセクション3の最初の方程式は、(m、n)形状のデータセットがある場合、_axis=0_を使用して、各特徴の期待値と分散を個別に計算する必要があることを示唆しているようです。 mはサンプルの数、nは特徴の数です。

編集3:別の例

おもちゃのデータセットでBatchNormalizationが計算している平均と分散の次元を確認したいと思いました。

_import pandas as pd
import numpy as np
from sklearn.datasets import load_iris

from keras.optimizers import Adam
from keras.models import Model
from keras.layers import BatchNormalization, Dense, Input


iris = load_iris()
X = iris.data
y = pd.get_dummies(iris.target).values

input_ = Input(shape=(4, ))
norm = BatchNormalization()(input_)
l1 = Dense(4, activation='relu')(norm)
output = Dense(3, activation='sigmoid')(l1)

model = Model(input_, output)
model.compile(Adam(0.01), 'categorical_crossentropy')
model.fit(X, y, epochs=100, batch_size=32)

bn = model.layers[1]
bn.moving_mean  # <tf.Variable 'batch_normalization_1/moving_mean:0' shape=(4,) dtype=float32_ref>
_

入力Xの形状は(150、4)であり、BatchNormalizationレイヤーで計算された4の意味は、_axis=0_で動作したことを意味します。

BatchNormalizationのデフォルトが_axis=-1_である場合、150の手段があるべきではありませんか?

14
trianta2

混乱は、axisではなく_np.mean_でのBatchNormalizationの意味によるものです。

軸に沿って平均を取ると、その次元が縮小され、他のすべての次元が保持されます。あなたの例では、data.mean(axis=0)dataの垂直寸法である_0-axis_を折りたたみます。

軸に沿ってBatchNormalizationを計算するとき、配列の次元を保存し、平均値と標準偏差他のすべての軸で正規化します。したがって、あなたの_2D_の例BatchNormalizationと_axis=1_ isを使用すると、期待どおりに_axis=0_の平均を減算します。これが_bn.moving_mean_が_(4,)_の形をしている理由です。

19
Imran

私はこの投稿が古いことを知っていますが、混乱がまだKerasのドキュメントに残っているため、まだ答えています。これを理解するためにコードを調べる必要がありました。

  1. 整数として文書化されている軸変数は、実際には複数の軸を示す整数のリストである場合があります。したがって、たとえば入力にNHWCまたはNCHW形式の画像が含まれている場合、OPが希望する方法でBatchNormalizationを実行する(つまり、バッチディメンションのみを正規化する)場合は、axis = [1,2,3]を指定します。
  2. 軸リスト(または整数)には、平均と分散の計算中に削減する望まないの軸を含める必要があります。言い換えれば、これは正規化する軸に沿った補完です。従来の「軸」の定義を使用した場合のドキュメントの表示とは正反対です。したがって、たとえば入力Iが(N、H、W、C)または(N、C、H、W)の場合-つまり、最初の次元はバッチディメンションであり、平均と分散のみをバッチディメンション全体で計算する必要がありました。 axis = [1,2,3]を指定する必要があります。これにより、Kerasは形状M(1、H、W、C)または(1、C、H、W)の平均Mと分散Vテンソルをそれぞれ計算します。つまり、バッチディメンションは、集計(つまり平均または、分散は最初の次元で計算されます)。 (I-M)や(I-M)/ Vなどのその後の操作では、MとVの最初の次元がバッチのN個のサンプルすべてにブロードキャストされます。
  3. BatchNormレイヤーは、この例では、axes =(1、)を指定してtf.nn.momentsを呼び出します。これは、tf.nn.momentsの軸の定義が正しいためです。
  4. 同様に、tf.nn.momentsはtf.nn.reduce_meanを呼び出します。ここでも、軸の定義は正しいものです(つまり、tf.keras.layers.BatchNormalizationの反対です)。
  5. とはいえ、BatchNormalizationペーパーでは、HxW空間マップ全体をバッチディメンション(N)に加えて正規化することを推奨しています。したがって、そのアドバイスに従う場合、軸にはチャネルディメンション(C)のみが含まれます。これは、削減したくない唯一の残りのディメンションだからです。 Kerasのドキュメントはおそらく非常に謎めいていますが、これについてほのめかしています。
3

ミニバッチが行列の場合[〜#〜] a [〜#〜]mxn、つまりmサンプルおよびn機能、正規化軸はaxis = 0。あなたが言ったように、私たちが望むのは、すべての機能を個別に正規化することです、デフォルトのaxis = -1は畳み込み層で使用され、数字データセットの次元は通常(samples、width、height、channal)channal axis(最後の軸)でバッチサンプルが正規化されます。

0
Hanrong Zheng