我正在尝试建立一个可以识别图片中是否有猫的神经网络。我在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
)
答案 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]
答案 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。