如何准备图像以使用 Python/Keras 训练 ConvNet?
Posted
技术标签:
【中文标题】如何准备图像以使用 Python/Keras 训练 ConvNet?【英文标题】:How to prepare images to train a ConvNet with Python/Keras? 【发布时间】:2019-12-18 16:13:57 【问题描述】:尝试使用 Python + Keras 训练 cnn(卷积神经网络)。但即使是最简单的问题似乎也很难回答,而且那里的教程也没有我想要的答案。
我可以访问我想识别的少数类的数千张图像。但是我如何准备图像?例如:
-
是否应该将图像裁剪为完全我想要识别的对象?本例中的对象是完美的矩形,因此如果这有助于训练,我可以将它们裁剪为完美。
图像应该是什么尺寸?我是让它们保持高分辨率,还是将它们调整为小? MNIST 之类的许多示例使用 18x18 像素的图像,但在这种尺寸下,这些类的对象是毫无意义的模糊,彼此相似。
在训练期间,我是否应该只拥有我想要识别的类的图像?或者我应该在混合中插入一些我不关心的其他事物的图像?
在训练期间,是否可以在单个图像中包含对象的多个实例?还是应该将训练图像限制为单个类中只有 1 个对象的图像?
编辑:被问及我是否需要知道对象的位置。答案是我需要做物体检测:
(这张图片取自关于 Mask-RCNN 的 blog post,但我的问题比这更新手,它并不特定于 Mask-RCNN。)
【问题讨论】:
您只是想对图像进行分类(例如它是椅子、狗、猫、树、灯等的图像),还是您还想在图像中找到物体的位置也一样? 我写的答案是考虑到图像分类;但我认为大部分都是通用的,适用于分类、对象检测甚至分割。例如,在最后一部分中,我提到了 VGG,因为我想到了分类。相反,您可以考虑将像 YOLO 这样的对象检测模型作为模型的基础(例如,参见 this 或 this)。 【参考方案1】:我的建议是从小而简单的开始:从使用常见的配置/参数/方法开始,然后根据您将执行的实验结果根据需要更改它们。
是否应该将图像裁剪为我想要识别的对象?本例中的对象是完美的矩形,因此如果这有助于训练,我可以将它们裁剪为完美。
不,不一定。实际上,最好不要这样做,因为当您想在现实世界中使用模型时,图像不会被完美裁剪。例如,假设您在房间里拍摄了以下照片:
您希望您的模型将“椅子”预测为输出,尽管背景中还有其他内容。因此,您的模型将更适用/更稳健地处理现实世界中可能存在杂乱背景的各种图像。此外,我们并非总是通过对象周围的框的坐标来裁剪它。
图像应该是什么尺寸?我是让它们保持高分辨率,还是将它们调整为小? MNIST 之类的许多示例使用 18x18 像素的图像,但在这种尺寸下,这些类的对象是毫无意义的模糊,彼此相似。
坚持图片的常用尺寸。例如,大多数在 ImageNet 上训练的模型都以 224x224 大小的图像作为输入。请记住,图像越大,模型的训练将涉及更多的计算,因此需要更多的时间来训练。一般来说,只要在调整大小后不会丢失太多图像的信息/质量,越小越好。
在训练期间,我是否应该只拥有我想要识别的类的图像?或者我应该在混合中插入一些我不关心的其他事物的图像?
通常,我们只有来自我们想要分类的已知类的图像,而不考虑“其他”类。但是,如果您对您的模型能够将未知图像分类为一个类别感兴趣(请注意,仅在狗和猫的图像上训练的模型,即使您给它一张椅子图像,也会看到并将所有东西分类为狗和猫或树或烤箱),您可以添加另一个“未知”/“其他”类,并将所有没有与它们关联的类的图像分配给该类。但是,在训练完成后,您不应该期望您的模型能够完美识别任何未知对象并将其预测为“未知”类(即主要是因为属于“未知”类的图像太多变化,你不能只用数百或数千个未知图像的例子来代表它们)。
在训练期间,是否可以在单个图像中包含对象的多个实例?还是应该将训练图像限制为单个类中只有 1 个对象的图像?
我不认为在图像中具有同一对象的多个实例会产生任何问题,主要是因为 CNN 是平移不变的,因此如果在图像区域中检测到特征,则可以检测到它图像中的其他位置(可能属于对象的另一个实例)。如果您在训练数据中混合使用单实例和多实例图像,它甚至可能会提高模型的准确性。
最后一点,我建议您不要从头开始训练 CNN 分类模型。已经有非常好的模型在 ImageNet 上进行了训练,因此您可以使用这些模型中已经提取和积累的知识(即这种方法称为“迁移学习”,即将知识从一个领域/模型转换到另一个领域/模型) .例如,您可以使用 VGG16 作为模型的基础,只需更改顶层(或仅更改分类器层)。这样训练不仅会更快(因为基础已经训练过了,至少边缘或纹理等低级特征大部分在我们看到的所有图像之间共享),而且会更加准确(因为该基础已经在数千张图像上进行了训练)。我建议你阅读这个official tutorial from Keras blog,它说明了如何使用这种培训。
【讨论】:
【参考方案2】:回答您的每个问题:
-
不,因为在测试时,这不是网络将接收的内容。它将在某个位置接收带有物体的图像,周围有很多噪音,因此最好训练它来应对。
尽可能低的分辨率,同时图像仍然可以区分。如果你能把它们区分开来,那么分辨率就可以了。分辨率低的原因是为了降低复杂度并增加 epochs/time 的数量
这取决于您,这取决于您是否认为该网络实际上会接收完全随机的输入。如果您想知道一些处理方法,请参见此处:My CNN classifier gives wrong prediction on random images
可以,只要它在训练期间出现多次并且不是异常值。您希望训练数据尽可能统一,因此理想情况下,如果有时有多个对象,而其他时候只有一个对象,则这两种情况下的训练图像数量应该相同,这样网络才能统一学习。
其他准备方式:
有时获取图像的灰度可以通过减少 复杂性。
集中数据(通过获取每个像素的平均像素值 跨整个数据集并从每个像素中减去它)可以 也有帮助。
【讨论】:
以上是关于如何准备图像以使用 Python/Keras 训练 ConvNet?的主要内容,如果未能解决你的问题,请参考以下文章
使用Python,Keras和TensorFlow训练第一个CNN
使用Python,Keras和TensorFlow训练第一个CNN