随机裁剪数据增强卷积神经网络

Random cropping data augmentation convolutional neural networks

我正在训练卷积神经网络,但数据集相对较小。所以我正在实施技术来增强它。现在这是我第一次处理核心计算机视觉问题,所以对它来说还比较陌生。对于增强,我阅读了很多技术,论文中经常提到的其中一种技术是随机裁剪。现在我正在尝试实现它,我已经搜索了很多关于这种技术的信息,但找不到合适的解释。所以有一些疑问:

随机裁剪实际上如何帮助数据扩充? python 中是否有任何库(例如 OpenCV、PIL、scikit-image、scipy)隐式实现随机裁剪?如果没有,我该如何实现?

在我看来,随机裁剪有助于数据增强的原因是,虽然图像的语义得以保留(除非你选择了一个非常糟糕的裁剪,但我们假设你设置了随机裁剪,所以这是非常低的概率)你在你的转换网络中得到的激活值是不同的。因此,实际上我们的 conv 网络学会了将更广泛的空间激活统计数据与某个 class 标签相关联,因此通过随机裁剪进行数据扩充有助于提高我们在 conv 网络中的特征检测器的稳健性。同样,随机裁剪产生不同的中间激活值并产生不同的前向传递,所以它就像 "new training point."

这也不是微不足道的。请参阅最近关于神经网络中对抗性示例的工作(相对于 AlexNet 大小而言相对较浅)。在语义上看起来或多或少相同的图像,当我们将它们传递给顶部带有 softmax classifier 的神经网络时,我们可以获得截然不同的 class 概率。因此,从语义的角度来看,细微的变化最终可能会导致不同的前向传递通过一个转换网络。有关详细信息,请参阅 Intriguing properties of neural networks

回答你问题的最后一部分:我通常只是制作自己的随机裁剪脚本。假设我的图像是 (3, 256, 256)(3 个 RGB 通道,256x256 空间大小),您可以编写一个循环,通过随机 select 一个有效的角点对图像进行 224x224 随机裁剪。所以我通常计算一个有效角点数组,如果我想随机裁剪 10 个,我从这个集合中随机 select 10 个不同的角点,假设我选择 (x0, y0) 作为我的左上角点,我将 select 作物 X[x0:x0+224, y0:y0+224],像这样。我个人喜欢从 pre-computed 一组有效的角点中随机选择,而不是一次随机选择一个角点,因为这样我保证我不会得到重复的裁剪,尽管实际上它的可能性很低.

要回答 "how to implement cropping" 问题,您可能需要探索 https://github.com/aleju/imgaug。有一个可用的 Crop 增强器,可让您进行随机裁剪。还有很多其他有趣的增强器。

根据@Indie AI 的上述回答,下面这段代码或许可以帮助您实现随机裁剪:

from random import randrange
import numpy as np

def my_random_crop(vol, w, h):
"""
Given a volume with extra pixels, this functions randomly 
crops it by removing a specific number of pixels from each side of it.

:param vol: input volume with shape W*H*D
:param w: number of pixels to be removed from the width dimension
:param h: number of pixels to be removed from the height dimension
:return: a cropped volume
"""
vw = randrange(w) # valid corner point for the width
vh = randrange(h) # valid corner point for the height

rw = w - vw  # remaining width to be removed
rh = h - vh  # remaining height to be removed

width, height, depth = vol.shape
vol = vol[vw:width - rw, vh:height - rh, :]

return vol

作为快速测试,运行以下内容:

tmp = np.random.randn(64,128,32)
print(tmp.shape)
tmp = my_random_crop(tmp, w = 10, h = 15)
print(tmp.shape)