【发布时间】: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