训练具有不同输入形状的预训练序列模型

时间:2021-04-07 11:44:12

标签: python-3.x tensorflow keras conv-neural-network pre-trained-model

我有一个预训练的连续 CNN 模型,我对 224x224x3 的图像进行了训练。以下是架构:

model = Sequential()
model.add(Conv2D(filters = 64, kernel_size = (5, 5), strides = 1, activation = 'relu', input_shape = (224, 224, 3)))
model.add(MaxPool2D(pool_size = (3, 3)))
model.add(Dropout(0.2))

model.add(Conv2D(filters = 128, kernel_size = (3, 3), strides = 1, activation = 'relu'))
model.add(MaxPool2D(pool_size = (2, 2)))
model.add(Dropout(0.2))

model.add(Conv2D(filters = 256, kernel_size = (2, 2), strides = 1, activation = 'relu'))
model.add(MaxPool2D(pool_size = (2, 2)))
model.add(Dropout(0.2))

model.add(Flatten())
model.add(Dense(128, activation = 'relu', use_bias=False))

model.add(Dense(num_classes, activation = 'softmax'))     

model.summary()

作为参考,这里是模型摘要:model summary

我想在大小为 40x40x3 的图像上重新训练此模型。但是,我面临以下错误:“ValueError:输入 0 层密集_12 与该层不兼容:输入形状的预期轴 -1 具有值 200704,但收到的输入具有形状(无,256)”。 我应该怎么做才能解决这个错误?

注意:我使用的是 Tensorflow 2.4.1 版

1 个答案:

答案 0 :(得分:0)

问题是,在您的预训练模型中,输入形状为 200704 的扁平形状(最后的第 4 行),然后密集层的输出大小为 128(最后的第 3 行)。现在你想对 40X40 的图像使用相同的预训练模型,它不起作用。原因是:

1- 您的模型依赖于输入图像形状。它不是端到端的 conv 模型,因为您在两者之间使用了密集层,这使得模型输入图像大小相关。

2- 在所有卷积层为 256 而不是 200704 后,40x40 图像的展平尺寸。

解决方案

1- 要么你用 自适应平均池化 层改变扁平部分,然后你最后一个用 softmax 的密集层就可以了。再次在 224x224 图像上重新训练旧模型。之后,您可以对 40x40 的图像进行训练。

2- 或者最简单的方法是只使用预训练模型的一个子集直到展平部分(排除展平部分),然后添加一个具有密集层和分类层的展平部分(带有 softmax 的层)。对于这种方法,您必须编写一个自定义模型,就像这里一样,只有第一部分是预训练模型的子集,而展平和分类部分将是额外的。然后您可以在新数据集上训练整个模型。您还可以使用此方法从迁移学习中获益,允许反向梯度仅流经新创建的线性层而不流经预训练层。