为什么训练会因角膜和张量流而成功并预测失败?

时间:2018-07-17 07:29:23

标签: python tensorflow keras

我训练了一个CNN,以检测图像上是否存在危险ID(example)。

我的培训准确率达到了99%。然后,我尝试根据训练集中的图片进行预测,但无法给出正确的估计。

您能告诉我这怎么可能吗?

取自Google的猫和狗示例(https://developers.google.com/machine-learning/practica/image-classification/exercise-1)的代码:

#!/usr/bin/env python3

import matplotlib.pyplot as plt
from tensorflow.keras import layers
from tensorflow.keras import Model
from tensorflow.keras.optimizers import RMSprop
from tensorflow.keras.preprocessing.image import ImageDataGenerator
import numpy as np
import os
import cv2

def predict(frame):
    frame = cv2.resize(frame, (150, 150))
    frame = np.expand_dims(frame, axis=0)
    frame = np.asarray(frame, dtype='int32')
    frame = frame / 255
    return model.predict(frame)

base_dir = './cats_and_dogs_filtered'
train_dir = os.path.join(base_dir, 'train')
validation_dir = os.path.join(base_dir, 'validation')

train_cats_dir = os.path.join(train_dir, 'cats')
train_dogs_dir = os.path.join(train_dir, 'dogs')

validation_cats_dir = os.path.join(validation_dir, 'cats')
validation_dogs_dir = os.path.join(validation_dir, 'dogs')

train_cat_fnames = os.listdir(train_cats_dir)
print(train_cat_fnames[:10])

train_dog_fnames = os.listdir(train_dogs_dir)
train_dog_fnames.sort()
print(train_dog_fnames[:10])

img_input = layers.Input(shape=(150, 150, 3))
x = layers.Conv2D(16, 3, activation='relu')(img_input)
x = layers.MaxPooling2D(2)(x)
x = layers.Conv2D(32, 3, activation='relu')(x)
x = layers.MaxPooling2D(2)(x)
x = layers.Conv2D(64, 3, activation='relu')(x)
x = layers.MaxPooling2D(2)(x)
x = layers.Flatten()(x)
x = layers.Dense(512, activation='relu')(x)
output = layers.Dense(1, activation='sigmoid')(x)

model = Model(img_input, output)

model.compile(loss='binary_crossentropy',
              optimizer=RMSprop(lr=0.001),
              metrics=['acc'])

train_datagen = ImageDataGenerator(rescale=1./255)
test_datagen = ImageDataGenerator(rescale=1./255)

train_generator = train_datagen.flow_from_directory(
        train_dir,  # This is the source directory for training images
        target_size=(150, 150),  # All images will be resized to 150x150
        batch_size=20,
        # Since we use binary_crossentropy loss, we need binary labels
        class_mode='binary')

validation_generator = test_datagen.flow_from_directory(
        validation_dir,
        target_size=(150, 150),
        batch_size=20,
        class_mode='binary')

history = model.fit_generator(
      train_generator,
      steps_per_epoch=100,  # 2000 images = batch_size * steps
      epochs=15,
      validation_data=validation_generator,
      validation_steps=50,  # 1000 images = batch_size * steps
      verbose=2)

#model.save("trained_cnn_cats_and_dogs.h5")

for i in range(100):
    frame_cat = cv2.imread(train_cats_dir + "/" + train_cat_fnames[i])
    predictions_cat = predict(frame_cat)

    frame_dog = cv2.imread(train_dogs_dir + "/" + train_dog_fnames[i])
    predictions_dog = predict(frame_dog)

    print("Dog: " + str(predictions_dog[0]) + " Cat: " + str(predictions_cat[0]))

对于数据集,我已将狗复制到猫身上(以便两个图像集都相同),然后将危险ID放在每张以前的猫图片上:link to the data (dropbox)

因此,在dogs目录中有“没有危险ID的狗”,在cats目录中有“有危险ID标志的狗”。

输出:

Epoch 15/15
 - 14s - loss: 0.0398 - acc: 0.9910 - val_loss: 0.1332 - val_acc: 0.9760
Dog: [0.9991505] Cat: [0.9996587]
Dog: [0.9996618] Cat: [0.9988152]
Dog: [0.99470115] Cat: [0.99987006]

所以我不知道是否有危险标志:狗的意思是“没有危险标志”,猫的意思是“危险标志”。

相同的代码与原始的猫狗数据完全匹配。

3 个答案:

答案 0 :(得分:2)

问题出在cv2.imread()的字节顺序是蓝色-绿色-红色,而ImageDataGenerator使用红色-绿色-蓝色。

解决方案:

elasticsearch-dsl

原始猫狗数据集:仍然有效(我猜颜色在那里没有影响-非常有趣!) 批次大小:经过1和20的测试,都可以工作

感谢您的所有评论-非常感谢您的帮助! 我希望其他人觉得这有用。

答案 1 :(得分:0)

因此,如果我理解正确,您的标签“猫”和“狗”应该实际上代表“存在危险标志”和“没有危险标志”吗?

我看不到您在任何地方指定标签吗?

您能否提供您提到的示例的链接?

(我通常将其发布为评论,但我没有足够的代表。)

编辑:在我看来,您的标签有误。 我要做的第一件事是验证您的训练数据是否正确标记。似乎只是将不同文件夹中的文件视为不同标签。

答案 2 :(得分:0)

该代码似乎是正确的。这可能不是代码问题,而是数据问题。验证集的分布可能与训练集的分布不同。

要进行验证,您应该用一部分训练集代替who验证集,然后运行代码以查看算法是否运行良好。如果此“假”验证的准确性低,那就是代码的问题。否则,您应该考虑一种更好的分割数据的方法