如何解释由model.predict返回的结果?

时间:2020-05-02 09:05:54

标签: python python-3.x tensorflow machine-learning keras

我正在尝试建立一个可以识别图片中是否有猫的神经网络。我在tensorflow网站上找到了this tutorial,并试图使其适应我的问题。该教程用于对猫和狗进行分类,但是由于我只想检测猫,因此将类别更改为猫和非猫。

对于非猫,我下载了随机图像的数据集。

我在本教程的代码中添加了两个生成器:

test_data_gen = test_image_generator.flow_from_directory(batch_size=batch_size,
                                                               directory=test_dir,
                                                               target_size=(IMG_HEIGHT, IMG_WIDTH),
                                                               class_mode='binary')

pred_data_gen = pred_image_generator.flow_from_directory(batch_size=batch_size,
                                                                 directory=pred_dir,
                                                                 target_size=(IMG_HEIGHT, IMG_WIDTH),
                                                                 class_mode='binary')

然后像这样测试模型:

print('\n# Evaluate on test data')
results = model.evaluate_generator(test_data_gen)
print('test loss, test acc:', results)

print('\n# Generate predictions')
predictions = model.predict(pred_data_gen)
print(len(predictions))
print(predictions)

这是输出:

# Evaluate on test data
test loss, test acc: [0.45212748232815003, 0.9324082]
# Generate predictions for custom samples
256
[[ -8.023465  ]
 [ -7.781438  ]
 [ 50.281197  ]
 [-10.172492  ]
 [ -5.1096087 ]
 [ 43.0299    ]
 [ 21.416649  ]
 ...
 [-10.866359  ]
 [-14.797473  ]
 [ 84.72212   ]
 [ 23.712345  ]
 [ -6.4916744 ]
 [-18.384903  ]
 [ 33.10642   ]]

测试准确性很高,但是我不知道这些结果是什么意思。我以为它们应该在0到1之间,但它们甚至具有负值。我应该如何解释这些结果?

编辑:

这是我的模型(在将S型激活函数添加到最后一层之前):

model = Sequential([
    Conv2D(16, 3, padding='same', activation='relu', input_shape=(IMG_HEIGHT, IMG_WIDTH, 3)),
    MaxPooling2D(),
    Conv2D(32, 3, padding='same', activation='relu'),
    MaxPooling2D(),
    Conv2D(64, 3, padding='same', activation='relu'),
    MaxPooling2D(),
    Flatten(),
    Dense(512, activation='relu'),
    Dense(1)
])

我将最后一层更改为Dense(1, activation='sigmoid'),输出看起来像这样:

# Evaluate on test data
test loss, test acc: [0.714477022488912, 0.5949367]

# Generate predictions for custom samples
256
[[1.]
 [1.]
 [1.]
 ...
 [1.]
 [1.]
 [1.]]

即使测试集中只有一半的图像是猫,所有预测值都是一个。

EDIT2:

这是我编译和拟合模型的方式:

model.compile(optimizer='adam',
              loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
              metrics=['accuracy'])

model.summary()

history = model.fit_generator(
    train_data_gen,
    steps_per_epoch=total_train // batch_size,
    epochs=epochs,
    validation_data=val_data_gen,
    validation_steps=total_val // batch_size
)

3 个答案:

答案 0 :(得分:2)

模型中的最后一层是具有单个神经元的Dense层。由于没有参数传递给它,因此默认情况下它具有线性激活。用户@Code Pope表示这是“失败”(Tensorflow文档中的错误?)。不是,代码完美无缺。

您的损失函数计算二进制交叉熵,可以轻松地与线性激活一起使用。实际上,计算sigmoid只是多余的一点。 ANN将为一类输出负值,为另一类输出正值。它们没有被规范化,而是所谓的logits-这就是为什么您要在损失函数from_logits=True中说。

如何获取预测

from sklearn.metrics import accuracy_score

images, actual = next(train_data_gen)
predictions = model.predict(images)
predictions = (predictions > 0).flatten()
accuracy_score(results, pred)

答案 1 :(得分:1)

您需要使用S型函数将标度输出输出到[0,1]

https://www.tensorflow.org/api_docs/python/tf/math/sigmoid

答案 2 :(得分:1)

在链接的样本中(here,这是失败的。在最后的Dense层中,必须有一个S型函数,其值在0到1之间。原始样本来自本书来自Francois Chollet,Deep Learning for Python,样本来自5.2章,该样本可在github上找到,我建议您使用它:here。 我已经使用了示例,并且效果很好。您编辑的模型看起来不错,但是我不确定您是否为图像以及ImageDataGenerator创建了正确的文件夹结构。我已经训练了模型,然后加载了图像进行预测:

from keras.preprocessing import image
from keras.applications.vgg16 import preprocess_input, decode_predictions
import numpy as np
img_path = '/Users/CodePope/Downloads/catsdogs/cats_and_dogs_smalla/test/dogs/dog.1500.jpg'
img = image.load_img(img_path, target_size=(150,150))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x /=255.
model.predict(x)

结果如下:

array([[0.8290838]], dtype=float32)

看起来不错,因为0代表猫,1代表狗。 对于猫的图像,我们有:

from keras.preprocessing import image
from keras.applications.vgg16 import preprocess_input, decode_predictions
import numpy as np
img_path = '/Users/CodePope/Downloads/catsdogs/cats_and_dogs_smalla/test/cats/cat.1500.jpg'
img = image.load_img(img_path, target_size=(150,150))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x /=255.
model.predict(x)

结果:

array([[0.15701984]], dtype=float32)

尽管这是事实,但我刚刚对模型进行了五个阶段的训练,验证精度为0.67。