【问题标题】:Very good validation accuracy but bad predictions非常好的验证准确性,但预测不佳
【发布时间】:2019-11-10 22:02:15
【问题描述】:

我正在构建一个 keras 模型来对猫和狗进行分类。我使用了具有瓶颈特征的迁移学习和 vgg 模型的微调。现在我得到了非常好的验证准确率,比如 97%,但是当我开始预测时,我得到了关于分类报告和混淆矩阵的非常糟糕的结果。可能是什么问题?

这是微调的代码和我得到的结果

base_model = applications.VGG16(weights='imagenet', include_top=False, input_shape=(150,150,3))
print('Model loaded.')

# build a classifier model to put on top of the convolutional model
top_model = Sequential()
top_model.add(Flatten(input_shape=base_model.output_shape[1:]))
top_model.add(Dense(256, activation='relu'))
top_model.add(Dropout(0.5))
top_model.add(Dense(2, activation='sigmoid'))

# note that it is necessary to start with a fully-trained
# classifier, including the top classifier,
# in order to successfully do fine-tuning
top_model.load_weights(top_model_weights_path)

# add the model on top of the convolutional base
# model.add(top_model)
model = Model(inputs=base_model.input, outputs=top_model(base_model.output))

# set the first 25 layers (up to the last conv block)
# to non-trainable (weights will not be updated)
for layer in model.layers[:15]:
    layer.trainable = False

# compile the model with a SGD/momentum optimizer
# and a very slow learning rate.
model.compile(loss='binary_crossentropy',
              optimizer=optimizers.SGD(lr=1e-4, momentum=0.9),
              metrics=['accuracy'])

# prepare data augmentation configuration
train_datagen = ImageDataGenerator(
    rescale=1. / 255,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True)

test_datagen = ImageDataGenerator(rescale=1. / 255)

train_generator = train_datagen.flow_from_directory(
    train_data_dir,
    target_size=(img_height, img_width),
    batch_size=batch_size,
    class_mode='categorical')

validation_generator = test_datagen.flow_from_directory(
    validation_data_dir,
    target_size=(img_height, img_width),
    batch_size=batch_size,
    class_mode='categorical')

model.summary()

# fine-tune the model
model.fit_generator(
    train_generator,
    steps_per_epoch=nb_train_samples // batch_size,
    epochs=epochs,
    validation_data=validation_generator,
    validation_steps=nb_validation_samples // batch_size,
    verbose=2)
scores=model.evaluate_generator(generator=validation_generator,
steps=nb_validation_samples // batch_size)
print("Accuracy = ", scores[1])

Y_pred = model.predict_generator(validation_generator, nb_validation_samples // batch_size)

y_pred = np.argmax(Y_pred, axis=1)

print('Confusion Matrix')

print(confusion_matrix(validation_generator.classes, y_pred))

print('Classification Report')

target_names = ['Cats', 'Dogs']

print(classification_report(validation_generator.classes, y_pred, target_names=target_names))
model.save("model_tuned.h5")

准确度 = 0.974375

混淆矩阵 [[186 214] [199 201]]

分类报告

          precision    recall  f1-score   support

    Cats       0.48      0.47      0.47       400
    Dogs       0.48      0.50      0.49       400

微平均 0.48 0.48 0.48 800 宏平均 0.48 0.48 0.48 800 加权平均 0.48 0.48 0.48 800

【问题讨论】:

  • 我也有同样的问题,基本上你这里的问题标题不正确。你的训练准确率很高,但分类报告并不能反映真实情况。

标签: keras conv-neural-network


【解决方案1】:

这个问题通常有两个原因:

  1. 最常见的是当我们使用不同形式的图像实现(预测)模型时(可能忘记标准化或混淆高度和宽度)。这似乎不是这里的情况。

  2. 第二个是当一个类的样本多于其他类时。假设有 1000 个样本 A 和 100 个样本 B。如果模型只计算 A,那么 90% 的时间都是正确的。这在数学上被称为“局部最小值”,即使验证结果产生 0.9 的准确度,实现也会很糟糕。

简而言之,您是否在处理不平衡的数据?在这种情况下,有时很难避免局部最小值。这可能是这里的问题吗?

【讨论】:

  • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
【解决方案2】:

我认为问题在于您应该在验证生成器中添加 shuffle = False

validation_generator = test_datagen.flow_from_directory(
validation_data_dir,
target_size=(img_height, img_width),
batch_size=batch_size,
class_mode='categorical',
shuffle=False)

问题是默认行为是打乱图像所以标签顺序

validation_generator.classes

与生成器不匹配

【讨论】:

    【解决方案3】:

    您的模型存在两个问题。首先,如果您有多个输出神经元,则需要使用 softmax 激活:

    top_model.add(Dense(2, activation='softmax'))
    

    然后你必须使用 categorical_crossentropy 损失,二元交叉熵仅适用于当你有一个具有 sigmoid 激活的输出神经元时。

    model.compile(loss='categorical_crossentropy',
                  optimizer=optimizers.SGD(lr=1e-4, momentum=0.9),
                  metrics=['accuracy'])
    

    【讨论】:

    • 其实我很困惑。我有两个班,用softmax可以吗
    • 是的,没关系
    • 我已经做出了您推荐的更改,但我仍然得到不好的预测。还有其他建议吗?感谢您的帮助,先生
    • 对于两个互斥的类,您应该只使用 1 个具有 sigmoid 激活函数和 binary_crossentropy 损失的输出神经元。当你有超过 2 个类时,softmax 实际上可以看作是 sigmoid 的扩展。
    • @GiuseppeMarra 不,也可以使用两级 softmax,没有你暗示的单一选项。
    猜你喜欢
    • 1970-01-01
    • 2021-11-12
    • 1970-01-01
    • 2020-10-16
    • 2021-06-06
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 2020-02-02
    相关资源
    最近更新 更多