寻找一堆 torch.Tensors 的方法和标准(从 ndarray 图像转换而来)

Finding means and stds of a bunch of torch.Tensors (that are converted from ndarray images)

to_tensor = transforms.ToTensor()
img = to_tensor(train_dataset[0]['image'])
img

在预期的 0 和 1 之间转换我的图像值。它还将 img 转换为 ndarraytorch.Tensor.

以前,在不使用 to_tensor(我现在需要它)的情况下,以下代码片段有效(不确定这是否是查找训练集均值和标准的最佳方法,但现在不是'不工作。我怎样才能让它工作?

image_arr = []

for i in range(len(train_dataset)):
    image_arr.append(to_tensor(train_dataset[i]['image']))

print(np.mean(image_arr, axis=(0, 1, 2)))
print(np.std(image_arr, axis=(0, 1, 2)))

错误是:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-147-0e007c030629> in <module>
      4     image_arr.append(to_tensor(train_dataset[i]['image']))
      5 
----> 6 print(np.mean(image_arr, axis=(0, 1, 2)))
      7 print(np.std(image_arr, axis=(0, 1, 2)))

<__array_function__ internals> in mean(*args, **kwargs)

~/anaconda3/lib/python3.7/site-packages/numpy/core/fromnumeric.py in mean(a, axis, dtype, out, keepdims)
   3333 
   3334     return _methods._mean(a, axis=axis, dtype=dtype,
-> 3335                           out=out, **kwargs)
   3336 
   3337 

~/anaconda3/lib/python3.7/site-packages/numpy/core/_methods.py in _mean(a, axis, dtype, out, keepdims)
    133 
    134 def _mean(a, axis=None, dtype=None, out=None, keepdims=False):
--> 135     arr = asanyarray(a)
    136 
    137     is_float16_result = False

~/anaconda3/lib/python3.7/site-packages/numpy/core/_asarray.py in asanyarray(a, dtype, order)
    136 
    137     """
--> 138     return array(a, dtype, copy=False, order=order, subok=True)
    139 
    140 

ValueError: only one element tensors can be converted to Python scalars

您正在尝试使用 numpy 计算张量的平均值吗?

您需要将数据转换为 NumPy,然后将 meanstd 计算为

image_arr = []
for i in range(len(train_dataset)):
       image_arr.append((to_tensor(train_dataset[i]['image'])).cpu().detach().numpy())

print(np.mean(image_arr, axis=(0, 1, 2)))
print(np.std(image_arr, axis=(0, 1, 2)))

这是一个工作示例:

import torch
from torchvision import transforms
train_dataset = torch.rand(100, 32, 32, 3)
image_arr = []
to_tensor = transforms.ToTensor()

for i in range(len(train_dataset)):
    # to tensor will give you a tensor which is emulated here by reading the tensor at i
    image_arr.append(train_dataset[i])

print(torch.mean(torch.stack(image_arr, dim=0), dim=(0, 1, 2)))
print(torch.std(torch.stack(image_arr, dim=0), dim=(0, 1, 2)))

我做了什么?

我使用 torch.stack 将图像数组连接成一个 torch 张量,并使用 torch.meantorch.std 计算统计数据。我不建议为了评估统计数据而转换回 numpy,因为它会导致从 GPU 到 CPU.

的不必要转换

有关渠道维度的更多信息: 上面的示例假设最后一个维度是通道,图像是 32x32x3,批量大小为 100。使用 PIL (pillow) 或 numpy 加载图像时通常会出现这种情况。在这种情况下,图像将作为 HWC(高宽通道)加载。这似乎也是查看代码示例时所问问题的维度。

如果图像张量是CHW格式,那么你应该使用

print(torch.mean(torch.stack(image_arr, dim=0), dim=(0, 2, 3)))
print(torch.std(torch.stack(image_arr, dim=0), dim=(0, 2, 3)))

Torch 张量通常是 CHW 格式,因为 Conv 层期望 CHW 格式。当 toTensor 变换应用于图像(PIL 图像)时,这是自动完成的。有关完整规则,请参阅 toTensor here.

的文档