【问题标题】:Keras: inconsistent results when fitting ConvNets in two different waysKeras:以两种不同方式拟合 ConvNet 时结果不一致
【发布时间】:2018-08-10 15:08:47
【问题描述】:

我正在尝试使用 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生成样本图像,并在这些图像上使用model.predict()后返回输出)

方法二: 以没有顶部的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)

两种方法的 epochs、样本等的数量并不完全相同,但它们不需要注意不一致:方法 1 仅在一个 epoch 后产生 0.47 的验证准确度,并达到当我使用大量样本来拟合时,0.7-0.8 甚至更好。然而,方法 2 卡在 0.1-0.15 的验证准确度上,无论我训练多少,都不会变得更好。

此外,方法 2 比方法 1 慢得多,尽管在我看来它们应该差不多快(考虑到方法 1 中提取特征所需的时间)。

【问题讨论】:

  • 为什么在第一种方法中使用 sigmoid 作为激活函数,而在第二种方法中使用 softmax?
  • 天哪,这是一个愚蠢的错误。我从我的其他一些测试中复制了代码的第二部分,并没有发现有什么不同。使用相同的激活函数,我现在实际上得到了两种方法的相似精度。现在只有速度的问题;为什么方法2比方法1慢得多?毕竟它们具有相同数量的可训练参数。

标签: tensorflow machine-learning neural-network keras image-recognition


【解决方案1】:

在您的第一种方法中,您使用 vgg16 预训练模型一次提取特征,然后您进行训练 - 微调您的网络,而在您的第二种方法中,您不断地将图像通过包括 vgg 层在内的每一层 在每个时代。这会导致您的模型使用第二种方法运行得更慢。

【讨论】:

  • 是的,但是在这两种情况下通过网络的图像总数相似。在第一种方法中,我从 3000 张图像中提取特征(=3000 次前向传递)并训练 10 个 epoch,每个 epoch 有 3000 个步骤。在第二种方法中,我有 10 个 epoch,每个 epoch 有 100 步(=1000(?)前向传递)。这实际上比第一种方法中的图像更少。如果我错了,请纠正我,但只要我不重复使用相同的图像太多次,这两种方法应该具有相似的速度。
  • 在第二种方法中,您有 10 个时期,每个时期 100 步加上批量大小。你的批量大小是多少?
  • 哦,这很好。我的批量大小是 32,这意味着(我猜)我实际上正在生成 32000 张图像。对不起,我对所有这些神经网络的东西都很陌生,显然犯了很多基本错误:)。
  • 别担心。我们都会犯错。
猜你喜欢
  • 1970-01-01
  • 2017-12-14
  • 1970-01-01
  • 2019-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-23
  • 1970-01-01
相关资源
最近更新 更多