尝试使用Python和Keras训练卷积神经网络(CNN)。但即使是最简单的问题似乎也很难找到答案,现有的教程也没有我想要的答案。
我有成千上万张我想识别的几个类别的图像。但是我应该如何准备这些图像呢?例如:
- 图像是否应该裁剪到我想要识别的对象的精确位置?这些对象在这种情况下都是完美的矩形,所以如果有助于训练,我可以将它们裁剪得非常精确。
- 图像应该是什么尺寸?我应该保持高分辨率,还是调整它们到较小的尺寸?很多例子都使用像MNIST这样的数据集,它使用的是18×18像素的图像,但在这种尺寸下,这些类别的对象都变成了无意义的模糊,看起来彼此相似。
- 在训练过程中,我应该只使用我想识别的类别的图像吗?还是应该在其中加入一些我不关心的其他东西的图像?
- 在训练过程中,一个图像中可以有多个对象实例吗?还是应该限制训练图像为每张图像中只有一个类别的一个对象?
编辑:有人问我是否需要知道对象的位置。答案是我需要进行对象检测:
(那张图片来自于一个关于Mask-RCNN的博客文章,但我的问题比那更基础,不特指Mask-RCNN。)
回答:
我的建议是从小处着手,保持简单:首先采用常见的配置/参数/方法,然后根据实验结果进行必要的调整。
- 图像是否应该裁剪到我想要识别的对象的精确位置?这些对象在这种情况下都是完美的矩形,所以如果有助于训练,我可以将它们裁剪得非常精确。
不,不一定。实际上,最好不要这样做,因为当你想在现实世界中使用你的模型时,图像并不是完美裁剪的。例如,假设你在房间里拍摄了以下照片:
你希望你的模型能预测出“椅子”作为输出,尽管背景中有其他东西。因此,你的模型将在现实世界中发现的各种图像上更加适用/健壮,这些图像的背景可能杂乱无章。此外,我们并不总是有包围对象的框的坐标来进行裁剪。
- 图像应该是什么尺寸?我应该保持高分辨率,还是调整它们到较小的尺寸?很多例子都使用像MNIST这样的数据集,它使用的是18×18像素的图像,但在这种尺寸下,这些类别的对象都变成了无意义的模糊,看起来彼此相似。
坚持使用常见的图像尺寸。例如,大多数在ImageNet上训练的模型接受224×224像素大小的图像作为输入。请记住,图像越大,模型的训练将越复杂,因此训练时间会更长。一般来说,只要在调整大小后不会丢失太多信息/图像质量,图像越小越好。
- 在训练过程中,我应该只使用我想识别的类别的图像吗?还是应该在其中加入一些我不关心的其他东西的图像?
通常,我们只使用我们想要分类的已知类别的图像,而不考虑“其他”类别。然而,如果你希望你的模型能够将未知图像分类为一个类别(请注意,仅用狗和猫的图像训练的模型,会将所有图像都视为狗和猫,即使你给它一张椅子、树或烤箱的图像),你可以添加另一个“未知”/“其他”类别,并将所有没有关联类别的图像分配到那个类别。但在训练结束后,你不应该期望你的模型能够完美地识别任何未知对象并将其预测为“未知”类别(主要是因为“未知”类别的图像差异很大,你无法仅用数百或数千个未知图像的例子来代表它们)。
- 在训练过程中,一个图像中可以有多个对象实例吗?还是应该限制训练图像为每张图像中只有一个类别的一个对象?
我认为在一个图像中拥有同一对象的多个实例不会造成任何问题,主要是因为CNN具有平移不变性,因此如果在图像的一个区域检测到一个特征,它可以在图像的其他地方检测到(这可能属于另一个对象实例)。如果你在训练数据中混合了单实例和多实例图像,甚至可能提高模型的准确性。
最后,我想建议你不要从头开始训练一个CNN分类模型。已经有一些在ImageNet上训练得很好的模型,因此你可以利用这些模型中已经提取和积累的知识(这种方法称为“迁移学习”,即你将知识从一个领域/模型转移到另一个领域/模型)。例如,你可以使用VGG16作为你模型的基础,只需更改顶层(或仅分类层)。这样,训练不仅会快得多(因为基础已经训练好,至少低级特征如边缘或纹理在我们看到的所有图像中大多是共享的),而且会更加准确(因为基础已经在数千张图像上训练过)。我建议你阅读这个Keras博客的官方教程,它展示了这种训练方法的使用。