【torch杂记】torchvision.transforms中的ToTensor和Normalize

2024-03-05 17:58

本文主要是介绍【torch杂记】torchvision.transforms中的ToTensor和Normalize,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

torchvision.transforms中的ToTensor和Normalize

文章目录

        • torchvision.transforms中的ToTensor和Normalize
          • 参考
          • transforms.ToTensor()
          • transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
          • 二者的调用_Compose

参考
  • 关于transforms.Normalize()函数
  • PyTorch中的contiguous
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
transforms.ToTensor()
  • 能够把灰度范围从0-255变换到0-1之间

  • 从源码的角度看,调用的ToTensor的时候是调用这个class的__call__方法,然后ToTensor的call是调用了F的to_tensor方法,F是functional.py

    • class ToTensor(object):"""Convert a ``PIL Image`` or ``numpy.ndarray`` to tensor.Converts a PIL Image or numpy.ndarray (H x W x C) in the range[0, 255] to a torch.FloatTensor of shape (C x H x W) in the range [0.0, 1.0]if the PIL Image belongs to one of the modes (L, LA, P, I, F, RGB, YCbCr, RGBA, CMYK, 1)or if the numpy.ndarray has dtype = np.uint8In the other cases, tensors are returned without scaling."""def __call__(self, pic):"""Args:pic (PIL Image or numpy.ndarray): Image to be converted to tensor.Returns:Tensor: Converted image."""# 这里会调用functional中的to_tensor方法return F.to_tensor(pic)def __repr__(self):return self.__class__.__name__ + '()'
      
  • to_tensor源码:

    • def to_tensor(pic):
      """Convert a ``PIL Image`` or ``numpy.ndarray`` to tensor.
      See ``ToTensor`` for more details.
      Args:pic (PIL Image or numpy.ndarray): Image to be converted to tensor.
      Returns:Tensor: Converted image.
      """
      if not(_is_pil_image(pic) or _is_numpy_image(pic)):raise TypeError('pic should be PIL Image or ndarray. Got {}'.format(type(pic)))if isinstance(pic, np.ndarray):# handle numpy arrayif pic.ndim == 2:pic = pic[:, :, None]img = torch.from_numpy(pic.transpose((2, 0, 1)))# backward compatibilityif isinstance(img, torch.ByteTensor):return img.float().div(255)else:return imgif accimage is not None and isinstance(pic, accimage.Image):nppic = np.zeros([pic.channels, pic.height, pic.width], dtype=np.float32)pic.copyto(nppic)return torch.from_numpy(nppic)# handle PIL Image
      if pic.mode == 'I':img = torch.from_numpy(np.array(pic, np.int32, copy=False))
      elif pic.mode == 'I;16':img = torch.from_numpy(np.array(pic, np.int16, copy=False))
      elif pic.mode == 'F':img = torch.from_numpy(np.array(pic, np.float32, copy=False))
      elif pic.mode == '1':img = 255 * torch.from_numpy(np.array(pic, np.uint8, copy=False))
      else:img = torch.ByteTensor(torch.ByteStorage.from_buffer(pic.tobytes()))
      # PIL image mode: L, LA, P, I, F, RGB, YCbCr, RGBA, CMYK
      if pic.mode == 'YCbCr':nchannel = 3
      elif pic.mode == 'I;16':nchannel = 1
      else:nchannel = len(pic.mode)
      img = img.view(pic.size[1], pic.size[0], nchannel)
      # put it from HWC to CHW format
      # yikes, this transpose takes 80% of the loading time/CPU
      img = img.transpose(0, 1).transpose(0, 2).contiguous()
      if isinstance(img, torch.ByteTensor):return img.float().div(255)
      else:return img
      
  • 对于RGB图片,to_tensor它主要做了四件事

    • 1、img = torch.ByteTensor(torch.ByteStorage.from_buffer(pic.tobytes()))将其转换成uint8类型的tensor,且是1维的

      • image-20210702001918510
      • image-20210702002517465
    • 2、nchannel = len(pic.mode)设定通道数,img = img.view(pic.size[1], pic.size[0], nchannel)将img重新变形成3维的tensor

      • image-20210702002357284
      • image-20210702002446945
    • 3、img = img.transpose(0, 1).transpose(0, 2).contiguous(),transpose函数的作用是交换坐标轴,类似二维中的转置的概念,而contiguous函数的作用是让tensor的底层变得连续(相当于改变底层的一维数组)

      • torch.view等方法操作需要连续的Tensor。transpose、permute 操作虽然没有修改底层一维数组,但是新建了一份Tensor元信息,并在新的元信息中的 重新指定 stride。torch.view 方法约定了不修改数组本身,只是使用新的形状查看数据。如果我们在 transpose、permute 操作后执行 view,Pytorch 会报错)
    • 4、return img.float().div(255),转成float再除以255(因为之前是uint8,区间是0-255,因此除以255之后就变成0-1区间)

    • 至此他就实现了将pic图片数组转成0-1区间的tensor

transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
  • 则把0-1变换到(-1,1)

  • class Normalize(object):"""Normalize a tensor image with mean and standard deviation.Given mean: ``(M1,...,Mn)`` and std: ``(S1,..,Sn)`` for ``n`` channels, this transformwill normalize each channel of the input ``torch.*Tensor`` i.e.``input[channel] = (input[channel] - mean[channel]) / std[channel]``.. note::This transform acts out of place, i.e., it does not mutates the input tensor.Args:mean (sequence): Sequence of means for each channel.std (sequence): Sequence of standard deviations for each channel."""def __init__(self, mean, std, inplace=False):self.mean = meanself.std = stdself.inplace = inplacedef __call__(self, tensor):"""Args:tensor (Tensor): Tensor image of size (C, H, W) to be normalized.Returns:Tensor: Normalized Tensor image."""return F.normalize(tensor, self.mean, self.std, self.inplace)def __repr__(self):return self.__class__.__name__ + '(mean={0}, std={1})'.format(self.mean, self.std)
    
  • 和ToTensor一样,调用的时候是调用call方法,此时输入的tensor如下图所示,维0-1的范围

  • 接下来是调用functional下的normalize方法,源码如下:

    • def normalize(tensor, mean, std, inplace=False):"""Normalize a tensor image with mean and standard deviation... note::This transform acts out of place by default, i.e., it does not mutates the input tensor.See :class:`~torchvision.transforms.Normalize` for more details.Args:tensor (Tensor): Tensor image of size (C, H, W) to be normalized.mean (sequence): Sequence of means for each channel.std (sequence): Sequence of standard deviations for each channely.Returns:Tensor: Normalized Tensor image."""if not _is_tensor_image(tensor):raise TypeError('tensor is not a torch image.')if not inplace:tensor = tensor.clone()mean = torch.tensor(mean, dtype=torch.float32)std = torch.tensor(std, dtype=torch.float32)tensor.sub_(mean[:, None, None]).div_(std[:, None, None])return tensor
    • 分析如下

      • 由于inplace默认为false,因此,首先会clone下tensor
      • mean和tensor都是(0.5,0.5,0.5)的元组,然后通过torch.tensor变成float32的一维tensor
        • image-20210702115138113
      • 然后这句就开始变换了tensor.sub_(mean[:, None, None]).div_(std[:, None, None])
        • mean[:, None, None]和std[:, None, None]将其变形成(3,1,1)的tensor然后相减,(0~1-0.5)/0.5=-1~1
      • 故此实现转换
二者的调用_Compose
  • 一般长这样

    • transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
      
  • 然后她就说传入一个数组,然后call函数遍历调用即可,下面是它的源码

    • class Compose(object):"""Composes several transforms together.Args:transforms (list of ``Transform`` objects): list of transforms to compose.Example:>>> transforms.Compose([>>>     transforms.CenterCrop(10),>>>     transforms.ToTensor(),>>> ])"""def __init__(self, transforms):self.transforms = transformsdef __call__(self, img):for t in self.transforms:img = t(img)return imgdef __repr__(self):format_string = self.__class__.__name__ + '('for t in self.transforms:format_string += '\n'format_string += '    {0}'.format(t)format_string += '\n)'return format_string
      

这篇关于【torch杂记】torchvision.transforms中的ToTensor和Normalize的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/777343

相关文章

pytorch+torchvision+python版本对应及环境安装

《pytorch+torchvision+python版本对应及环境安装》本文主要介绍了pytorch+torchvision+python版本对应及环境安装,安装过程中需要注意Numpy版本的降级,... 目录一、版本对应二、安装命令(pip)1. 版本2. 安装全过程3. 命令相关解释参考文章一、版本对

pytorch torch.nn.functional.one_hot函数介绍

torch.nn.functional.one_hot 是 PyTorch 中用于生成独热编码(one-hot encoding)张量的函数。独热编码是一种常用的编码方式,特别适用于分类任务或对离散的类别标签进行处理。该函数将整数张量的每个元素转换为一个独热向量。 函数签名 torch.nn.functional.one_hot(tensor, num_classes=-1) 参数 t

torch.nn 与 torch.nn.functional的区别?

区别 PyTorch中torch.nn与torch.nn.functional的区别是:1.继承方式不同;2.可训练参数不同;3.实现方式不同;4.调用方式不同。 1.继承方式不同 torch.nn 中的模块大多数是通过继承torch.nn.Module 类来实现的,这些模块都是Python 类,需要进行实例化才能使用。而torch.nn.functional 中的函数是直接调用的,无需

生活杂记1

生命中,总有一些事需要你一生去治愈,我把这些杂记写出来,写完了就不再想了,太内耗了…hahaha~ 因为嘴馋,小时候经常去老姑家,她家有各类零食及平时很少吃的“山珍海味”。去的次数多了,就和她家附近的邻居小孩也混的熟络了。再后来上了高中去的就少了,当年七中统招线521自费线491。我刚好压自费线,举全家之力花了15000读了七中,也没争气,后面高考也一塌糊涂。高二那会,一次去老姑家做客,经

torchvision.transforms.ToPILImage()使用

grid_img = torchvision.transforms.ToPILImage()(grid_img) torchvision.transforms.ToPILImage() 是一个类,后面的空括号 () 表示实例化这个类。 详细解释: 1. torchvision.transforms.ToPILImage(): 这是 torchvision.transforms 中的一个类

【杂记】裂脑人实验和语言模型幻觉

【杂记】裂脑人实验和语言模型幻觉 模型的自主意识在哪里,人的自我认知在哪里?自然而然的,“裂脑人” 这个词突然出现在我脑海里。然后随意翻了翻相关的文章,觉得这个问题和目前大模型面临的幻觉问题也高度相关,遂随笔记录。 裂脑人 什么是裂脑人?人的大脑左右半脑本来是一个整体,因为先天或者后天的原因让左右半脑分开不产生连接,就是“裂脑”。过去这个方法被作为控制恶性癫痫的治疗手段。 一些铺垫知识

torch.backends.cudnn.benchmark和torch.use_deterministic_algorithms总结学习记录

经常使用PyTorch框架的应该对于torch.backends.cudnn.benchmark和torch.use_deterministic_algorithms这两个语句并不陌生,在以往开发项目的时候可能专门化花时间去了解过,也可能只是浅尝辄止简单有关注过,正好今天再次遇到了就想着总结梳理一下。 torch.backends.cudnn.benchmark 是 PyTorch 中的一个设置

torchvision数据集使用

文章目录 一、下载torchvision中的数据集文件二、断点知识点三、数据集形式建立四、展示数据集中的图片 一、下载torchvision中的数据集文件 这段代码是使用PyTorch的torchvision库来加载CIFAR-10数据集。 import torchvisiontrain_set = torchvision.datasets.CIFAR10(root="./

Transforms的常见用法

文章目录 一、封装函数与普通函数的用法区别二、Image.open()打开图片的格式三、ToTensor打开图片格式四、ToTensor使用五、Normalize归一化使用六、Resize的使用七、Compose - Resize 使用八、RandomCrop() 随机裁剪用法 一、封装函数与普通函数的用法区别 class Person:def __call__(self, n

【稀疏矩阵】使用torch.sparse模块

文章目录 稀疏矩阵的格式coocsrcsc Construction of Sparse COO tensorsConstruction of CSR tensorsLinear Algebra operations(稀疏与稠密之间混合运算)Tensor methods and sparse(与稀疏有关的tensor成员函数)coo张量可用的tensor成员函数(经实测,csr也有一些可以用