Keras VGG16 修改模型每次都给出相同的预测

Posted

技术标签:

【中文标题】Keras VGG16 修改模型每次都给出相同的预测【英文标题】:Keras VGG16 modified model giving the same prediction every time 【发布时间】:2020-01-27 09:33:26 【问题描述】:

我采用了内置的 keras.applications.vgg16.VGG16(weights='imagenet', include_top=True,input_shape=(224,224,3)) 模型,并通过包含 Global 对具有 20 个类的 PASCAL VOC 2012 数据集进行了迁移学习平均池化层如下所示:

def VGG16_modified():
    base_model = vgg16.VGG16(include_top=True,weights='imagenet',input_shape=(224,224,3))
    print(base_model.summary())
    x = base_model.get_layer('block5_pool').output
    x = (GlobalAveragePooling2D())(x)
    predictions = Dense(20,activation='sigmoid')(x)

    final_model = Model(input = base_model.input, output = predictions)
    print(final_model.get_weights())
    return final_model

现在,我想获取基于this 论文的类激活图。为此,我的代码如下:

 def get_CAM(model,img):
        model = load_model(model)
        im = image.load_img(img,target_size=(224,224))
        im = image.img_to_array(im)
        im = np.expand_dims(im,axis=0)
        class_weights = model.layers[-1].get_weights()[0]
        final_conv_layer = model.get_layer('block5_pool')
        cam_model = Model(inputs = model.input,outputs=(final_conv_layer.output,model.layers[-1].output))
        conv_outputs, predictions = cam_model.predict(im)
        conv_outputs = np.squeeze(conv_outputs)
        prediction = np.argmax(predictions)
        print(predictions)
        print(prediction)
        print(conv_outputs)
        print(conv_outputs.shape)
        class_weights = class_weights[:,prediction]
        mat_for_mult = scipy.ndimage.zoom(conv_outputs,(32,32,1),order=1)
        final_output = np.dot(mat_for_mult.reshape((224*224, 512)),class_weights).reshape((224,224))
        print(final_output)
        return final_output

cam_model.predict(im) 总是为所有图像提供相同的类。我不确定我哪里错了。由于 pascal voc 2012 包含多标签图像,我在 modified_vgg16 的最后一层使用了“sigmoid”而不是“softmax”。你能告诉我我哪里出错了。

【问题讨论】:

训练时也会出现这种情况吗? PASCAL VOC 具有多标签图像。我注意到大约 50% 的图像具有“人”类标签,现在所有图像都被归类为“人”。只是想知道是不是这个问题。如果是这样,我们如何解决这个问题。 由于您使用的是 sigmoid,因此每个类都应该是独立的。我注意到您正在使用np.argmax(predictions),如果在最后一层应用softmax 将是有意义的。但是,对于多标签的任务,通常我会根据每个类的阈值来预测多个类。 @zihaozhihao,是的,我看到了,我想改成阈值,但我被这个问题打动了。 'Person' 类总是在这里获得最高的概率。 嗯,不平衡的问题可以在训练过程中得到缓解,比如引入类权重。 【参考方案1】:

PASCAL VOC 在类之间存在不平衡的图像分布。

数据集中的大多数图像都是针对人的,这会导致数据分布不平衡并产生对人类的偏见。

为了避免这种情况,您可以使用加权类的方法,这有助于消除类之间的不平衡

请参考this了解更多关于如何为不平衡类设置类权重的信息。

【讨论】:

以上是关于Keras VGG16 修改模型每次都给出相同的预测的主要内容,如果未能解决你的问题,请参考以下文章

Keras如何改变加载模型的可训练层

Keras:ValueError:decode_predictions 需要一批预测

将 Keras 模型集成到 TensorFlow

VGG16 Keras微调:精度低

基于Keras 的VGG16神经网络模型的Mnist数据集识别并使用GPU加速

markdown VGG-16预训练的Keras模型