如果我想在Keras中使用BatchNormalization函数,那么我是否只需要在开头调用它一次?
我为它阅读了这个文档: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)
我问,因为如果我运行包含批量规范化的第二行的代码,如果我运行没有第二行的代码,我得到类似的输出.所以要么我没有在正确的位置调用该功能,要么我认为它没有那么大的差别.
只是为了更详细地回答这个问题,并且正如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的回答,但我还没有正确的权限,所以我只想把它放在这里.
批量标准化在激活功能之后效果最好,这里或这里是原因:它是为了防止内部协变量偏移而开发的.当整个训练期间层的激活的分布发生显着变化时,发生内部协变量偏移.使用批量标准化,以便输入(以及这些输入实际上是激活函数的结果)到特定层的分布不会随着时间的推移而改变,因为每个批次的参数更新(或者至少允许它更改)以有利的方式).它使用批量统计进行规范化,然后使用批量标准化参数(原始论文中的gamma和beta)"以确保插入网络中的转换可以表示身份转换"(引自原始论文).但重点是我们正在尝试将输入规范化为一个层,因此它应该始终紧接在网络中的下一层之前.激活功能之后是否依赖于所讨论的体系结构.
关于是否应该在当前层的非线性或前一层的激活之前应用BN,该线程存在一些争论.
虽然没有正确答案,但批量标准化的作者说它 应该在当前层的非线性之前立即应用.原因(引自原始论文) -
"我们在非线性之前立即加入BN变换,通过归一化x = Wu + b.我们也可以对层输入u进行归一化,但由于你很可能是另一个非线性的输出,它的分布形状可能会在训练,约束其第一和第二时刻不会消除协变量偏移.相反,Wu + b更可能具有对称的非稀疏分布,即"更高斯"(Hyv¨arinen&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)))