迁移学习精度差
Transfer learning bad accuracy
我有一项任务是根据缺陷对种子进行分类。我在 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=30
、width_shift_range=0.2
、height_shift_range=0.2
和 horizontal_flip = True
,同时迁移学习以进一步增强数据。
- 也许 Adam 优化器是个坏主意?例如,我应该尝试 RMSprop 吗?
- 我是否也应该微调一些学习率较小的 SGD 转换层?
还是我做错了什么?
编辑:我post训练历史图。也许它包含有价值的信息:
EDIT2: 改变 InceptionV3 的参数:
对比VGG16:
如果您想使用 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 层,
- 或通过减少最后一层之前的密集层中的单元数来减小网络大小。
@今天,我发现了一个问题。这是因为 Batch Normalization 层及其在冻结它们时的行为发生了一些变化。 Chollet 先生给出了一个解决方法,但我使用了 datumbox 制作的 Keras fork,这解决了我的问题。主要问题描述如下:
https://github.com/keras-team/keras/pull/9965
现在我的准确率约为 85%,我正在努力提高它。
我有一项任务是根据缺陷对种子进行分类。我在 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=30
、width_shift_range=0.2
、height_shift_range=0.2
和horizontal_flip = True
,同时迁移学习以进一步增强数据。 - 也许 Adam 优化器是个坏主意?例如,我应该尝试 RMSprop 吗?
- 我是否也应该微调一些学习率较小的 SGD 转换层?
还是我做错了什么?
编辑:我post训练历史图。也许它包含有价值的信息:
EDIT2: 改变 InceptionV3 的参数:
对比VGG16:
如果您想使用 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 层,
- 或通过减少最后一层之前的密集层中的单元数来减小网络大小。
@今天,我发现了一个问题。这是因为 Batch Normalization 层及其在冻结它们时的行为发生了一些变化。 Chollet 先生给出了一个解决方法,但我使用了 datumbox 制作的 Keras fork,这解决了我的问题。主要问题描述如下:
https://github.com/keras-team/keras/pull/9965
现在我的准确率约为 85%,我正在努力提高它。