torchvision.transforms.Normalize 是如何运作的?
How does torchvision.transforms.Normalize operates?
我不明白 Pytorch
中的规范化是如何工作的。
我想将形状为 (2, 2, 3)
.[=17= 的张量 x
中所有列的均值设置为 0
,标准差设置为 1
]
一个简单的例子:
>>> 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.]]])
所以在应用归一化变换时没有任何改变。这是为什么?
按照documentation of torchvision.transforms.Normalize的解释:
Normalize a tensor image with mean and standard deviation. Given mean:
(mean[1],...,mean[n]) and std: (std[1],..,std[n]) for n channels, this
transform will normalize each channel of the input torch.*Tensor i.e.,
output[channel] = (input[channel] - mean[channel]) / std[channel]
因此,如果您有 mead=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.
实际回答您的问题。您现在已经意识到 torchvision.transforms.Normalize
并不像您期望的那样工作。那是因为它不是为了
normalize: (使你的数据范围在[0, 1]
) nor
标准化:使数据的 mean=0
和 std=1
(这就是你在找
T.Normalize
执行的操作仅仅是一个平移变换:
output[channel] = (input[channel] - mean[channel]) / std[channel]
给定参数mean
和std
,调用函数Normalize
及其参数[=22=感觉违反直觉]和"std"
...自然地,如果你输入mean=0
和std=1
,它会给你output = (input - 0) / 1 = input
。因此你得到的结果是:norm
没有效果。
但是,如果您提供 mean=mean(data)
和 std=std(data)
作为参数,那么您最终会逐个通道计算数据通道的 z-score,这通常称为 'standardization'。因此,为了实际获得 mean=0
和 std=1
,您首先需要计算数据的均值和标准差。
如果你这样做:
>>> mean, std = x.mean(), x.std()
(tensor(6.5000), tensor(3.6056))
它将分别为您提供全球平均值和全球标准差。
相反,您想要的是测量每个每个通道。所以我们想在 dim=1
上的所有维度上应用 torch.mean
and torch.std
。这两个函数都可以接收维度为 的元组 :
>>> mean, std = flattened.mean((0,2)), flattened.std((0,2))
(tensor([5., 8.]), tensor([3.4059, 3.4059]))
以上是 x
沿每个通道测量的正确平均值和标准偏差。从那里你可以继续使用 torchvision.transforms.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]]])
我不明白 Pytorch
中的规范化是如何工作的。
我想将形状为 (2, 2, 3)
.[=17= 的张量 x
中所有列的均值设置为 0
,标准差设置为 1
]
一个简单的例子:
>>> 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.]]])
所以在应用归一化变换时没有任何改变。这是为什么?
按照documentation of torchvision.transforms.Normalize的解释:
Normalize a tensor image with mean and standard deviation. Given mean: (mean[1],...,mean[n]) and std: (std[1],..,std[n]) for n channels, this transform will normalize each channel of the input torch.*Tensor i.e., output[channel] = (input[channel] - mean[channel]) / std[channel]
因此,如果您有 mead=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.
实际回答您的问题。您现在已经意识到 torchvision.transforms.Normalize
并不像您期望的那样工作。那是因为它不是为了
normalize: (使你的数据范围在
[0, 1]
) nor标准化:使数据的
mean=0
和std=1
(这就是你在找
T.Normalize
执行的操作仅仅是一个平移变换:
output[channel] = (input[channel] - mean[channel]) / std[channel]
给定参数mean
和std
,调用函数Normalize
及其参数[=22=感觉违反直觉]和"std"
...自然地,如果你输入mean=0
和std=1
,它会给你output = (input - 0) / 1 = input
。因此你得到的结果是:norm
没有效果。
但是,如果您提供 mean=mean(data)
和 std=std(data)
作为参数,那么您最终会逐个通道计算数据通道的 z-score,这通常称为 'standardization'。因此,为了实际获得 mean=0
和 std=1
,您首先需要计算数据的均值和标准差。
如果你这样做:
>>> mean, std = x.mean(), x.std()
(tensor(6.5000), tensor(3.6056))
它将分别为您提供全球平均值和全球标准差。
相反,您想要的是测量每个每个通道。所以我们想在 dim=1
上的所有维度上应用 torch.mean
and torch.std
。这两个函数都可以接收维度为 的元组 :
>>> mean, std = flattened.mean((0,2)), flattened.std((0,2))
(tensor([5., 8.]), tensor([3.4059, 3.4059]))
以上是 x
沿每个通道测量的正确平均值和标准偏差。从那里你可以继续使用 torchvision.transforms.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]]])