为啥 Pytorch 官方使用 mean=[0.485, 0.456, 0.406] 和 std=[0.229, 0.224, 0.225] 来规范化图像?

Posted

技术标签:

【中文标题】为啥 Pytorch 官方使用 mean=[0.485, 0.456, 0.406] 和 std=[0.229, 0.224, 0.225] 来规范化图像?【英文标题】:Why Pytorch officially use mean=[0.485, 0.456, 0.406] and std=[0.229, 0.224, 0.225] to normalize images?为什么 Pytorch 官方使用 mean=[0.485, 0.456, 0.406] 和 std=[0.229, 0.224, 0.225] 来规范化图像? 【发布时间】:2020-01-28 18:44:54 【问题描述】:

在此页面 (https://pytorch.org/vision/stable/models.html) 中,它说“所有预训练模型都期望输入图像以相同方式归一化,即小批量 3 通道 RGB 图像的形状 (3 x H x W),其中 H 和 W 预计至少为 224。图像必须加载到 [0, 1] 的范围内,然后使用 mean = [0.485, 0.456, 0.406]std = [0.229, 0.224, 0.225]" 进行归一化。

通常的meanstd不应该是[0.5, 0.5, 0.5][0.5, 0.5, 0.5]吗?为什么会设置这么奇怪的值?

【问题讨论】:

***.com/questions/57532661/… 【参考方案1】:

使用 Imagenet 的均值和标准差是一种常见的做法。它们是根据数百万张图像计算得出的。如果您想在自己的数据集上从头开始训练,可以计算新的均值和标准差。否则,建议使用具有自己的均值和标准差的 Imagenet 预测试模型。

【讨论】:

【参考方案2】:

在该示例中,他们使用 ImageNet 的均值和标准差,但如果您查看他们的 MNIST 示例,均值和标准差是一维的(因为输入是灰度 - 没有 RGB 通道)。

是否使用ImageNet's mean 和 stddev 取决于您的数据。假设您的数据是“自然场景”的普通照片(人物、建筑物、动物、不同的照明/角度/背景等),并假设您的数据集以与 ImageNet 相同的方式存在偏差(就类平衡而言),那么可以使用 ImageNet 的场景统计数据进行归一化。如果照片在某种程度上是“特殊的”(颜色过滤、对比度调整、不常见的照明等)或“非自然主题”(医学图像、卫星图像、手绘等),那么我建议正确标准化您的数据集在模型训练之前!*

这里有一些示例代码可以帮助您入门:

import os
import torch
from torchvision import datasets, transforms
from torch.utils.data.dataset import Dataset
from tqdm.notebook import tqdm
from time import time

N_CHANNELS = 1

dataset = datasets.MNIST("data", download=True,
                 train=True, transform=transforms.ToTensor())
full_loader = torch.utils.data.DataLoader(dataset, shuffle=False, num_workers=os.cpu_count())

before = time()
mean = torch.zeros(1)
std = torch.zeros(1)
print('==> Computing mean and std..')
for inputs, _labels in tqdm(full_loader):
    for i in range(N_CHANNELS):
        mean[i] += inputs[:,i,:,:].mean()
        std[i] += inputs[:,i,:,:].std()
mean.div_(len(dataset))
std.div_(len(dataset))
print(mean, std)

print("time elapsed: ", time()-before)

在计算机视觉中,“自然场景”具有特定含义,与自然与人造无关,请参阅https://en.wikipedia.org/wiki/Natural_scene_perception

* 否则,由于损失函数的伸长,您会遇到优化问题——请参阅my answer here。

【讨论】:

【参考方案3】:

我无法按计划计算标准偏差,但使用下面的代码进行了计算。灰度图像网络的训练数据集均值和标准差为(任意取整):

平均值:0.44531356896770125

标准偏差:0.2692461874154524

def calcSTD(d):
    meanValue = 0.44531356896770125
    squaredError = 0
    numberOfPixels = 0
    for f in os.listdir("/home/imagenet/ILSVRC/Data/CLS-LOC/train/"+str(d)+"/"): 
        if f.endswith(".JPEG"):
            
            image = imread("/home/imagenet/ILSVRC/Data/CLS-LOC/train/"+str(d)+"/"+str(f))
                
            ###Transform to gray if not already gray anyways  
            if  np.array(image).ndim == 3:
                matrix = np.array(image)
                blue = matrix[:,:,0]/255
                green = matrix[:,:,1]/255
                red = matrix[:,:,2]/255
                gray = (0.2989 * red + 0.587 * green + 0.114 * blue)
            else:
                gray = np.array(image)/255
            ###----------------------------------------------------       
                    
            for line in gray:
                for pixel in line:


                    squaredError += (pixel-meanValue)**2
                    numberOfPixels += 1
    
    return (squaredError, numberOfPixels)

a_pool = multiprocessing.Pool()
folders = []
[folders.append(f.name) for f in os.scandir("/home/imagenet/ILSVRC/Data/CLS-LOC/train") if f.is_dir()]
resultStD = a_pool.map(calcSTD, folders)

StD = (sum([intensity[0] for intensity in resultStD])/sum([pixels[1] for pixels in resultStD]))**0.5
print(StD)

来源:https://***.com/a/65717887/7156266

【讨论】:

【参考方案4】:

TL;DR

我相信原因是,就像(深度)机器学习中的许多事情一样, 它恰好运行良好。

详情

统计中的“标准化”一词可以应用于不同的转换。 例如: for all x in X: x->(x - min(x))/(max(x)-min(x) 会将 X 的值标准化并拉伸到 [0..1] 范围。

另一个例子: for all x in X: x->(x - mean(X))/stdv(x) 会将图像转换为均值 = 0,标准差 = 1。这种转换称为标准分数,有时也称为标准化。如果我们将结果乘以 sigma,然后加上 mu,我们会将结果设置为 mean=mu 和 stdv=sigma

Pytorch 不做任何这些 - 相反,它应用标准分数,但不是使用 X 的平均值和 stdv 值(要归一化的图像),而是使用平均平均值和平均 stdv 的值。 Imagenet 图像集。但不均值和标准差设置为这些值。

如果图像恰好与 Imagenet 集合的平均值具有相同的均值和标准差 - 它将被转换为均值 0 和标准偏差 1。 否则,它将转换为它的平均值和标准差以及所述平均值的函数。

对我来说,不清楚这严格意味着什么(为什么是标准差平均值?为什么要对平均值应用标准分数?)。

也许有人可以澄清这一点?

但是,与深度机器学习中的许多事情一样,该理论尚未完全确立。我的猜测是人们尝试了不同的标准化,而这个恰好表现良好。

这并不意味着这是最好的标准化,只是说它是一个不错的标准化。当然,如果您使用的是使用此特定归一化学习的预训练值,您可能最好使用与训练中使用的相同的归一化进行推理或派生模型。

【讨论】:

以上是关于为啥 Pytorch 官方使用 mean=[0.485, 0.456, 0.406] 和 std=[0.229, 0.224, 0.225] 来规范化图像?的主要内容,如果未能解决你的问题,请参考以下文章

不只是支持Windows, PyTorch 0.4新版本变动详解与升级指南

为啥我们将图像归一化为mean=0.5,std=0.5?

为啥这个 Pytorch 官方教程中没有 .train() 方法?

Pytorch 0.3加载0.4模型

无缝整合PyTorch 0.4与Caffe2,PyTorch 1.0问世

无缝整合PyTorch 0.4与Caffe2,PyTorch 1.0即将问世