KerasでBatchNormalization関数を使用したい場合は、最初に1回だけ呼び出す必要がありますか?
私はこのドキュメントを読みました。 http://keras.io/layers/normalization/
どこに電話したらいいのかわかりません。以下はそれを使用しようとしている私のコードです。
model = Sequential()
keras.layers.normalization.BatchNormalization(epsilon=1e-06, mode=0, momentum=0.9, weights=None)
model.add(Dense(64, input_dim=14, init='uniform'))
model.add(Activation('tanh'))
model.add(Dropout(0.5))
model.add(Dense(64, init='uniform'))
model.add(Activation('tanh'))
model.add(Dropout(0.5))
model.add(Dense(2, init='uniform'))
model.add(Activation('softmax'))
sgd = SGD(lr=0.1, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='binary_crossentropy', optimizer=sgd)
model.fit(X_train, y_train, nb_Epoch=20, batch_size=16, show_accuracy=True, validation_split=0.2, verbose = 2)
バッチ正規化を含む2行目でコードを実行した場合と2行目を使用せずにコードを実行した場合にも同様の出力が得られるためです。だから私は正しい場所で関数を呼んでいないか、私はそれがそれほど大きな違いはないと思います。
もう少し詳細にこの質問に答えるために、そしてPavelが言ったように、バッチ正規化は単なる別の層なので、あなたはそれをあなたの望むネットワークアーキテクチャを作成するためにそのまま使うことができます。
一般的なユースケースは、ネットワーク内の線形レイヤと非線形レイヤの間でBNを使用することです。これは、アクティブ化関数への入力を正規化し、アクティブ化関数の線形セクション(Sigmoidなど)を中心に配置します。ちょっとした議論があります ここで
上記の場合、これは次のようになります。
# import BatchNormalization
from keras.layers.normalization import BatchNormalization
# instantiate model
model = Sequential()
# we can think of this chunk as the input layer
model.add(Dense(64, input_dim=14, init='uniform'))
model.add(BatchNormalization())
model.add(Activation('tanh'))
model.add(Dropout(0.5))
# we can think of this chunk as the hidden layer
model.add(Dense(64, init='uniform'))
model.add(BatchNormalization())
model.add(Activation('tanh'))
model.add(Dropout(0.5))
# we can think of this chunk as the output layer
model.add(Dense(2, init='uniform'))
model.add(BatchNormalization())
model.add(Activation('softmax'))
# setting up the optimization of our weights
sgd = SGD(lr=0.1, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='binary_crossentropy', optimizer=sgd)
# running the fitting
model.fit(X_train, y_train, nb_Epoch=20, batch_size=16, show_accuracy=True, validation_split=0.2, verbose = 2)
これが物事をもう少し明確にすることを願っています。
このスレッドは誤解を招くようです。 Lucas Ramadanの答えについてコメントしようとしたが、私はまだ正しい特権を持っていないので、これをここに置くだけにする。
バッチ正規化はアクティベーション関数の後で最も効果的に機能します。 こちら または こちら は理由:それは内部共変量シフトを防ぐために開発されました。内部共変量シフトは、層の活性化の分布がトレーニングを通して大幅にシフトすると発生します。バッチ正規化を使用して、特定のレイヤーへの入力の分布(およびこれらの入力は文字通りアクティブ化関数の結果)が、各バッチからのパラメーター更新のために時間の経過とともに変化しないようにします。有利な方法で)。それは正規化をするためにバッチ統計を使い、それからバッチ正規化パラメータ(オリジナルの紙の中のガンマとベータ)を使って「ネットワークに挿入された変換が恒等変換を表すことができるようにする」。しかし重要なのは、入力をレイヤーに正規化しようとしているため、ネットワーク内の次のレイヤーの直前に移動する必要があるということです。それが活性化機能の後であるかどうかは、問題のアーキテクチャに依存します。
このスレッドは、現在のレイヤの非線形性の前にBNを適用すべきか、前のレイヤのアクティブ化にBNを適用すべきかについて、かなりの議論があります。
正しい答えはありませんが、Batch Normalizationの作者は次のように述べています。これは現在のレイヤの非線形性の直前に適用する必要があります。原著論文から引用)
「x = Wu + bを正規化することにより、非線形性の直前にBN変換を追加します。また、レイヤ入力uを正規化することもできますが、uは別の非線形性の出力であるため、その分布の形状は対照的に、Wu + bは対称的な非スパース分布、つまり「よりガウス分布」を持つ可能性が高くなります(Hyvarinen&Oja、2000)。正規化すると安定した分布で活性化する可能性があります。」
Kerasはuse_bias=False
オプションをサポートするようになったので、次のように書くことで計算を節約できます
model.add(Dense(64, use_bias=False))
model.add(BatchNormalization(axis=bn_axis))
model.add(Activation('tanh'))
または
model.add(Convolution2D(64, 3, 3, use_bias=False))
model.add(BatchNormalization(axis=bn_axis))
model.add(Activation('relu'))
現在はConv2D
の後にReLu
の後にBatchNormalization
レイヤーが続く傾向があります。そこで私はそれらすべてを一度に呼び出すための小さな関数を作りました。モデル定義をずっときれいにして読みやすくします。
def Conv2DReluBatchNorm(n_filter, w_filter, h_filter, inputs):
return BatchNormalization()(Activation(activation='relu')(Convolution2D(n_filter, w_filter, h_filter, border_mode='same')(inputs)))
これは別の種類のレイヤーなので、モデルの適切な場所にレイヤーとして追加する必要があります。
model.add(keras.layers.normalization.BatchNormalization())
こちらの例をご覧ください。 https://github.com/fchollet/keras/blob/master/examples/kaggle_otto_nn.py
バッチ正規化は、活性化の平均とスケーリングを調整することによって、隠れ層と同様に入力層を正規化するために使用されます。ディープニューラルネットワークにおける追加の層を用いたこの正規化効果のために、ネットワークは勾配を消失または爆発させることなくより高い学習率を使用することができる。さらに、バッチ正規化は、一般化しやすいようにネットワークを正規化します。したがって、過剰適合を軽減するためにドロップアウトを使用する必要はありません。
Kerasのsay、Dense()またはConv2D()を使用して線形関数を計算した直後に、BatchNormalization()を使用してレイヤー内の線形関数を計算し、次にActivation()を使用して非線形性をレイヤーに追加します。
from keras.layers.normalization import BatchNormalization
model = Sequential()
model.add(Dense(64, input_dim=14, init='uniform'))
model.add(BatchNormalization(epsilon=1e-06, mode=0, momentum=0.9, weights=None))
model.add(Activation('tanh'))
model.add(Dropout(0.5))
model.add(Dense(64, init='uniform'))
model.add(BatchNormalization(epsilon=1e-06, mode=0, momentum=0.9, weights=None))
model.add(Activation('tanh'))
model.add(Dropout(0.5))
model.add(Dense(2, init='uniform'))
model.add(BatchNormalization(epsilon=1e-06, mode=0, momentum=0.9, weights=None))
model.add(Activation('softmax'))
sgd = SGD(lr=0.1, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='binary_crossentropy', optimizer=sgd)
model.fit(X_train, y_train, nb_Epoch=20, batch_size=16, show_accuracy=True,
validation_split=0.2, verbose = 2)
バッチ正規化はどのように適用されますか?
レイヤlにa [l-1]を入力したとします。また、レイヤlの重みW [l]とバイアス単位b [l]があります。層lについて計算された(すなわち非線形性を加えた後の)活性化ベクトルをa [l]とし、非線形性を加える前のベクトルをz [l]とする。
隠れ層のスケールを変更する新しいパラメータγとβを次のように定義します。
z_norm [l] =γ.Z_temp[l] +β
このコードの抜粋では、Dense()はa [l-1]を受け取り、W [l]を使用してz [l]を計算します。それから即時のBatchNormalization()はz_norm [l]を与えるために上記のステップを実行します。それから即時のActivation()はtanh(z_norm [l])を計算して[1]を得る。
a[l] = tanh(z_norm[l])