Keras 的批量归一化层破坏了 PlatoBlockchain 数据智能。垂直搜索。人工智能。

Keras的批处理规范化层已损坏

更新:不幸的是,我对Keras的Pull-Request更改了批处理规范化层的行为,但不被接受。 您可以阅读详细信息 此处。 对于那些敢于自定义实现的人,您可以在 我的分支。 我可能会对其进行维护,并将其与Keras的最新稳定版本合并(2.1.6, 2.2.22.2.4),只要我使用了,但没有任何承诺。

从事深度学习的大多数人都曾经使用过或听说过 Keras。 对于那些还没有的人来说,这是一个很棒的库,它抽象了底层的深度学习框架,例如TensorFlow,Theano和CNTK,并提供了一个 高级API 用于训练人工神经网络。 它易于使用,能够快速建立原型,并拥有一个友好的活跃社区。 我一直在大量使用它,并定期为该项目做出贡献很长时间,并且我绝对将其推荐给想要从事深度学习工作的任何人。

即使Keras使我的生活更轻松,但很多时候我还是被Batch Normalization层的奇怪行为所困扰。 它的默认行为已随着时间而改变,尽管如此,它仍然会给许多用户带来问题,因此,有几个相关的问题 开放式问题 在Github上。 在此博客文章中,我将尝试说明为什么Keras的BatchNormalization层在Transfer Learning中不能很好地发挥作用,我将提供解决问题的代码,并提供有关结果的示例。 补丁.

在下面的小节中,我将介绍深度学习中如何使用转移学习,什么是批处理规范化层,learnining_phase如何工作以及Keras如何随时间改变BN行为。 如果您已经知道这些,则可以安全地直接跳至第2节。

1.1使用转移学习对深度学习至关重要

过去批评深度学习的原因之一是它需要太多数据。 这并非总是如此; 有几种解决此限制的技术,其中之一是转移学习。

假设您正在使用Computer Vision应用程序,并且想要构建一个区分猫和狗的分类器。 您实际上不需要数百万张猫/狗图像来训练模型。 相反,您可以使用预先训练的分类器,并以较少的数据微调顶部卷积。 其背后的想法是,由于预训练模型适合图像,因此底部卷积可以识别线条,边缘和其他有用模式等特征,这意味着您可以将其权重用作良好的初始化值,也可以使用数据对网络进行部分重新训练。
Keras 的批量归一化层破坏了 PlatoBlockchain 数据智能。垂直搜索。人工智能。
Keras随附了几个经过预训练的模型,以及有关如何微调模型的易于使用的示例。 您可以阅读更多关于 文件.

1.2什么是批标准化层?

批次标准化层是Ioffe和Szegedy于2014年引入的。 它通过标准化前一层的输出来解决消失的梯度问题,通过减少所需的迭代次数来加快训练速度,并且可以训练更深的神经网络。 确切解释其工作原理超出了本文的范围,但是我强烈建议您阅读 原始纸。 过于简单的解释是,它通过减去均值并除以标准差来重新缩放输入。 如果需要,它还可以学会撤消转换。
Keras 的批量归一化层破坏了 PlatoBlockchain 数据智能。垂直搜索。人工智能。

1.3 Keras中的learning_phase是什么?

在训练和推理模式下,某些层的操作有所不同。 最著名的例子是批处理规范化和退出层。 对于BN,在训练过程中,我们使用小批量的均值和方差来重新调整输入。 另一方面,在推论过程中,我们使用训练期间估计的移动平均值和方差。

Keras知道以哪种模式运行,因为它具有一种称为 学习阶段。 学习阶段控制网络是处于训练还是测试模式。 如果不是由用户手动设置的,则在fit()期间,网络以learning_phase = 1(训练模式)运行。 在生成预测时(例如,当我们调用predict()和evaluate()方法或在fit()的验证步骤时),网络以learning_phase = 0(测试模式)运行。 即使不建议这样做,用户也可以将learning_phase静态更改为特定值,但这需要在将任何模型或张量添加到图中之前发生。 如果learning_phase是静态设置的,则Keras将被锁定为用户选择的任何一种模式。

1.4 Keras如何逐步实现批量标准化?

Keras多次更改了批处理规范化的行为,但最新的重大更新发生在Keras 2.1.3中。 在v2.1.3之前,冻结BN层(可训练= False)时,它会不断更新其批次统计信息,这使用户感到头疼。

这不仅是一个奇怪的政策,实际上是错误的。 想象在卷积之间存在一个BN层; 如果图层冻结,则不会发生任何变化。 如果我们确实部分地更新了其权重并且下一层也被冻结,则它们将永远没有机会适应迷你批处理统计信息的更新,从而导致更高的误差。 幸运的是,从版本2.1.3开始,冻结BN层时,它不再更新其统计信息。 但是够了吗? 如果您使用的是转移学习,则不会。

下面,我准确地描述了问题所在,并勾画出解决该问题的技术方案。 我还提供了一些示例来展示模型对模型精度的影响。 补丁 被应用。

2.1问题的技术说明

当前Keras实施的问题在于,当冻结BN层时,它会在训练期间继续使用小批量统计信息。 我相信冻结BN时更好的方法是使用在训练中学到的移动均值和方差。 为什么? 出于同样的原因,冻结层时迷你批处理统计信息不应更新:由于下一层的训练不正确,可能导致结果不佳。

假设您正在构建计算机视觉模型,但是没有足够的数据,那么您决定使用Keras的预训练CNN之一并对其进行微调。 不幸的是,这样做不能保证BN层中新数据集的均值和方差与原始数据集的均值和方差相似。 请记住,目前,在训练过程中,您的网络将始终使用小批量统计信息,无论BN层是否冻结。 同样在推理过程中,您将使用先前了解的冻结BN层统计信息。 因此,如果您微调顶层,则它们的权重将被调整为 数据集。 不过,在推论过程中,他们将收到按比例缩放的数据 不同 因为的均值/方差 原版的 将使用数据集。
Keras 的批量归一化层破坏了 PlatoBlockchain 数据智能。垂直搜索。人工智能。
以上,出于演示目的,我提供了一种简单(且不切实际)的体系结构。 假设我们从卷积k + 1到网络顶部(右侧)微调模型,并冻结底部(左侧)。 在训练期间,从1到k的所有BN层都将使用训练数据的均值/方差。 如果每个BN的均值和方差与预训练期间学习的均方差和方差不接近,则这将对冻结的ReLU产生负面影响。 这也将导致网络的其余部分(来自CONV k + 1和更高版本)使用与推断期间将接收到的缩放比例不同的输入进行训练。 在训练过程中,您的网络可以适应这些变化,但是,当您切换到预测模式时,Keras将使用不同的标准化统计数据,这将使下一层输入的分布迅速,从而导致结果不佳。

2.2如何检测自己是否受到影响?

一种检测方法是将Keras的学习阶段静态设置为1(训练模式)和0(测试模式),然后分别评估模型。 如果同一数据集的准确性存在显着差异,那么您将受到问题的影响。 值得指出的是,由于在Keras中实现learning_phase机制的方式,通常不建议将其弄乱。 learning_phase的更改将不会影响已经编译和使用的模型; 正如您将在下一部分的示例中看到的那样,执行此操作的最佳方法是从干净的会话开始,然后在图中定义任何张量之前更改learning_phase。

在使用二进制分类器时检测问题的另一种方法是检查准确性和AUC。 如果准确性接近50%,但AUC接近1(并且您在同一数据集上观察到训练/测试模式之间的差异),则可能是由于BN统计信息导致概率超出范围。 同样,对于回归,您可以使用MSE和Spearman的相关性进行检测。

2.3我们如何解决?

我相信,如果冻结的BN层实际上只是这样:永久锁定在测试模式下,则可以解决此问题。 在实现方面,可训练标记需要成为计算图的一部分,而BN的行为不仅需要取决于learning_phase,而且还取决于可训练属性的值。 您可以在以下位置找到我的实施细节 Github上.

通过应用以上修复程序,当冻结BN层时,它将不再使用小批量统计信息,而是使用在训练中学习的统计信息。 结果,训练和测试模式之间不会存在差异,从而提高了准确性。 显然,当BN层未冻结时,它将在训练期间继续使用小批量统计信息。

2.4评估补丁的效果

即使我最近写了上述实现,其背后的想法也已通过使用各种具有相同效果的变通办法,在现实世界的问题上进行了严格的测试。 例如,可以通过将网络分为两部分(冻结和未冻结)并执行缓存的训练(将数据通过冻结模型传递一次,然后使用它们来训练未冻结的网络)来避免训练和测试模式之间的差异。 但是,由于“相信我,我之前已经做过”通常不起作用,因此在下面提供一些示例,这些示例在实践中展示了新实现的效果。

以下是有关实验的一些要点:

  1. 我将使用少量数据有意过拟合模型,并在同一数据集中训练和验证模型。 这样,我期望训练/验证数据集具有接近完美的准确性和相同的性能。
  2. 如果在验证期间我对同一数据集的准确性大大降低,我将明确指出当前的BN策略会在推理过程中对模型的性能产生负面影响。
  3. 任何预处理都将在Generator之外进行。 这样做是为了解决v2.1.5中引入的错误(当前已在即将发布的v2.1.6和最新的master中修复)。
  4. 我们将迫使Keras在评估过程中使用不同的学习阶段。 如果发现报告的准确性之间存在差异,我们将知道我们受到当前BN政策的影响。

实验代码如下所示:

import numpy as np
from keras.datasets import cifar10
from scipy.misc import imresize

from keras.preprocessing.image import ImageDataGenerator
from keras.applications.resnet50 import ResNet50, preprocess_input
from keras.models import Model, load_model
from keras.layers import Dense, Flatten
from keras import backend as K


seed = 42
epochs = 10
records_per_class = 100

# We take only 2 classes from CIFAR10 and a very small sample to intentionally overfit the model.
# We will also use the same data for train/test and expect that Keras will give the same accuracy.
(x, y), _ = cifar10.load_data()

def filter_resize(category):
   # We do the preprocessing here instead in the Generator to get around a bug on Keras 2.1.5.
   return [preprocess_input(imresize(img, (224,224)).astype('float')) for img in x[y.flatten()==category][:records_per_class]]

x = np.stack(filter_resize(3)+filter_resize(5))
records_per_class = x.shape[0] // 2
y = np.array([[1,0]]*records_per_class + [[0,1]]*records_per_class)


# We will use a pre-trained model and finetune the top layers.
np.random.seed(seed)
base_model = ResNet50(weights='imagenet', include_top=False, input_shape=(224, 224, 3))
l = Flatten()(base_model.output)
predictions = Dense(2, activation='softmax')(l)
model = Model(inputs=base_model.input, outputs=predictions)

for layer in model.layers[:140]:
   layer.trainable = False

for layer in model.layers[140:]:
   layer.trainable = True

model.compile(optimizer='sgd', loss='categorical_crossentropy', metrics=['accuracy'])
model.fit_generator(ImageDataGenerator().flow(x, y, seed=42), epochs=epochs, validation_data=ImageDataGenerator().flow(x, y, seed=42))

# Store the model on disk
model.save('tmp.h5')


# In every test we will clear the session and reload the model to force Learning_Phase values to change.
print('DYNAMIC LEARNING_PHASE')
K.clear_session()
model = load_model('tmp.h5')
# This accuracy should match exactly the one of the validation set on the last iteration.
print(model.evaluate_generator(ImageDataGenerator().flow(x, y, seed=42)))


print('STATIC LEARNING_PHASE = 0')
K.clear_session()
K.set_learning_phase(0)
model = load_model('tmp.h5')
# Again the accuracy should match the above.
print(model.evaluate_generator(ImageDataGenerator().flow(x, y, seed=42)))


print('STATIC LEARNING_PHASE = 1')
K.clear_session()
K.set_learning_phase(1)
model = load_model('tmp.h5')
# The accuracy will be close to the one of the training set on the last iteration.
print(model.evaluate_generator(ImageDataGenerator().flow(x, y, seed=42)))

让我们检查一下Keras v2.1.5的结果:

Epoch 1/10
1/7 [===>..........................] - ETA: 25s - loss: 0.8751 - acc: 0.5312
2/7 [=======>......................] - ETA: 11s - loss: 0.8594 - acc: 0.4531
3/7 [===========>..................] - ETA: 7s - loss: 0.8398 - acc: 0.4688 
4/7 [================>.............] - ETA: 4s - loss: 0.8467 - acc: 0.4844
5/7 [====================>.........] - ETA: 2s - loss: 0.7904 - acc: 0.5437
6/7 [========================>.....] - ETA: 1s - loss: 0.7593 - acc: 0.5625
7/7 [==============================] - 12s 2s/step - loss: 0.7536 - acc: 0.5744 - val_loss: 0.6526 - val_acc: 0.6650

Epoch 2/10
1/7 [===>..........................] - ETA: 4s - loss: 0.3881 - acc: 0.8125
2/7 [=======>......................] - ETA: 3s - loss: 0.3945 - acc: 0.7812
3/7 [===========>..................] - ETA: 2s - loss: 0.3956 - acc: 0.8229
4/7 [================>.............] - ETA: 1s - loss: 0.4223 - acc: 0.8047
5/7 [====================>.........] - ETA: 1s - loss: 0.4483 - acc: 0.7812
6/7 [========================>.....] - ETA: 0s - loss: 0.4325 - acc: 0.7917
7/7 [==============================] - 8s 1s/step - loss: 0.4095 - acc: 0.8089 - val_loss: 0.4722 - val_acc: 0.7700

Epoch 3/10
1/7 [===>..........................] - ETA: 4s - loss: 0.2246 - acc: 0.9375
2/7 [=======>......................] - ETA: 3s - loss: 0.2167 - acc: 0.9375
3/7 [===========>..................] - ETA: 2s - loss: 0.2260 - acc: 0.9479
4/7 [================>.............] - ETA: 2s - loss: 0.2179 - acc: 0.9375
5/7 [====================>.........] - ETA: 1s - loss: 0.2356 - acc: 0.9313
6/7 [========================>.....] - ETA: 0s - loss: 0.2392 - acc: 0.9427
7/7 [==============================] - 8s 1s/step - loss: 0.2288 - acc: 0.9456 - val_loss: 0.4282 - val_acc: 0.7800

Epoch 4/10
1/7 [===>..........................] - ETA: 4s - loss: 0.2183 - acc: 0.9688
2/7 [=======>......................] - ETA: 3s - loss: 0.1899 - acc: 0.9844
3/7 [===========>..................] - ETA: 2s - loss: 0.1887 - acc: 0.9792
4/7 [================>.............] - ETA: 1s - loss: 0.1995 - acc: 0.9531
5/7 [====================>.........] - ETA: 1s - loss: 0.1932 - acc: 0.9625
6/7 [========================>.....] - ETA: 0s - loss: 0.1819 - acc: 0.9688
7/7 [==============================] - 8s 1s/step - loss: 0.1743 - acc: 0.9747 - val_loss: 0.3778 - val_acc: 0.8400

Epoch 5/10
1/7 [===>..........................] - ETA: 3s - loss: 0.0973 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0828 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0851 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0897 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0928 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0936 - acc: 1.0000
7/7 [==============================] - 8s 1s/step - loss: 0.1337 - acc: 0.9838 - val_loss: 0.3916 - val_acc: 0.8100

Epoch 6/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0747 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0852 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0812 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0831 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0779 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0766 - acc: 1.0000
7/7 [==============================] - 8s 1s/step - loss: 0.0813 - acc: 1.0000 - val_loss: 0.3637 - val_acc: 0.8550

Epoch 7/10
1/7 [===>..........................] - ETA: 1s - loss: 0.2478 - acc: 0.8750
2/7 [=======>......................] - ETA: 2s - loss: 0.1966 - acc: 0.9375
3/7 [===========>..................] - ETA: 2s - loss: 0.1528 - acc: 0.9583
4/7 [================>.............] - ETA: 1s - loss: 0.1300 - acc: 0.9688
5/7 [====================>.........] - ETA: 1s - loss: 0.1193 - acc: 0.9750
6/7 [========================>.....] - ETA: 0s - loss: 0.1196 - acc: 0.9792
7/7 [==============================] - 8s 1s/step - loss: 0.1084 - acc: 0.9838 - val_loss: 0.3546 - val_acc: 0.8600

Epoch 8/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0539 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.0900 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0815 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0740 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0700 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0701 - acc: 1.0000
7/7 [==============================] - 8s 1s/step - loss: 0.0695 - acc: 1.0000 - val_loss: 0.3269 - val_acc: 0.8600

Epoch 9/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0306 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0377 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0898 - acc: 0.9583
4/7 [================>.............] - ETA: 1s - loss: 0.0773 - acc: 0.9688
5/7 [====================>.........] - ETA: 1s - loss: 0.0742 - acc: 0.9750
6/7 [========================>.....] - ETA: 0s - loss: 0.0708 - acc: 0.9792
7/7 [==============================] - 8s 1s/step - loss: 0.0659 - acc: 0.9838 - val_loss: 0.3604 - val_acc: 0.8600

Epoch 10/10
1/7 [===>..........................] - ETA: 3s - loss: 0.0354 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0381 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0354 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0828 - acc: 0.9688
5/7 [====================>.........] - ETA: 1s - loss: 0.0791 - acc: 0.9750
6/7 [========================>.....] - ETA: 0s - loss: 0.0794 - acc: 0.9792
7/7 [==============================] - 8s 1s/step - loss: 0.0704 - acc: 0.9838 - val_loss: 0.3615 - val_acc: 0.8600

DYNAMIC LEARNING_PHASE
[0.3614931714534759, 0.86]

STATIC LEARNING_PHASE = 0
[0.3614931714534759, 0.86]

STATIC LEARNING_PHASE = 1
[0.025861846953630446, 1.0]

正如我们在上面看到的,在训练过程中,模型可以很好地学习数据,并在训练集上达到接近完美的准确性。 仍在每次迭代结束时,在同一数据集上评估模型时,我们在损失和准确性上会产生明显差异。 注意,我们不应该得到这个。 我们有意过拟合了特定数据集上的模型,并且训练/验证数据集是相同的。

训练完成后,我们使用3种不同的learning_phase配置评估模型:动态,静态= 0(测试模式)和静态= 1(训练模式)。 如我们所见,前两种配置在损失和准确性方面将提供相同的结果,并且它们的值与上次迭代中验证集上模型报告的准确性相匹配。 但是,一旦我们切换到训练模式,就会发现巨大的差异(改进)。 为什么呢? 如前所述,调整网络的权重以期望接收按训练数据的均值/方差缩放的数据。 不幸的是,这些统计数据与存储在BN层中的统计数据不同。 由于BN层已冻结,因此这些统计信息从未更新过。 BN统计值之间的这种差异导致推理过程中准确性的下降。

让我们看看应用了 补丁:

Epoch 1/10
1/7 [===>..........................] - ETA: 26s - loss: 0.9992 - acc: 0.4375
2/7 [=======>......................] - ETA: 12s - loss: 1.0534 - acc: 0.4375
3/7 [===========>..................] - ETA: 7s - loss: 1.0592 - acc: 0.4479 
4/7 [================>.............] - ETA: 4s - loss: 0.9618 - acc: 0.5000
5/7 [====================>.........] - ETA: 2s - loss: 0.8933 - acc: 0.5250
6/7 [========================>.....] - ETA: 1s - loss: 0.8638 - acc: 0.5417
7/7 [==============================] - 13s 2s/step - loss: 0.8357 - acc: 0.5570 - val_loss: 0.2414 - val_acc: 0.9450

Epoch 2/10
1/7 [===>..........................] - ETA: 4s - loss: 0.2331 - acc: 0.9688
2/7 [=======>......................] - ETA: 2s - loss: 0.3308 - acc: 0.8594
3/7 [===========>..................] - ETA: 2s - loss: 0.3986 - acc: 0.8125
4/7 [================>.............] - ETA: 1s - loss: 0.3721 - acc: 0.8281
5/7 [====================>.........] - ETA: 1s - loss: 0.3449 - acc: 0.8438
6/7 [========================>.....] - ETA: 0s - loss: 0.3168 - acc: 0.8646
7/7 [==============================] - 9s 1s/step - loss: 0.3165 - acc: 0.8633 - val_loss: 0.1167 - val_acc: 0.9950

Epoch 3/10
1/7 [===>..........................] - ETA: 1s - loss: 0.2457 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.2592 - acc: 0.9688
3/7 [===========>..................] - ETA: 2s - loss: 0.2173 - acc: 0.9688
4/7 [================>.............] - ETA: 1s - loss: 0.2122 - acc: 0.9688
5/7 [====================>.........] - ETA: 1s - loss: 0.2003 - acc: 0.9688
6/7 [========================>.....] - ETA: 0s - loss: 0.1896 - acc: 0.9740
7/7 [==============================] - 9s 1s/step - loss: 0.1835 - acc: 0.9773 - val_loss: 0.0678 - val_acc: 1.0000

Epoch 4/10
1/7 [===>..........................] - ETA: 1s - loss: 0.2051 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.1652 - acc: 0.9844
3/7 [===========>..................] - ETA: 2s - loss: 0.1423 - acc: 0.9896
4/7 [================>.............] - ETA: 1s - loss: 0.1289 - acc: 0.9922
5/7 [====================>.........] - ETA: 1s - loss: 0.1225 - acc: 0.9938
6/7 [========================>.....] - ETA: 0s - loss: 0.1149 - acc: 0.9948
7/7 [==============================] - 9s 1s/step - loss: 0.1060 - acc: 0.9955 - val_loss: 0.0455 - val_acc: 1.0000

Epoch 5/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0769 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.0846 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0797 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0736 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0914 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0858 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0808 - acc: 1.0000 - val_loss: 0.0346 - val_acc: 1.0000

Epoch 6/10
1/7 [===>..........................] - ETA: 1s - loss: 0.1267 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.1039 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0893 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0780 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0758 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0789 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0738 - acc: 1.0000 - val_loss: 0.0248 - val_acc: 1.0000

Epoch 7/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0344 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0385 - acc: 1.0000
3/7 [===========>..................] - ETA: 3s - loss: 0.0467 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0445 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0446 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0429 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0421 - acc: 1.0000 - val_loss: 0.0202 - val_acc: 1.0000

Epoch 8/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0319 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0300 - acc: 1.0000
3/7 [===========>..................] - ETA: 3s - loss: 0.0320 - acc: 1.0000
4/7 [================>.............] - ETA: 2s - loss: 0.0307 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0303 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0291 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0358 - acc: 1.0000 - val_loss: 0.0167 - val_acc: 1.0000

Epoch 9/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0246 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0255 - acc: 1.0000
3/7 [===========>..................] - ETA: 3s - loss: 0.0258 - acc: 1.0000
4/7 [================>.............] - ETA: 2s - loss: 0.0250 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0252 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0260 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0327 - acc: 1.0000 - val_loss: 0.0143 - val_acc: 1.0000

Epoch 10/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0251 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.0228 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0217 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0249 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0244 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0239 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0290 - acc: 1.0000 - val_loss: 0.0127 - val_acc: 1.0000

DYNAMIC LEARNING_PHASE
[0.012697912137955427, 1.0]

STATIC LEARNING_PHASE = 0
[0.012697912137955427, 1.0]

STATIC LEARNING_PHASE = 1
[0.01744014158844948, 1.0]

首先,我们观察到网络收敛速度明显加快,并且达到了完美的精度。 我们还看到,当我们在不同的learning_phase值之间切换时,在准确性方面不再存在差异。

2.5补丁如何在真实数据集上执行?

那么,在更现实的实验中,补丁的效果如何? 让我们使用Keras的预训练ResNet50(最初适合imagenet),删除顶层分类层,并在有或没有补丁的情况下对其进行微调,然后比较结果。 对于数据,我们将使用CIFAR10(Keras提供的标准火车/测试区),并将图像大小调整为224×224,以使其与ResNet50的输入大小兼容。

我们将使用RSMprop进行10次训练顶级分类层,然后使用SGD(lr = 5e-139,动量= 1)进行另外4次以微调第0.9层之后的所有内容。 没有补丁,我们的模型可以达到87.44%的精度。 使用补丁,我们可以达到92.36%的准确性,几乎提高了5个百分点。

2.6我们是否应该对其他层(例如Dropout)应用相同的修补程序?

批标准化不是唯一的在训练模式和测试模式之间有不同操作的层。 辍学及其变体也具有相同的效果。 我们是否应该对所有这些层应用相同的策略? 我相信不会(尽管我很想听听您对此的想法)。 原因是使用Dropout来避免过度拟合,因此在训练过程中将其永久锁定在预测模式将无法实现其目的。 你怎么看?

我坚信必须在Keras中解决这一差异。 我已经看到了实际应用中由该问题引起的更深远的影响(从100%降低到50%精度)。 一世 计划发送 已经发送了 PR 修复后,请寄给Keras,希望它会被接受。

如果您喜欢此博客文章,请花一点时间在Facebook或Twitter上分享。 🙂

时间戳记:

更多来自 基准框