学习pytorch中归一化transforms.Normalize

这篇具有很好参考价值的文章主要介绍了学习pytorch中归一化transforms.Normalize。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

torchvison:计算机视觉工具包

包含

  1. torchvison.transforms(常用的图像预处理方法);
  2. torchvision.datasets(常用数据集的dataset实现,MNIST,CIFAR-10,ImageNet等);
  3. torchvison.model(常用的模型预训练,AlexNet,VGG,ResNet,GoogleNet等)。

torchvision.transforms

常用的数据预处理方法,提升泛化能力。包括:数据中心化、数据标准化、缩放、裁剪、旋转、填充、噪声添加、灰度变换、线性变换、放射变换、亮度、饱和度和对比度变换等


数据标准化——transforms.Normalize

功能:逐channel的对图像进行标准化(均值变为0,标准差变为1),可以加快模型的收敛

  • output=(input-mean)/std
  • mean:各通道的均值
  • std:各通道的标准差
  • inplace:是否原地操作

问题:究竟是什么意思?(0.5,0.5,0.5),(0.5,0.5,0.5)又是怎么来的呢?

transform.ToTensor(),
transform.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))

1、transform.ToTensor() 

原始的PILImage格式或者numpy.array格式的数据格式化为可被pytorch快速处理的张量类型

  • 是将输入的数据shape W,H,C---> C,W,H。   从opencv读到的图片是通道数在第三个维度,现在经过ToTensor操作cv2图片变成了torch image类型,也就是通道在第一个维度。

  • 将所有数除以255,将数据归一化到[0,1]

  • 示例:

import torch
import numpy as np
from torchvision import transforms
import cv2
# 自定义图片数组,数据类型一定要转为‘uint8’,不然transforms.ToTensor()不会归一化
data = np.array([
                [[1,1,1],[1,1,1],[1,1,1],[1,1,1],[1,1,1]],
                [[2,2,2],[2,2,2],[2,2,2],[2,2,2],[2,2,2]],
                [[3,3,3],[3,3,3],[3,3,3],[3,3,3],[3,3,3]],
                [[4,4,4],[4,4,4],[4,4,4],[4,4,4],[4,4,4]],
                [[5,5,5],[5,5,5],[5,5,5],[5,5,5],[5,5,5]]
        ],dtype='uint8')
print(data)
print(data.shape)   #(5,5,3)
data = transforms.ToTensor()(data)
print(data)
print(data.shape)	#(3,5,5)

输出:
tensor([[[0.0039, 0.0039, 0.0039, 0.0039, 0.0039],
         [0.0078, 0.0078, 0.0078, 0.0078, 0.0078],
         [0.0118, 0.0118, 0.0118, 0.0118, 0.0118],
         [0.0157, 0.0157, 0.0157, 0.0157, 0.0157],
         [0.0196, 0.0196, 0.0196, 0.0196, 0.0196]],

        [[0.0039, 0.0039, 0.0039, 0.0039, 0.0039],
         [0.0078, 0.0078, 0.0078, 0.0078, 0.0078],
         [0.0118, 0.0118, 0.0118, 0.0118, 0.0118],
         [0.0157, 0.0157, 0.0157, 0.0157, 0.0157],
         [0.0196, 0.0196, 0.0196, 0.0196, 0.0196]],

        [[0.0039, 0.0039, 0.0039, 0.0039, 0.0039],
         [0.0078, 0.0078, 0.0078, 0.0078, 0.0078],
         [0.0118, 0.0118, 0.0118, 0.0118, 0.0118],
         [0.0157, 0.0157, 0.0157, 0.0157, 0.0157],
         [0.0196, 0.0196, 0.0196, 0.0196, 0.0196]]])

2、 transforms.Normalize()

x = (x - mean) / std

即同一纬度的数据减去这一维度的平均值,再除以标准差,将归一化后的数据变换到[-1,1]之间。可真是这样吗??

  • 求解mean和std

我们需要求得一批数据的mean和std,代码如下:

import torch
import numpy as np
from torchvision import transforms

# 这里以上述创建的单数据为例子
data = np.array([
                [[1,1,1],[1,1,1],[1,1,1],[1,1,1],[1,1,1]],
                [[2,2,2],[2,2,2],[2,2,2],[2,2,2],[2,2,2]],
                [[3,3,3],[3,3,3],[3,3,3],[3,3,3],[3,3,3]],
                [[4,4,4],[4,4,4],[4,4,4],[4,4,4],[4,4,4]],
                [[5,5,5],[5,5,5],[5,5,5],[5,5,5],[5,5,5]]
        ],dtype='uint8')

#将数据转为C,W,H,并归一化到[0,1]
data = transforms.ToTensor()(data)
# 需要对数据进行扩维,增加batch维度
data = torch.unsqueeze(data,0)

nb_samples = 0.
#创建3维的空列表
channel_mean = torch.zeros(3)   #tensor([0., 0., 0.])
channel_std = torch.zeros(3)    #tensor([0., 0., 0.])

print(data.shape)  # torch.Size([1,3,5,5])
# tensor([[[[0.0039, 0.0039, 0.0039, 0.0039, 0.0039],
          [0.0078, 0.0078, 0.0078, 0.0078, 0.0078],
          [0.0118, 0.0118, 0.0118, 0.0118, 0.0118],
          [0.0157, 0.0157, 0.0157, 0.0157, 0.0157],
          [0.0196, 0.0196, 0.0196, 0.0196, 0.0196]],
         [[0.0039, 0.0039, 0.0039, 0.0039, 0.0039],
          [0.0078, 0.0078, 0.0078, 0.0078, 0.0078],
          [0.0118, 0.0118, 0.0118, 0.0118, 0.0118],
          [0.0157, 0.0157, 0.0157, 0.0157, 0.0157],
          [0.0196, 0.0196, 0.0196, 0.0196, 0.0196]],
         [[0.0039, 0.0039, 0.0039, 0.0039, 0.0039],
          [0.0078, 0.0078, 0.0078, 0.0078, 0.0078],
          [0.0118, 0.0118, 0.0118, 0.0118, 0.0118],
          [0.0157, 0.0157, 0.0157, 0.0157, 0.0157],
          [0.0196, 0.0196, 0.0196, 0.0196, 0.0196]]]])


N, C, H, W = data.shape[:4]   #N=1  C=3  H=5   W=5
data = data.view(N, C, -1)    #将w,h维度的数据展平,为batch,channel,data,然后对三个维度上的数分别求和和标准差
 
print(data.shape)   #torch.Size([1, 3, 25])
#tensor([[[0.0039, 0.0039, 0.0039, 0.0039, 0.0039, 0.0078, 0.0078, 0.0078,
          0.0078, 0.0078, 0.0118, 0.0118, 0.0118, 0.0118, 0.0118, 0.0157,
          0.0157, 0.0157, 0.0157, 0.0157, 0.0196, 0.0196, 0.0196, 0.0196,
          0.0196],
         [0.0039, 0.0039, 0.0039, 0.0039, 0.0039, 0.0078, 0.0078, 0.0078,
          0.0078, 0.0078, 0.0118, 0.0118, 0.0118, 0.0118, 0.0118, 0.0157,
          0.0157, 0.0157, 0.0157, 0.0157, 0.0196, 0.0196, 0.0196, 0.0196,
          0.0196],
         [0.0039, 0.0039, 0.0039, 0.0039, 0.0039, 0.0078, 0.0078, 0.0078,
          0.0078, 0.0078, 0.0118, 0.0118, 0.0118, 0.0118, 0.0118, 0.0157,
          0.0157, 0.0157, 0.0157, 0.0157, 0.0196, 0.0196, 0.0196, 0.0196,
          0.0196]]])


#展平后,w,h属于第二维度,对他们求平均,sum(0)为将同一纬度的数据累加
channel_mean += data.mean(2).sum(0)  #tensor([0.0118, 0.0118, 0.0118])

#展平后,w,h属于第二维度,对他们求标准差,sum(0)为将同一纬度的数据累加
channel_std += data.std(2).sum(0)   #tensor([0.0057, 0.0057, 0.0057])

#获取所有batch的数据,这里为1
nb_samples += N

#获取同一batch的均值和标准差
channel_mean /= nb_samples
channel_std /= nb_samples

print(channel_mean, channel_std)   #tensor([0.0118, 0.0118, 0.0118]) tensor([0.0057, 0.0057, 0.0057])

以此便可求得均值和标准差。我们再带入公式:

x = (x - mean) / std
  • 自己实现:
data = np.array([
                [[1,1,1],[1,1,1],[1,1,1],[1,1,1],[1,1,1]],
                [[2,2,2],[2,2,2],[2,2,2],[2,2,2],[2,2,2]],
                [[3,3,3],[3,3,3],[3,3,3],[3,3,3],[3,3,3]],
                [[4,4,4],[4,4,4],[4,4,4],[4,4,4],[4,4,4]],
                [[5,5,5],[5,5,5],[5,5,5],[5,5,5],[5,5,5]]
        ],dtype='uint8')
data = transforms.ToTensor()(data)
print(data)
#tensor([[[0.0039, 0.0039, 0.0039, 0.0039, 0.0039],
         [0.0078, 0.0078, 0.0078, 0.0078, 0.0078],
         [0.0118, 0.0118, 0.0118, 0.0118, 0.0118],
         [0.0157, 0.0157, 0.0157, 0.0157, 0.0157],
         [0.0196, 0.0196, 0.0196, 0.0196, 0.0196]],
        [[0.0039, 0.0039, 0.0039, 0.0039, 0.0039],
         [0.0078, 0.0078, 0.0078, 0.0078, 0.0078],
         [0.0118, 0.0118, 0.0118, 0.0118, 0.0118],
         [0.0157, 0.0157, 0.0157, 0.0157, 0.0157],
         [0.0196, 0.0196, 0.0196, 0.0196, 0.0196]],
        [[0.0039, 0.0039, 0.0039, 0.0039, 0.0039],
         [0.0078, 0.0078, 0.0078, 0.0078, 0.0078],
         [0.0118, 0.0118, 0.0118, 0.0118, 0.0118],
         [0.0157, 0.0157, 0.0157, 0.0157, 0.0157],
         [0.0196, 0.0196, 0.0196, 0.0196, 0.0196]]])

for i in range(3):
    data[i,:,:] = (data[i,:,:] - channel_mean[i]) / channel_std[i]
print(data)

输出:
tensor([[[-1.3856, -1.3856, -1.3856, -1.3856, -1.3856],
         [-0.6928, -0.6928, -0.6928, -0.6928, -0.6928],
         [ 0.0000,  0.0000,  0.0000,  0.0000,  0.0000],
         [ 0.6928,  0.6928,  0.6928,  0.6928,  0.6928],
         [ 1.3856,  1.3856,  1.3856,  1.3856,  1.3856]],

        [[-1.3856, -1.3856, -1.3856, -1.3856, -1.3856],
         [-0.6928, -0.6928, -0.6928, -0.6928, -0.6928],
         [ 0.0000,  0.0000,  0.0000,  0.0000,  0.0000],
         [ 0.6928,  0.6928,  0.6928,  0.6928,  0.6928],
         [ 1.3856,  1.3856,  1.3856,  1.3856,  1.3856]],

        [[-1.3856, -1.3856, -1.3856, -1.3856, -1.3856],
         [-0.6928, -0.6928, -0.6928, -0.6928, -0.6928],
         [ 0.0000,  0.0000,  0.0000,  0.0000,  0.0000],
         [ 0.6928,  0.6928,  0.6928,  0.6928,  0.6928],
         [ 1.3856,  1.3856,  1.3856,  1.3856,  1.3856]]])
  • 官方实现
data = np.array([
                [[1,1,1],[1,1,1],[1,1,1],[1,1,1],[1,1,1]],
                [[2,2,2],[2,2,2],[2,2,2],[2,2,2],[2,2,2]],
                [[3,3,3],[3,3,3],[3,3,3],[3,3,3],[3,3,3]],
                [[4,4,4],[4,4,4],[4,4,4],[4,4,4],[4,4,4]],
                [[5,5,5],[5,5,5],[5,5,5],[5,5,5],[5,5,5]]
        ],dtype='uint8')
data = transforms.ToTensor()(data)
data = transforms.Normalize(channel_mean, channel_std)(data)
print(data)

输出:
tensor([[[-1.3856, -1.3856, -1.3856, -1.3856, -1.3856],
         [-0.6928, -0.6928, -0.6928, -0.6928, -0.6928],
         [ 0.0000,  0.0000,  0.0000,  0.0000,  0.0000],
         [ 0.6928,  0.6928,  0.6928,  0.6928,  0.6928],
         [ 1.3856,  1.3856,  1.3856,  1.3856,  1.3856]],

        [[-1.3856, -1.3856, -1.3856, -1.3856, -1.3856],
         [-0.6928, -0.6928, -0.6928, -0.6928, -0.6928],
         [ 0.0000,  0.0000,  0.0000,  0.0000,  0.0000],
         [ 0.6928,  0.6928,  0.6928,  0.6928,  0.6928],
         [ 1.3856,  1.3856,  1.3856,  1.3856,  1.3856]],

        [[-1.3856, -1.3856, -1.3856, -1.3856, -1.3856],
         [-0.6928, -0.6928, -0.6928, -0.6928, -0.6928],
         [ 0.0000,  0.0000,  0.0000,  0.0000,  0.0000],
         [ 0.6928,  0.6928,  0.6928,  0.6928,  0.6928],
         [ 1.3856,  1.3856,  1.3856,  1.3856,  1.3856]]])

我们观察数据发现,通过求解的均值和标准差,求得的标准化的值,并非在[-1,1]

结论:

经过这样处理后的数据符合标准正态分布,即均值为0,标准差为1。使模型更容易收敛。并非是归于[-1,1]!!


Normalize之前,数据分布是在[0,1]

Normalize之后:

  • ①如果mean = std=(0.5,0.5,0.5),那么Normalize之后,数据分布是【-1,1】;因为最小值=(0-mean)/std=(0-0.5)/0.5=-1。同理最大值的等于1。
  • ②如果mean为数据的计算的mean,std也是数据计算的std。那么Normalize之后根据公式(x-mean)/std,结合均值和方差的性质,可以算出新数据的均值会变成0,方差会变成1。

总结:
如果是Normalize((0.5,0.5,0.5),(0.5,0.5,0.5)),确实是归一化到【-1,1】
如果是Normalize(channel_mean, channel_std),才是均值为0,标准差为1。


transforms 数据增强

数据增强又称为数据增广,数据扩增,它是对训练集进行变换,使训练集更丰富,从而让模型更具泛化能力。

transforms——裁剪

  1. transforms.CenterCrop  

  • 功能:从图像中心裁剪图片
  • size:所需裁剪图片尺寸

    2、transforms.RandomCrop

  • 功能:从图片中随机裁剪出尺寸为size的图片
  • size:所需裁剪图片尺寸
  • padding:设置填充大小。当为a时,上下左右均填充a个像素,当为(a,b)时,上下填充b个像素,左右填充a个像素。当为(a,b,c,d)时,左上右下分别填充abcd
  • pad_if_need:若图像小于设定size,则填充
  • padding_mode:填充模式:(1)constant像素值由fill设定(默认模式);(2)edge像素值由图像边缘像素决定(3)reflect镜像填充,最后一个像素不镜像,eg,[1,2,3,4]->[3,2,1,2,3,4,3,2];(4)symmetric镜像填充,最后一个像素镜像,eg,[1,2,3,4]->[2,1,1,2,3,4,4,3]
  • fill:constant时,设置填充的像素值

transforms——翻转和旋转

  1. RandomHorizontalFlip 水平翻转
  2. RandomVerticalFlip  垂直翻转
  3. RandomRotation  随机旋转图像

自定义tansfroms方法

class Compose(object):
    def __call__(self,img):
        for t in self.transforms:
               img = t(img)
        return img

transforms方法是在Compose类的__call__方法中被调用的,对一组transforms方法进行for循环,每次循序的挑选并执行transforms方法。

  • 自定义transforms要素:

  1. 仅接收一个参数,返回一个参数
  2. 注意上下游的输出和输入,数据类型必须匹配

通过类实现多参数传入,下图为自定义transforms的基本参数,一个init,一个call文章来源地址https://www.toymoban.com/news/detail-444914.html

class YourTransforms(object):
    def __init__(self,...):
        ...
    def __call__(self,img):
        ...
        return img

椒盐噪声

  • 椒盐噪声又称为又称为脉冲噪声,是一种随机出现的白点或者黑点,白点称为盐噪声,黑点称为椒噪声。
  • 信噪比(SNR):衡量噪声的比例,图像中为图像像素的占比

class AddPepperNoise(object):
	def __init__(self, snr, p):
		self.snr = snr
		self.p = p
	
	def __call__(self, img):
		'''
		添加椒盐噪声具体实现过程
		'''
		return img

到了这里,关于学习pytorch中归一化transforms.Normalize的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 用pytorch给深度学习加速:正交与谱归一化技术

    目录 torch.nn参数优化 parametrizations.orthogonal 用途 用法 使用技巧 参数 注意事项 示例代码 parametrizations.spectral_norm 用途 用法 使用技巧 参数 注意事项 示例代码 总结 这个 torch.nn.utils.parametrizations.orthogonal 模块是PyTorch库中的一个功能,用于对神经网络中的矩阵或一批矩阵应用正交

    2024年01月17日
    浏览(30)
  • OpenCV的函数normalize()的两个作用:调整矩阵的值范围(归一化处理)、规范化矩阵的范数为某个值

    OpenCV的函数normalize()的两个作用:调整矩阵的值范围(归一化处理)、规范化矩阵的范数为某个值 函数normalize()有两个原型: 原型一: 原型二: 原型一的适用对象是密集矩阵,通常我们的矩阵都是密集矩阵。 原型二的适用对象是稀疏矩阵,在这篇博文中暂不作介绍。 在介绍各参

    2024年02月06日
    浏览(31)
  • 【Pytorch基础知识】数据的归一化和反归一化

    一张正常的图,或者说是人眼习惯的图是这样的: 但是,为了 神经网络更快收敛 ,我们在深度学习网络过程中 通常需要将读取的图片转为tensor并归一化 (此处的归一化指 transforms .Normalize()操作)输入到网络中进行系列操作。 如果将转成的tensor再直接转为图片,就会变成下

    2023年04月09日
    浏览(72)
  • Pytorch学习笔记(8):正则化(L1、L2、Dropout)与归一化(BN、LN、IN、GN)

     一、正则化之weight_decay(L2正则) 1.1 正则化及相关概念 1.2 正则化策略(L1、L2) (1)L1正则化 (2)L2正则化 1.3 L2正则项——weight_decay 二、正则化之Dropout 2.1 Dropout概念 2.2 nn.Dropout  三、归一化之Batch Normalization(BN层) 3.1 Batch Normalization介绍 3.2 Pytorch的Batch Normalization 1d

    2024年02月04日
    浏览(31)
  • MinMaxScaler 中scaler.inverse_transform不能反归一化正确的数据

    参考代码[时间序列预测]基于BP、RNN、LSTM、CNN-LSTM算法多特征(多影响因素)用电负荷预测[保姆级手把手教学] 他的源代码部分: 我的代码仿写部分: 其中的 np.concatenate 就是拼接,按列拼接。 我拿个demo来解释一下: 也就是从demo理解了我把y列加在了x上,并且是在最后列。

    2023年04月22日
    浏览(28)
  • 深度学习基本理论下篇:(梯度下降/卷积/池化/归一化/AlexNet/归一化/Dropout/卷积核)、深度学习面试

    深度学习面试必备 1:(MLP/激活函数/softmax/损失函数/梯度/梯度下降/学习率/反向传播/深度学习面试 深度学习面试必备 2:(梯度下降/卷积/池化/归一化/AlexNet/归一化/Dropout/卷积核/深度学习面试 深度学习面试必备 3 :物体检测(Anchor base/NMS/softmax/损失函数/BCE/CE/zip) Momentum、

    2024年02月12日
    浏览(33)
  • 深度学习基础入门篇[七]:常用归一化算法、层次归一化算法、归一化和标准化区别于联系、应用案例场景分析。

    【深度学习入门到进阶】必看系列,含激活函数、优化策略、损失函数、模型调优、归一化算法、卷积模型、序列模型、预训练模型、对抗神经网络等 专栏详细介绍:【深度学习入门到进阶】必看系列,含激活函数、优化策略、损失函数、模型调优、归一化算法、卷积模型、

    2024年02月13日
    浏览(29)
  • Pytorch下transforms.ToTensor(),transforms.Normalize()详解,及代码实现和复原

    一、在数据处理时,我们要经常用到 transforms.ToTensor(),transforms.Normalize() 语句,将图像数据转换为tensor并标准化到[-1,1]之间。 其计算过程为: ①将image数据由(H,W,C)变为(C,H,W),并除以255进行归一化到[0,1]区间; ②将numpy.ndarray数据类型转换为Tensor ③根据image=(x-mean)/std进行

    2024年02月16日
    浏览(28)
  • 深度学习输入数据的归一化

    将2D点坐标映射到[-1, 1]范围的主要原因有: 消除分辨率影响 不同图像分辨率下的绝对像素坐标值会有很大差异(例如100px和1000px)。映射到[-1, 1]可以抹平这种分辨率影响,使坐标值处在统一的数值范围内。 适合网络输入 大多数基于深度学习的模型会假设输入数据处在[-1, 1]或[0,

    2024年02月09日
    浏览(27)
  • 【机器学习】数据预处理 - 归一化和标准化

    「作者主页」: 士别三日wyx 「作者简介」: CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」: 对网络安全感兴趣的小伙伴可以关注专栏《网络安全入门到精通》 处理数据之前,通常会使用一些转换函数将 「特征数据」 转换成更适合 「

    2024年02月15日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包