Pytorch - 迁移学习教程中图像预处理的目的
Pytorch - Purpose of images preprocessing in the transfer learning tutorial
在Pytorch transfer learning tutorial中,训练集和测试集中的图像都使用以下代码进行预处理:
data_transforms = {
'train': transforms.Compose([
transforms.RandomResizedCrop(224),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
]),
'val': transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
]),
}
我的问题是 - 这种转换选择背后的直觉是什么?特别是,选择 RandomResizedCrop(224)
和 RandomHorizontalFlip()
背后的直觉是什么?让神经网络在整个图像上训练不是更好吗? (或者至少,使用这些转换来扩充数据集)?我理解为什么只将包含 ant/bees 的图像部分插入神经网络是合理的,但不明白为什么插入随机裁剪是合理的...
希望我能把我所有的问题都说清楚
谢谢!
关于RandomResizedCrop
为什么 ...ResizedCrop
? - 这个答案很简单。将裁剪调整为相同尺寸允许您对输入数据进行批处理。由于您的玩具数据集中的训练图像具有不同的维度,因此这是使您的训练更有效率的最佳方式。
为什么 Random...
? - 每次迭代为每个图像生成不同的随机裁剪(即随机中心和随机裁剪 dimensions/ratio 在调整大小之前) 是一种人工扩充数据集的好方法,即每次迭代都为网络提供不同外观的输入(从相同的原始图像中提取)。这有助于部分避免对小数据集的过度拟合,并使您的网络整体更加稳健。
然而你是对的,因为你的一些训练图像高达 500px 宽并且语义目标 (ant
/bee
) 有时只覆盖图像的一小部分,所以这些随机作物中的一些可能不含昆虫……但只要发生这种情况的可能性相对较低,它就不会真正影响你的训练。每次迭代都提供不同的训练作物(而不是总是相同的非增强图像)的优势极大地抵消了有时给予 "empty" 作物的副作用。您可以通过在代码中将 RandomResizedCrop(224)
替换为 Resize(224)
(固定调整大小)来验证此断言,并比较测试集上的最终精度。
此外,我要补充一点,神经网络是智能 cookie,有时会通过您意想不到的特征来学习识别图像(即,如果您的数据集或损失有偏差,它们往往会学习识别捷径,c.f.过拟合)。如果这个玩具网络表现得如此出色,我不会感到惊讶,尽管有时只是因为它学习了 "empty" 作物,因为它学习了区分通常的 "ant backgrounds"(底层、树叶等)和 "bee backgrounds"(花朵)。
关于RandomHorizontalFlip
它的目的也是人为地增加你的数据集。对于网络,图像及其翻转版本是两个不同的输入,因此您基本上是人为地将 "free".
的训练数据集的大小加倍
还有很多操作可以用来扩充训练数据集(例如 RandomAffine
, ColorJitter
等)。然而,必须小心选择对目标用例有意义/不影响目标语义信息的转换(例如,对于 ant/bee 分类,RandomHorizontalFlip
很好,因为您可能会得到许多昆虫的图像都是面向右而不是面向左;但是 RandomVerticalFlip
没有多大意义,因为您肯定不会得到颠倒的昆虫照片。
在Pytorch transfer learning tutorial中,训练集和测试集中的图像都使用以下代码进行预处理:
data_transforms = {
'train': transforms.Compose([
transforms.RandomResizedCrop(224),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
]),
'val': transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
]),
}
我的问题是 - 这种转换选择背后的直觉是什么?特别是,选择 RandomResizedCrop(224)
和 RandomHorizontalFlip()
背后的直觉是什么?让神经网络在整个图像上训练不是更好吗? (或者至少,使用这些转换来扩充数据集)?我理解为什么只将包含 ant/bees 的图像部分插入神经网络是合理的,但不明白为什么插入随机裁剪是合理的...
希望我能把我所有的问题都说清楚
谢谢!
关于RandomResizedCrop
为什么
...ResizedCrop
? - 这个答案很简单。将裁剪调整为相同尺寸允许您对输入数据进行批处理。由于您的玩具数据集中的训练图像具有不同的维度,因此这是使您的训练更有效率的最佳方式。为什么
Random...
? - 每次迭代为每个图像生成不同的随机裁剪(即随机中心和随机裁剪 dimensions/ratio 在调整大小之前) 是一种人工扩充数据集的好方法,即每次迭代都为网络提供不同外观的输入(从相同的原始图像中提取)。这有助于部分避免对小数据集的过度拟合,并使您的网络整体更加稳健。然而你是对的,因为你的一些训练图像高达 500px 宽并且语义目标 (
ant
/bee
) 有时只覆盖图像的一小部分,所以这些随机作物中的一些可能不含昆虫……但只要发生这种情况的可能性相对较低,它就不会真正影响你的训练。每次迭代都提供不同的训练作物(而不是总是相同的非增强图像)的优势极大地抵消了有时给予 "empty" 作物的副作用。您可以通过在代码中将RandomResizedCrop(224)
替换为Resize(224)
(固定调整大小)来验证此断言,并比较测试集上的最终精度。此外,我要补充一点,神经网络是智能 cookie,有时会通过您意想不到的特征来学习识别图像(即,如果您的数据集或损失有偏差,它们往往会学习识别捷径,c.f.过拟合)。如果这个玩具网络表现得如此出色,我不会感到惊讶,尽管有时只是因为它学习了 "empty" 作物,因为它学习了区分通常的 "ant backgrounds"(底层、树叶等)和 "bee backgrounds"(花朵)。
关于RandomHorizontalFlip
它的目的也是人为地增加你的数据集。对于网络,图像及其翻转版本是两个不同的输入,因此您基本上是人为地将 "free".
的训练数据集的大小加倍还有很多操作可以用来扩充训练数据集(例如 RandomAffine
, ColorJitter
等)。然而,必须小心选择对目标用例有意义/不影响目标语义信息的转换(例如,对于 ant/bee 分类,RandomHorizontalFlip
很好,因为您可能会得到许多昆虫的图像都是面向右而不是面向左;但是 RandomVerticalFlip
没有多大意义,因为您肯定不会得到颠倒的昆虫照片。