torchvision.transforms.Normalize 是如何操作的?

问题描述 投票:0回答:2

我不明白

Pytorch
中的标准化是如何工作的。

我想将形状为

0
的张量
1
中所有列的平均值设置为
x
,将标准差设置为
(2, 2, 3)

一个简单的例子:

>>> x = torch.tensor([[[ 1.,  2.,  3.],
                       [ 4.,  5.,  6.]],

                       [[ 7.,  8.,  9.],
                        [10., 11., 12.]]])

>>> norm = transforms.Normalize((0, 0), (1, 1))
>>> norm(x)
tensor([[[ 1.,  2.,  3.],
         [ 4.,  5.,  6.]],

        [[ 7.,  8.,  9.],
         [10., 11., 12.]]])

所以应用归一化变换时没有任何变化。这是为什么?

pytorch torchvision
2个回答
28
投票

为了回答您的问题,您现在已经意识到

torchvision.transforms.Normalize
并不像您预期的那样工作。那是因为它的目的不是:

  • 标准化:(使您的数据范围在

    [0, 1]
    )也不

  • 标准化:使您的数据的

    mean=0
    std=1
    (这就是您正在寻找的。

T.Normalize
执行的操作仅仅是移位尺度变换:

output[channel] = (input[channel] - mean[channel]) / std[channel]

参数名称

mean
std
似乎相当具有误导性,因为它并不是指所需的 output 统计数据,而是指任何任意值。没错,如果你输入
mean=0
std=1
,它会给你
output = (input - 0) / 1 = input
。因此,当您期望分别获得均值和方差张量
norm
0
时,您收到的结果是函数
1
对张量值没有影响。

但是,提供正确的

mean
std
参数,i.e.
mean=mean(data)
std=std(data)
时,那么你最终会逐个通道计算数据通道的 z-score,这就是通常称为“标准化”。因此,为了真正获得 mean=0
std=1
,您首先需要计算数据的平均值和标准差。
如果你这样做:

>>> mean, std = x.mean(), x.std() (tensor(6.5000), tensor(3.6056))

它将分别为您提供全局平均值和全局标准差。

相反,您想要的是测量每个

通道的一阶和二阶统计数据。因此,我们需要在除

torch.mean 之外的所有维度上应用 torch.std

dim=1
。这两个函数都可以接收维度的
tuple
>>> mean, std = x.mean((0,2)), x.std((0,2)) (tensor([5., 8.]), tensor([3.4059, 3.4059]))

以上是沿每个通道测量的
x
的正确平均值和标准差。从那里您可以继续使用

T.Normalize(mean, std)

 使用正确的移位比例参数正确转换数据 
x
>>> norm(x)
tensor([[[-1.5254, -1.2481, -0.9707],
         [-0.6934, -0.4160, -0.1387]],

        [[ 0.1387,  0.4160,  0.6934],
         [ 0.9707,  1.2481,  1.5254]]])

参见 

2
投票

用平均值和标准差对张量图像进行归一化。给定均值: (mean[1],...,mean[n]) 和 std: (std[1],..,std[n]) 对于 n 个通道,这 变换将标准化输入火炬的每个通道。*张量,即 输出[通道] = (输入[通道] - 平均值[通道]) / std[通道]

因此,如果您有

mean=0

std=1

,那么 
output=(output - 0) / 1
 不会改变。
扩展上述解释的示例:

from torchvision import transforms import torch norm = transforms.Normalize((0,0),(1,2)) x = torch.tensor([[[1.0,2,3],[4,5,6]],[[7,8,9],[10,11,12]]]) out = norm(x) print(x) print(out)

输出:
tensor([[[ 1.,  2.,  3.],  
         [ 4.,  5.,  6.]], 

        [[ 7.,  8.,  9.],  
         [10., 11., 12.]]])
tensor([[[1.0000, 2.0000, 3.0000], 
         [4.0000, 5.0000, 6.0000]],

        [[3.5000, 4.0000, 4.5000],
         [5.0000, 5.5000, 6.0000]]])

如您所见,第一个通道不变,第二个通道除以 2。
    

© www.soinside.com 2019 - 2024. All rights reserved.