Keras:以两种不同方式拟合 ConvNet 时的结果不一致
Keras: inconsistent results when fitting ConvNets in two different ways
我正在尝试使用 VGG16 网络进行图像分类。我尝试了两种不同的方法来做到这一点,据我所知应该大致相同,但结果却大不相同。
方法 1: 使用 VGG16 提取特征并使用自定义的全连接网络拟合这些特征。这是代码:
model = vgg16.VGG16(include_top=False, weights='imagenet',
input_shape=(imsize,imsize,3),
pooling='avg')
model_pred = keras.Sequential()
model_pred.add(keras.layers.Dense(1024, input_dim=512, activation='sigmoid'))
model_pred.add(keras.layers.Dropout(0.5))
model_pred.add(keras.layers.Dense(512, activation='sigmoid'))
model_pred.add(keras.layers.Dropout(0.5))
model_pred.add(keras.layers.Dense(num_categories, activation='sigmoid'))
model_pred.compile(loss=keras.losses.categorical_crossentropy,
optimizer=keras.optimizers.Adadelta(), metrics=['accuracy'])
(xtr, ytr) = tools.extract_features(model, 3000, imsize, datagen,
rootdir + '/train',
pickle_name = rootdir + '/testpredstrain.pickle')
(xv, yv) = tools.extract_features(model, 300, imsize, datagen,
rootdir + '/valid1',
pickle_name = rootdir + '/testpredsvalid.pickle')
model_pred.fit(xtr, ytr, epochs = 10, validation_data = (xv, yv), verbose=1)
(函数 extract_features()
简单地使用 Keras ImageDataGenerator
生成样本图像和 returns 在这些图像上使用 model.predict()
后的输出)
方法二:取没有top部分的VGG16网络,将所有的卷积层设置为不可训练的,并添加几个可训练的密集连接层。然后使用 keras fit_generator()
进行拟合。这是代码:
model2 = vgg16.VGG16(include_top=False, weights='imagenet',
input_shape=(imsize,imsize,3),
pooling='avg')
for ll in model2.layers:
ll.trainable = False
out1 = keras.layers.Dense(1024, activation='softmax')(model2.layers[-1].output)
out1 = keras.layers.Dropout(0.4)(out1)
out1 = keras.layers.Dense(512, activation='softmax')(out1)
out1 = keras.layers.Dropout(0.4)(out1)
out1 = keras.layers.Dense(num_categories, activation='softmax')(out1)
model2 = keras.Model(inputs = model2.input, outputs = out1)
model2.compile(loss=keras.losses.categorical_crossentropy,
optimizer=keras.optimizers.Adadelta(),
metrics=['accuracy'])
model2.fit_generator(train_gen,
steps_per_epoch = 100,
epochs = 10,
validation_data = valid_gen,
validation_steps = 10)
两种方法的轮数、样本数等并不完全相同,但不需要注意不一致:方法 1 在一个轮数后产生的验证精度为 0.47,并得到高达 0.7-0.8,当我使用更多样本进行拟合时甚至更好。然而,方法 2 卡在 0.1-0.15 的验证准确度上,无论我训练多少,都不会变得更好。
此外,方法 2 比方法 1 慢得多,尽管在我看来它们应该大约一样快(考虑到提取方法 1 中的特征所花费的时间)。
使用第一种方法,您使用 vgg16 pre-trained 模型提取特征 一次 然后训练 - 微调您的网络,而在第二种方法中,您不断传递图像通过每一层,包括 vgg 的层 在每个 epoch。这会导致您的模型使用第二种方法 运行 变慢。
我正在尝试使用 VGG16 网络进行图像分类。我尝试了两种不同的方法来做到这一点,据我所知应该大致相同,但结果却大不相同。
方法 1: 使用 VGG16 提取特征并使用自定义的全连接网络拟合这些特征。这是代码:
model = vgg16.VGG16(include_top=False, weights='imagenet',
input_shape=(imsize,imsize,3),
pooling='avg')
model_pred = keras.Sequential()
model_pred.add(keras.layers.Dense(1024, input_dim=512, activation='sigmoid'))
model_pred.add(keras.layers.Dropout(0.5))
model_pred.add(keras.layers.Dense(512, activation='sigmoid'))
model_pred.add(keras.layers.Dropout(0.5))
model_pred.add(keras.layers.Dense(num_categories, activation='sigmoid'))
model_pred.compile(loss=keras.losses.categorical_crossentropy,
optimizer=keras.optimizers.Adadelta(), metrics=['accuracy'])
(xtr, ytr) = tools.extract_features(model, 3000, imsize, datagen,
rootdir + '/train',
pickle_name = rootdir + '/testpredstrain.pickle')
(xv, yv) = tools.extract_features(model, 300, imsize, datagen,
rootdir + '/valid1',
pickle_name = rootdir + '/testpredsvalid.pickle')
model_pred.fit(xtr, ytr, epochs = 10, validation_data = (xv, yv), verbose=1)
(函数 extract_features()
简单地使用 Keras ImageDataGenerator
生成样本图像和 returns 在这些图像上使用 model.predict()
后的输出)
方法二:取没有top部分的VGG16网络,将所有的卷积层设置为不可训练的,并添加几个可训练的密集连接层。然后使用 keras fit_generator()
进行拟合。这是代码:
model2 = vgg16.VGG16(include_top=False, weights='imagenet',
input_shape=(imsize,imsize,3),
pooling='avg')
for ll in model2.layers:
ll.trainable = False
out1 = keras.layers.Dense(1024, activation='softmax')(model2.layers[-1].output)
out1 = keras.layers.Dropout(0.4)(out1)
out1 = keras.layers.Dense(512, activation='softmax')(out1)
out1 = keras.layers.Dropout(0.4)(out1)
out1 = keras.layers.Dense(num_categories, activation='softmax')(out1)
model2 = keras.Model(inputs = model2.input, outputs = out1)
model2.compile(loss=keras.losses.categorical_crossentropy,
optimizer=keras.optimizers.Adadelta(),
metrics=['accuracy'])
model2.fit_generator(train_gen,
steps_per_epoch = 100,
epochs = 10,
validation_data = valid_gen,
validation_steps = 10)
两种方法的轮数、样本数等并不完全相同,但不需要注意不一致:方法 1 在一个轮数后产生的验证精度为 0.47,并得到高达 0.7-0.8,当我使用更多样本进行拟合时甚至更好。然而,方法 2 卡在 0.1-0.15 的验证准确度上,无论我训练多少,都不会变得更好。
此外,方法 2 比方法 1 慢得多,尽管在我看来它们应该大约一样快(考虑到提取方法 1 中的特征所花费的时间)。
使用第一种方法,您使用 vgg16 pre-trained 模型提取特征 一次 然后训练 - 微调您的网络,而在第二种方法中,您不断传递图像通过每一层,包括 vgg 的层 在每个 epoch。这会导致您的模型使用第二种方法 运行 变慢。