【问题标题】:Transfer learning bad accuracy迁移学习准确率差
【发布时间】:2019-01-30 08:06:02
【问题描述】:

我的任务是根据缺陷对种子进行分类。我在 7 个班级中有大约 14k 张图片(它们的大小不相等,有些班级的照片更多,有些班级的照片更少)。我尝试从头开始训练 Inception V3,我的准确率约为 90%。然后我尝试使用带有 ImageNet 权重的预训练模型进行迁移学习。我从applications 导入了inception_v3,没有顶层fc 层,然后在文档中添加了我自己的like。我以以下代码结束:

# Setting dimensions
img_width = 454
img_height = 227

###########################
# PART 1 - Creating Model #
###########################

# Creating InceptionV3 model without Fully-Connected layers
base_model = InceptionV3(weights='imagenet', include_top=False, input_shape = (img_height, img_width, 3))

# Adding layers which will be fine-tunned
x = base_model.output
x = GlobalAveragePooling2D()(x)
x = Dense(1024, activation='relu')(x)
predictions = Dense(7, activation='softmax')(x)

# Creating final model
model = Model(inputs=base_model.input, outputs=predictions)

# Plotting model
plot_model(model, to_file='inceptionV3.png')

# Freezing Convolutional layers
for layer in base_model.layers:
    layer.trainable = False

# Summarizing layers
print(model.summary())

# Compiling the CNN
model.compile(optimizer = 'adam', loss = 'categorical_crossentropy', metrics = ['accuracy'])

##############################################
# PART 2 - Images Preproccessing and Fitting #
##############################################

# Fitting the CNN to the images

train_datagen = ImageDataGenerator(rescale = 1./255,
                                   rotation_range=30,
                                   width_shift_range=0.2,
                                   height_shift_range=0.2,
                                   shear_range = 0.2,
                                   zoom_range = 0.2,
                                   horizontal_flip = True,
                                   preprocessing_function=preprocess_input,)

valid_datagen = ImageDataGenerator(rescale = 1./255,
                                   preprocessing_function=preprocess_input,)

train_generator = train_datagen.flow_from_directory("dataset/training_set",
                                                    target_size=(img_height, img_width),
                                                    batch_size = 4,
                                                    class_mode = "categorical",
                                                    shuffle = True,
                                                    seed = 42)

valid_generator = valid_datagen.flow_from_directory("dataset/validation_set",
                                                    target_size=(img_height, img_width),
                                                    batch_size = 4,
                                                    class_mode = "categorical",
                                                    shuffle = True,
                                                    seed = 42)

STEP_SIZE_TRAIN = train_generator.n//train_generator.batch_size
STEP_SIZE_VALID = valid_generator.n//valid_generator.batch_size

# Save the model according to the conditions  
checkpoint = ModelCheckpoint("inception_v3_1.h5", monitor='val_acc', verbose=1, save_best_only=True, save_weights_only=False, mode='auto', period=1)
early = EarlyStopping(monitor='val_acc', min_delta=0, patience=10, verbose=1, mode='auto')

#Training the model
history = model.fit_generator(generator=train_generator,
                         steps_per_epoch=STEP_SIZE_TRAIN,
                         validation_data=valid_generator,
                         validation_steps=STEP_SIZE_VALID,
                         epochs=25,
                         callbacks = [checkpoint, early])

但我得到了糟糕的结果:45% 的准确率。我认为它应该更好。我有一些假设可能会出错:

  • 我从头开始对缩放图像 (299x299) 和迁移学习时的非缩放图像 (227x454) 进行了训练,但它失败了(或者我的尺寸顺序失败了)。
  • 在迁移学习时我使用了preprocessing_function=preprocess_input(在网上找到一篇文章说它非常重要,所以我决定添加它)。
  • 添加了rotation_range=30width_shift_range=0.2height_shift_range=0.2horizontal_flip = True,同时迁移学习以进一步增强数据。
  • 也许 Adam 优化器是个坏主意?例如,我应该尝试 RMSprop 吗?
  • 我是否也应该使用小学习率的 SGD 微调一些卷积层?

还是我失败了?

编辑:我发布了一个训练历史图。也许它包含有价值的信息:

EDIT2:随着InceptionV3参数的变化:

VGG16 对比:

【问题讨论】:

  • 你用过的preprocess_input函数是什么?
  • 哦,对不起。即:from keras.applications.inception_v3 import InceptionV3, preprocess_input
  • 你在从头训练 inception 的时候也用过吗?
  • 不,我没有。现在我正在尝试在没有它的情况下进行训练

标签: python tensorflow machine-learning keras transfer-learning


【解决方案1】:

如果您想使用 Keras 中的 preprocess_input 方法预处理输入,请删除 rescale=1./255 参数。否则,保留 rescale 参数并删除 preprocessing_function 参数。另外,如果损失没有减少,请尝试使用较低的学习率,例如 1e-4 或 3e-5 或 1e-5(Adam 优化器的默认学习率是 1e-3):

from keras.optimizers import Adam

model.compile(optimizer = Adam(lr=learning_rate), ...)

编辑:添加训练图后,您可以看到它在训练集上是否过拟合。你可以:

  • 添加某种正则化,例如 Dropout 层,
  • 或通过减少最后一层之前的 Dense 层中的单元数来减小网络大小。

【讨论】:

  • 我也试试。我会让你知道结果
  • 附言。我添加了一个训练历史图。你觉得学习率太高了吗?
  • @MichaelS。哦!它显示过拟合。是的,降低学习率可能会有所帮助。但是您需要添加某种正则化。在这种情况下,添加 dropout 层也可能有所帮助。或者通过减少最后一层之前的密集层中的单元数来减小网络大小。 1024 可能太多了!
  • 我应该在哪里添加 Dropout?在 InceptionV3 网络内部的某个地方还是在完全连接的层之前?我应该尝试 512 甚至更少的单位吗?
  • 另外,尝试删除GlobalAveragePooling2D
【解决方案2】:

@今天,我发现了一个问题。这是因为批量标准化层及其在冻结时的行为发生了一些变化。 Chollet 先生给出了一个解决方法,但我使用了 datumbox 制造的 Keras 叉子,它解决了我的问题。这里描述了主要问题:

https://github.com/keras-team/keras/pull/9965

现在我得到了约 85% 的准确率,并且正在努力提高它。

【讨论】:

  • 感谢您让我知道这一点。其实我之前在关于SO的问题中遇到过这个问题,但我完全忘记了。
  • 我也遇到了同样的问题,我尝试了上面 datumbox 制作的 Keras fork。简而言之,它工作得很好。该用户在他的博客中详细解决了这个问题。 blog.datumbox.com/…
  • 如何应用补丁?
猜你喜欢
  • 1970-01-01
  • 2019-05-07
  • 2022-11-12
  • 2019-06-07
  • 1970-01-01
  • 2020-12-28
  • 2021-01-19
  • 2019-06-11
  • 1970-01-01
相关资源
最近更新 更多