修改ResNet50输出层以进行回归

时间:2019-02-05 15:21:50

标签: keras keras-layer resnet

我正在尝试为回归问题创建ResNet50模型,其输出值为-1到1。

我省略了classes参数,在预处理步骤中,我将图像的大小调整为224,224,3。

我尝试使用创建模型

def create_resnet(load_pretrained=False):
  if load_pretrained:
        weights = 'imagenet'
  else:
      weights = None

  # Get base model
  base_model = ResNet50(weights=weights)

  optimizer = Adam(lr=1e-3)
  base_model.compile(loss='mse', optimizer=optimizer)

  return base_model

然后创建模型,打印摘要并使用fit_generator进行训练

   history = model.fit_generator(batch_generator(X_train, y_train, 100, 1),
                                  steps_per_epoch=300, 
                                  epochs=10,
                                  validation_data=batch_generator(X_valid, y_valid, 100, 0),
                                  validation_steps=200,
                                  verbose=1,
                                  shuffle = 1)

虽然我说错了

ValueError: Error when checking target: expected fc1000 to have shape (1000,) but got array with shape (1,)

看看模型摘要,这很有意义,因为最终的Dense层的输出形状为(None,1000)

fc1000 (Dense)                  (None, 1000)         2049000     avg_pool[0][0]      

但是我不知道如何修改模型。我已经阅读了Keras文档并看了几个示例,但是我看到的几乎所有内容都是针对分类模型的。

如何修改模型,使其正确格式化以进行回归?

1 个答案:

答案 0 :(得分:2)

您的代码引发错误,因为您使用的是原始的全连接顶层,该层经过培训可将图像分类为1000个类别之一。为了使网络正常工作,您需要用自己的顶层替换顶层,顶层的形状应与数据集和任务兼容。

这是我用来为Keras的回归任务(面部轮廓预测)创建ImageNet预训练模型的一个小片段:

Contains

就您而言,我想您只需要将NUM_OF_LANDMARKS = 136 def create_model(input_shape, top='flatten'): if top not in ('flatten', 'avg', 'max'): raise ValueError('unexpected top layer type: %s' % top) # connects base model with new "head" BottleneckLayer = { 'flatten': Flatten(), 'avg': GlobalAvgPooling2D(), 'max': GlobalMaxPooling2D() }[top] base = InceptionResNetV2(input_shape=input_shape, include_top=False, weights='imagenet') x = BottleneckLayer(base.output) x = Dense(NUM_OF_LANDMARKS, activation='linear')(x) model = Model(inputs=base.inputs, outputs=x) return model 替换为InceptionResNetV2。本质上,您正在创建一个没有顶层的预训练模型:

ResNet50

然后在其上附加自定义层:

base = ResNet50(input_shape=input_shape, include_top=False)

就是这样。

您还可以从Keras存储库中检查this link,该存储库显示了x = Flatten()(base.output) x = Dense(NUM_OF_LANDMARKS, activation='sigmoid')(x) model = Model(inputs=base.inputs, outputs=x) 在内部的构造方式。我相信它将为您提供有关functional API和图层替换的一些见识。


此外,我想说的是,如果我们谈论的是对预训练的ImageNet模型进行微调,则回归和分类任务都没有太大不同。任务的类型主要取决于您的损失功能和顶层的激活功能。否则,您仍然具有带有ResNet50输出的完全连接层,但是它们的解释方式不同。