点击小眼睛开启蜘蛛网特效

浅谈深度学习训练中数据规范化(Normalization)的重要性

前言

数据规范-Normalization是深度学习中我们很容易忽视,也很容易出错的问题。我们训练的所有数据在输入到模型中的时候都要进行一些规范化。例如在pytorch中,有些模型是通过规范化后的数据进行训练的,所以我们在使用这些预训练好的模型的时候,要注意在将自己的数据投入模型中之前要首先对数据进行规范化。

在pytorch附带的模型中我们可以选择预训练模型

import torchvision.models as models
resnet18 = models.resnet18(pretrained=True)
alexnet = models.alexnet(pretrained=True)
squeezenet = models.squeezenet1_0(pretrained=True)
vgg16 = models.vgg16(pretrained=True)
densenet = models.densenet161(pretrained=True)
inception = models.inception_v3(pretrained=True)

预训练模型即模型中的权重参数都被训练好了,在构造模型后读取模型权重即可。

但是有些东西需要注意:

  • 模型的权重参数是训练好的,但是要确定你输入的数据和预训练时使用的数据格式一致。
  • 要注意什么时候需要格式化什么时候不需要。

也就是说,模型设计的正确只是第一步,我们输入的图像数据的格式的正确性也是特别重要的,我们平常输入的图像大部分都是三通道RGB彩色图像,数据范围大部分都是[0-255],也就是通常意义上的24-bit图(RGB三通道各8位)。在pytorch中有专门的一些模块:transforms 模块来对图像进行一些预处理操作:

transform = transforms.Compose([
        transforms.RandomResizedCrop(100),
        transforms.RandomHorizontalFlip(),
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ])

正文

而且在pytorch的官方介绍中也提到了,pytorch使用的预训练模型搭配的数据必须是:

《浅谈深度学习训练中数据规范化(Normalization)的重要性》

也就是3通道RGB图像(3 x H x W),而且高和宽最好不低于224(因为拿来做预训练的模型大小就是224 x 224),并且图像数据大小的范围为[0-1],使用mean和std去Normalize。

为什么这样说官方也说了,因为所有的预训练模型是使用经过normal后的数据得到的,所以我们输入的数据也必须经过格式化,否则很容易出现损失爆炸。

为什么我们要进行格式化呢?

我们选取一组人脸图片来举个例子,这组人脸图像的格式是这样的:

  • 取100组人脸图像
  • 图像的高和宽都是100
  • 3通道,像素点的范围是[0-255]

这里从Labeled faces in the Wild数据集中取出100个人脸图像,这个数据集中每张图像对应着一个名字,而且每张图像的脸都差不多被定位到了中间。

《浅谈深度学习训练中数据规范化(Normalization)的重要性》

我们有了这一组数据后,接下来要做的一般是这几个步骤:

统一形状和大小

在图像输入到神经网络之前要注意,每张图都要保证一样的尺寸和大小。大部分的模型要求输入的图像的形状是正方形,一般都是256 x 256、128 x 128 、 64 x 64或者其他的形状,这种方形是最好进行训练的。当然其他形状也是可以的,比如长方形,但如果是长方形的话就要注意设计卷积层通道的时候要稍微注意一下。总之,我们都是先对图像极性crop,crop成正方形,一般取图像的中心位置。

《浅谈深度学习训练中数据规范化(Normalization)的重要性》

比如下面这张人脸图(256 x 256)就很舒服,呃,因为不用修剪了。

《浅谈深度学习训练中数据规范化(Normalization)的重要性》

图像比例

比例也是比较重要的,图像形状确定了,但是有些时候我们在训练时随着卷积层越来越深,特征图越来越小,为了实现一些功能,我们所需要的图像的比例也要稍微改变一下。不论是放大还是缩小,假如缩小到100像素,我们就让上面的图像乘以0.39(100/256)。但是放大和缩小时都要考虑四舍五入,是floor还是ceil就各有见地了。

均值,标准差

一组图像集的均值和标准差可以很好地概括这组图像的信息和特征。均值就是一组数据的平均水平,而标准差代表的是数据的离散程度。下图是之前展示的100张人脸图的均值图和标准差图,可以看到左面的均值图中,明显看到一个模糊的人脸。并且可以看出100张人脸图中,人的脸是分布在中心的,而右边的标准差图可以看到中心颜色偏暗(小于100),四周偏亮(大于100),也就是说明100张图中,图像四周的分布明显变化比较剧烈。

在这样Normalize之后,神经网络在训练的过程中,梯度对每一张图片的作用都是平均的,也就是不存在比例不匹配的情况。而在normalize之前每张图片的特征分布都是不一样的,有的陡峭有的平缓,如果不进行预处理,那么在梯度下降的时候有些图片的特征值比较大而有些则比较小,这样梯度运算无法顾及到不同特征不同维度不同层次的下降趋势,这样很难进行训练,loss会不停的震荡。

《浅谈深度学习训练中数据规范化(Normalization)的重要性》

格式化(Normalization)

说到重点了,我们在文章最开始说的格式化,其实即使在一组图中,每个图像的像素点首先减去所有图像均值的像素点,然后再除以标准差。这样可以保证所有的图像分布都相似,也就是在训练的时候更容易收敛,也就是训练的更快更好了。另外,不同图像像素点范围的mean和std是不一样的,一般我们输入的都是[0-1]或者[0-255]的图像数据,在pytorch的模型中,输入的是[0-1],而在caffe的模型中,我们输入的是[0-255]。

下面这个图就是在格式化后的100张人脸图。

《浅谈深度学习训练中数据规范化(Normalization)的重要性》

显然,格式化就是使数据中心对齐,如cs231n中的示例图,左边是原始数据,中间是减去mean的数据分布,右边是除以std标准差的数据分布,当然cs231n中说除以std其实可以不去执行,因为只要数据都遵循一定范围的时候(比如图像都是[0-255])就没有必要这样做了。

《浅谈深度学习训练中数据规范化(Normalization)的重要性》

维数变化

有时候需要输入不是彩色图,这时候可能需要对数据进行降维操作,也就是RGB->GRAY,当然还有颜色通道和色彩通道的改变,例如RGB->BGR,或者RGB->YUV。颜色通道的改变是为了实现不同的任务和功能,这就要视情况来决定。

《浅谈深度学习训练中数据规范化(Normalization)的重要性》

其他变化:数据增强

在pytorch的transforms模块中有很多的变化,都可以用来做数据增强,比如图像翻转,旋转,极坐标变换,都可以得到不同的“原始图”从而加大训练变量达到很好的训练效果。这里不多说,这个需要单独说明。

参考文章

https://becominghuman.ai/image-data-pre-processing-for-neural-networks-498289068258

http://cs231n.github.io/neural-networks-2/

  点赞
本篇文章采用 署名-非商业性使用-禁止演绎 4.0 国际 进行许可
转载请务必注明来源: https://oldpan.me/archives/use-pytorch-normalization

   关注Oldpan博客微信公众号,你最需要的及时推送给你。


  1. 你呢说道:

    博主,我有一个问题,希望您能解答一下,谢谢您。我的训练数据分布在很多的文件夹中,我训练网络的时候需要从一个文件夹中导入数据(一个批次),这些数据是没有标准化的,我想对数据进行标准化,是以每批次数据为基础分别求一个标准差和平均值来标准化,还是以所有训练数据为基础求一个总的标准差和平均值来标准化??

  2. s
    subson说道:

    std应该是标准差,不是方差

    1. O
      Oldpan说道:

      多谢提醒,已修正~

  3. a
    avery说道:

    真的棒~支持博主。学习了很多知识。受益匪浅

    1. O
      Oldpan说道:

      哈哈,谢谢~