【问题标题】:Validation and Test accuracy at random performance, whereas Train accuracy very high随机性能的验证和测试准确度,而训练准确度非常高
【发布时间】:2023-04-03 21:48:01
【问题描述】:

我正在尝试在 TensorFlow2.1 中为 CIFAR10 构建一个分类器,使用 ResNet50keras 的 imagenet 上进行预训练。应用程序,然后在其上堆叠一个小的 FNN:

# Load ResNet50 pre-trained on imagenet
resn = applications.resnet50.ResNet50(weights='imagenet', input_shape=(IMG_SIZE, IMG_SIZE, 3), pooling='avg', include_top=False)

# Load CIFAR10 
(c10_train, c10_test), info = tfds.load(name='cifar10', split=['train', 'test'], with_info=True, as_supervised=True)

# Make sure all the layers are not trainable
for layer in resn.layers:
    layer.trainable = False

# Transfert Learning for CIFAR10: fine-tune the network by stacking a trainable FNN on top of Resnet
from tensorflow.keras import models, layers

def build_model():
  model = models.Sequential()
  # Feature extractor
  model.add(resn)
  # Small FNN
  model.add(layers.Dense(256, activation='relu'))
  model.add(layers.Dropout(0.4))
  model.add(layers.Dense(10, activation='softmax'))

  model.compile(loss='categorical_crossentropy',
                optimizer=tf.keras.optimizers.SGD(learning_rate=0.1),
                metrics=['accuracy'])

  return model

# Build the resulting net
resn50_c10 = build_model()

在验证或测试准确性时,我面临以下问题:

history = resn50_c10.fit_generator(c10_train.shuffle(1000).batch(BATCH_SIZE), validation_data=c10_test.batch(BATCH_SIZE), epochs=20)

Epoch 1/20
25/25 [==============================] - 113s 5s/step - loss: 0.9659 - accuracy: 0.6634 - val_loss: 2.8157 - val_accuracy: 0.1000
Epoch 2/20
25/25 [==============================] - 109s 4s/step - loss: 0.8908 - accuracy: 0.6920 - val_loss: 2.8165 - val_accuracy: 0.1094
Epoch 3/20
25/25 [==============================] - 116s 5s/step - loss: 0.8743 - accuracy: 0.7038 - val_loss: 2.7555 - val_accuracy: 0.1016
Epoch 4/20
25/25 [==============================] - 132s 5s/step - loss: 0.8319 - accuracy: 0.7166 - val_loss: 2.8398 - val_accuracy: 0.1013
Epoch 5/20
25/25 [==============================] - 132s 5s/step - loss: 0.7903 - accuracy: 0.7253 - val_loss: 2.8624 - val_accuracy: 0.1000
Epoch 6/20
25/25 [==============================] - 132s 5s/step - loss: 0.7697 - accuracy: 0.7325 - val_loss: 2.8409 - val_accuracy: 0.1000
Epoch 7/20
25/25 [==============================] - 132s 5s/step - loss: 0.7515 - accuracy: 0.7406 - val_loss: 2.7697 - val_accuracy: 0.1000   
#... (same for the remaining epochs) 

尽管模型似乎从训练拆分中充分学习,验证集的准确性和损失都没有提高。是什么导致了这种行为?

我正在排除这是过度拟合,因为我正在应用 Dropout,并且该模型似乎从未在测试集上真正改进过。

到目前为止我做了什么:

  • 检查 one-hot 标记在整个训练和测试过程中是否一致
  • 尝试了不同的 FNN 配置
  • 尝试了fit_generator而不是fit的方法
  • 预处理图像,使用不同的 input_shape 调整图像大小

总是遇到同样的问题。

任何提示将不胜感激。

【问题讨论】:

  • 丢弃 dropout(默认情况下不应该使用它,只有在怀疑过度拟合时才使用它),并降低你的学习率(尝试 0.01)。
  • 我忘了提到我已经尝试了不同的学习率,最高可达 0.01(虽然没有降低)。按照您的建议,我删除了辍学,但仍然没有任何改变。在我看来,这一定是与数据或代码错误有关的问题。在验证每个时期时,权重似乎被重置为随机。

标签: keras deep-learning tensorflow2.0 resnet batch-normalization


【解决方案1】:

问题可能是由于使用tfds加载数据,然后传递给Keras .fit

尝试使用

加载您的数据
from keras.datasets import cifar10

(x_train, y_train), (x_test, y_test) = cifar10.load_data()

然后

fit(x=x_train, y=y_train, batch_size=BATCH_SIZE, epochs=20, verbose=1, callbacks=None, validation_split=0.2, validation_data=None, shuffle=True)

【讨论】:

  • 感谢您的回复。但是,即使使用此解决方法,问题仍然存在。我正在经历的行为似乎表明当 tensorflow 调用 .evaluate 方法时,学习的权重被设置回随机忘记学习的权重。我对 TensorFlow 还很陌生,所以我可能会遗漏一些琐碎的东西,但我真的不明白是什么。
【解决方案2】:

显然这个问题是由使用ResNet50引起的。

作为一种变通方法,我下载并使用了其他预训练的深度网络,例如 keras.applications.vgg16.VGG16keras.applications.densenet.DenseNet121,测试集的准确率按预期提高了。

更新

这个答案的上述部分只是一个姑息。为了了解真正发生的事情并最终通过 ResNet50 正确使用迁移学习,请继续阅读。

根本原因似乎在于Keras 处理Batch Normalization 层的方式:

在微调期间,如果批量标准化层被冻结,它将使用小批量统计信息。我认为这是不正确的,它会导致准确性降低,尤其是当我们使用迁移学习时。在这种情况下,更好的方法是使用移动均值和方差的值。

这里有更深入的解释:https://github.com/keras-team/keras/pull/9965

尽管在 TensorFlow 2 中实现了正确的方法,但当我们使用 tf.keras.applications 时,我们还是引用了 TensorFlow 1.0 的批量标准化行为。这就是为什么我们需要在加载模块时通过添加参数layers=tf.keras.layers 来显式注入对 TensorFlow 2 的引用。所以在我的情况下,ResNet50的加载会变成

history = resn50_c10.fit_generator(c10_train.shuffle(1000).batch(BATCH_SIZE), validation_data=c10_test.batch(BATCH_SIZE), epochs=20, layers=tf.keras.layers)

这样就可以了。

@rpeloff 的解决方案致谢:https://github.com/keras-team/keras/pull/9965#issuecomment-549126009

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-16
    • 2021-11-12
    • 2021-07-22
    • 2020-07-08
    • 2020-11-06
    • 2017-12-21
    • 2017-11-05
    • 2017-10-14
    相关资源
    最近更新 更多