【问题标题】:Keras/Tensorflow Model Works with Validation Images but Not Real World DataKeras/Tensorflow 模型适用于验证图像,但不适用于真实世界数据
【发布时间】:2018-07-17 01:16:24
【问题描述】:

我有一个验证精度非常高 (> 99%) 的模型,当针对不在原始训练或验证集中的图像(即用我的智能手机拍摄的照片)运行时,它会失败。

我一直认为,要学习任何新技术,就必须忍受它。为此(在阅读和观看了一堆机器学习教程之后),我创建并标记了大约 25,000 张图像,并将它们输入到我的 CNN 中(大部分来自 CIFAR-10 示例)。

图像(我在纽约街区的建筑物)是从使用 GoPro 和我的 Android 手机拍摄的视频中获取的。每一帧都被转换为全尺寸(原始分辨率)jpeg 文件。

图像被标记并组织成一个目录结构,其中每个子目录对应于图像的地址(标签)(100MainSt、102MainSt 等)。这是为了允许与 Keras 的“flow_from_directory”功能无缝集成。请注意,给定的目录/标签同时包含 Android 和 GoPro 图像。

然后使用sklearntrain_test_split 函数将数据分为 (80/20) 训练和验证数据。

我使用 Adam 优化器运行我的模型,损失函数为 categorical_crossentropy,学习率为 1e-6,并且每个图像都缩小到 300x300(由于我的 GPU 的内存限制)。经过 70 多个 epoch 后,我的验证准确率为 99.2%,损失为 0.0383。不错(至少我是这么认为的)。

现在我的问题:当我用手机拍照(静止图像,而不是上述视频中的帧)并通过我的模型输入它们时,性能很糟糕,12 张图像中有 7 张不正确分类。当我通过模型随机选择(由我)训练或验证图像(从上面)运行时,它运行良好,这是我所期望的。这表明我对输入图像所做的转换(缩小、转置、转换为numpy 数组等)在所有情况下都是相同且正确的。

我可以看到用于训练和验证的视频采集图像与静止图像(也称为快照)之间的唯一显着区别是分辨率。快照具有明显更高的分辨率,但我认为这并不重要,因为所有图像都缩小到了 300x300。

任何见解或想法都将不胜感激(并且可能对未来的旅行者有所帮助),因为我完全不知道为什么这不起作用。

我的代码的胆量:

model = Sequential()

filters = 32
model.add(Conv2D(filters, (3, 3), padding='same', input_shape=(image_width, image_height, 3)))

model.add(Activation('relu'))
model.add(Conv2D(filters, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

model.add(Conv2D(filters*2, (3, 3), padding='same'))
model.add(Activation('relu'))
model.add(Conv2D(filters*2, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

model.add(Flatten())
model.add(Dense(filters*16))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(len(classes)))
model.add(Activation('softmax'))

model.compile(loss='categorical_crossentropy',
              optimizer=opts[opt],
              metrics=['accuracy'])

拟合、归一化和预测:

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

train_generator = train_datagen.flow_from_directory(
        training_dir,
        target_size=(image_width, image_height),
        batch_size=batch_size,
        class_mode='categorical',
        follow_links=True
)

validation_generator = test_datagen.flow_from_directory(
        validation_dir,
        target_size=(image_width, image_height),
        batch_size=batch_size,
        class_mode='categorical',
        follow_links=True
)

hist = model.fit_generator(
        train_generator,
        steps_per_epoch=train_generator.samples//batch_size,
        epochs=epochs,
        validation_data=validation_generator,
        validation_steps=validation_generator.samples//batch_size,
        use_multiprocessing=True,
        workers=8,
        callbacks=[early_stopping, time_callback]
)

pred = model.predict_generator(validation_generator, workers=8, use_multiprocessing=True, verbose=1)

以及我用来测试单个(快照)图像的代码:

#... Use with snapshots (may need to be rotated)
# image = Image.open(image_file).convert("RGB").rotate(-90).resize((width, height))

#... Use with images scraped from video (either GoPro or Android)
image = Image.open(image_file).convert("RGB").resize((width, height))

img = np.array(image)

r = img[:,:,0]
g = img[:,:,1]
b = img[:,:,2]

npimages = np.array([[r] + [g] + [b]], np.uint8)
npimages = npimages.transpose(0,2,3,1)

classes = model.predict_classes(npimages)
prediction = model.predict(npimages, verbose=2)

print(prediction)
print(classes)
print(label_map[classes[0]])

plt.imshow(img)

【问题讨论】:

  • 能否提供推理代码?
  • 您是否应用了与训练和验证数据相同的标准化程序?
  • Mikkola -- 如果我理解你所说的“标准化”是什么意思,我会使用 Keras 的“ImageDataGenerator”函数将训练/验证图像重新缩放 1./255。当我对完全训练的模型的输入执行相同操作时,它每次都无法正确分类,包括训练或验证步骤中使用的快照和图像。
  • Marcin -- 我已经修改了我的原始帖子,以包含我认为您所说的“推理代码”的意思。如果不清楚,请随时 LMK。
  • 当您运行predict 方法时,我的意思是这段代码。当然 - fit 方法也可能有帮助。

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


【解决方案1】:

恐怕视频数据往往具有很强的相关性。也就是说,虽然 1 分钟的视频转换为 60 秒的 30 fps (1800) 图像,但它们中的大多数都非常相似。这是相同的场景,“相同”的照明条件,相同的汽车或路过的人。

如果您的验证图像数据与您的测试数据来自相同的视频序列,您将获得很高的准确率(接近 100%!),但它类似于对您的训练数据进行测试。它是过拟合的,并且验证集与测试集足够相似,因此准确度很高。退出可能会有所帮助,但如果您的数据集高度相关,则不会。

从好的方面来说,您的编码可能是有效的!

修复?更多数据可能是您的最佳途径。即使是在不同的日子(不同的汽车、人、天气等)拍摄的更多视频数据。抱歉——我知道给事物贴标签需要做很多工作。或者,也可以尝试根据您的数据微调预训练网络。

【讨论】:

  • Pam -- 啊,这很有帮助。是的,我的验证图像数据来自与训练相同的视频序列(GoPro 和 Android)。我可以做的是在 GoPro 图像上进行训练,并针对 Android 进行验证,反之亦然。
  • 这可能会有所帮助,但您可能会遇到与现在相同的问题。而且您的准确性也可能会下降,因为验证集与训练数据差异太大。如果可以,请获取更多数据。 Kaggle 可能有一些用处。甚至更多的数据增强 - 随机剪辑。我会尝试对帧进行洗牌,因此我不会取每一帧,而是只取 1/30,这样它们就没有那么相关,并且在训练和验证数据中具有 Android 和 GoPro 的代表性分布。
  • 谢谢,所有这些都很有帮助。上面提出的一个我在其他地方也听说过的建议是将图像集归零。我想知道这有多重要,因为我使用的架构并不简单。
猜你喜欢
  • 2023-03-31
  • 1970-01-01
  • 1970-01-01
  • 2018-09-06
  • 1970-01-01
  • 2021-06-18
  • 2021-04-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多