我正在尝试使用transforms.compose将我的图像转换为范围为[0255]的归一化图像,而不是将其归一化为[0,1]来训练我的模型。我如何让我的代码做到这一点。目前,它对[0,1]中的图像进行了归一化。我如何将其乘以255,使其为0-255,或者它不是那么简单吗?
def build_model(self):
""" DataLoader """
train_transform = transforms.Compose([
transforms.RandomHorizontalFlip(),
transforms.Resize((self.img_size + 30, self.img_size+30)),
transforms.RandomCrop(self.img_size),
transforms.ToTensor(),
transforms.Normalize(mean=(0.5, 0.5, 0.5), std=(0.5, 0.5, 0.5))
])
test_transform = transforms.Compose([
transforms.Resize((self.img_size, self.img_size)),
transforms.ToTensor(),
transforms.Normalize(mean=(0.5, 0.5, 0.5), std=(0.5, 0.5, 0.5))
])
理想情况下,通过计算整个训练集的mean
和std
并将其应用于所有数据集(训练、验证和测试集(,对[0, 1]
之间的值进行归一化,然后标准化。
以下基本上是x in [x_min, x_max] -> x' in [0, 1]
映射:
x_min, x_max = x.min(), x.max()
x = (x - x_min) / (x_max-x_min)
然后标准化,例如使用z分数,这使得mean(x')=0
和std(x')=1
:
mean, std = x.mean(), x.std()
x = (x - mean) / std
回到您的问题,torchvision.transforms.Normalize
被描述为:
output[channel] = (input[channel] - mean[channel]) / std[channel]
如果将std
参数除以255,则输出将最终乘以255。
以下是形状为(b=1, c=3, h=1, w=3)
:的示例
> x = torch.tensor([[[[0.2, 0.3, 0.6]], [[0.1, 0.4, 0.2]], [[0.1, 0.8, 0.6]]]])
> mean, std = x.mean(), x.std()
tensor(0.3667), tensor(0.2500)
> t = T.Normalize(mean=mean, std=std/255)
> t(x).mean(), t(x).std()
tensor(~0), tensor(255.)
然而,如果您只是想在torchvision.transforms.Compose
管道内将数据乘以255,您可以执行以下操作:
T.Compose([
# other transforms
T.ToTensor(),
T.Normalize(mean=(0,)*3, std=(255,)*3)
])
或者只使用lambda:
T.Compose([
# other transforms
T.ToTensor(),
lambda x: x*255
])
已将torchvision.transforms
导入为T
第一个选项
我注意到,当你不使用ToTensor
,而是通过numpy进行转换时,你可以在没有规范化的情况下实现转换。那么所得到的张量将根本不会被归一化。
我的例子是使用pillow
。当再次转换为图像时,请再次使用numpy,不要使用ToPilImage
。
因此:
from PIL import Image
import numpy as np
image = Image.open('image.jpg')
im_arr = np.array(image)
# optional type conversion
im_arr = im_arr.astype(np.float32)
image_tensor = torch.tensor(image).unsqueeze_(0)
# do stuff with your image
img_np_arr = np.array(image_tensor_conv2d.squeeze_(0))
valid_pil_image = Image.fromarray(img_np_arr).convert('RGB')
valid_pil_image.save('image_torch.jpg')
也会做这项工作。
作为作曲家,你可以像一样写作
image_transform = transfroms.Compose([
transforms.Lambda(lambda image: torch.tensor(numpy.array(image).astype(numpy.float32)).unsqueeze(0)),
transforms.Normalize((value,), (value,))
)]
参考请参见此处
第二种选择
另一种选择是使用PilToTensor
。检查https://pytorch.org/vision/stable/generated/torchvision.transforms.PILToTensor.html