pytorch中的transforms.ToTensor和transforms.Normalize理解

简介: pytorch中的transforms.ToTensor和transforms.Normalize理解

pytorch中的transforms.ToTensor和transforms.Normalize理解🌴

transforms.ToTensor🌵

最近看pytorch时,遇到了对图像数据的归一化,如下图所示:1a897537d91ae638717214c5c592b59c.png

该怎么理解这串代码呢?我们一句一句的来看,先看transforms.ToTensor(),我们可以先转到官方给的定义,如下图所示:f3b92dc81868306ba1095add6dcee906.png

大概的意思就是说,transforms.ToTensor()可以将PIL和numpy格式的数据从[0,255]范围转换到[0,1] ,具体做法其实就是将原始数据除以255。另外原始数据的shape是(H x W x C),通过transforms.ToTensor()后shape会变为(C x H x W)。这样说我觉得大家应该也是能理解的,这部分并不难,但想着还是用一些例子来加深大家的映像🌽🌽🌽

  • 先导入一些包
import cv2
import numpy as np
import torch
from torchvision import transforms
  • 定义一个数组模型图片,注意数组数据类型需要时np.uint8【官方图示中给出】
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的shape,注意现在为(W H C)。

image.png


  • 使用transforms.ToTensor()将data进行转换
data = transforms.ToTensor()(data)

这时候我们来看看data中的数据及shape。

6669d9bd03b14903a23d884717bd17b4.png

很明显,数据现在都映射到了[0, 1]之间,并且data的shape发生了变换。

**注意:不知道大家是如何理解三维数组的,这里提供我的一个方法。**🥝🥝🥝


🌼原始的data的shape为(5,5,3),则其表示有5个(5 , 3)的二维数组,即我们把最外层的[]去掉就得到了5个五行三列的数据。


🌼同样的,变换后data的shape为(3,5,5),则其表示有3个(5 , 5)的二维数组,即我们把最外层的[]去掉就得到了3个五行五列的数据。


transforms.Normalize🌵

  相信通过前面的叙述大家应该对transforms.ToTensor有了一定的了解,下面将来说说这个transforms.Normalize🍹🍹🍹同样的,我们先给出官方的定义,如下图所示:308dd2831aa3c5376b60b927a958026c.png

可以看到这个函数的输出output[channel] = (input[channel] - mean[channel]) / std[channel]。这里[channel]的意思是指对特征图的每个通道都进行这样的操作。【mean为均值,std为标准差】接下来我们看第一张图片中的代码,即c9ac9390e825a69f6af3763baac8852e.png

这里的第一个参数(0.5,0.5,0.5)表示每个通道的均值都是0.5,第二个参数(0.5,0.5,0.5)表示每个通道的方差都为0.5。【因为图像一般是三个通道,所以这里的向量都是1x3的🍵🍵🍵】有了这两个参数后,当我们传入一个图像时,就会按照上面的公式对图像进行变换。【注意:这里说图像其实也不够准确,因为这个函数传入的格式不能为PIL Image,我们应该先将其转换为Tensor格式】

说了这么多,那么这个函数到底有什么用呢?我们通过前面的ToTensor已经将数据归一化到了0-1之间,现在又接上了一个Normalize函数有什么用呢?其实Normalize函数做的是将数据变换到了[-1,1]之间。之前的数据为0-1,当取0时,output =(0 - 0.5)/ 0.5 = -1;当取1时,output =(1 - 0.5)/ 0.5 = 1。这样就把数据统一到了[-1,1]之间了🌱🌱🌱那么问题又来了,数据统一到[-1,1]有什么好处呢?数据如果分布在(0,1)之间,可能实际的bias,就是神经网络的输入b会比较大,而模型初始化时b=0的,这样会导致神经网络收敛比较慢,经过Normalize后,可以加快模型的收敛速度。【这句话是再网络上找到最多的解释,自己也不确定其正确性】

读到这里大家是不是以为就完了呢?这里还想和大家唠上一唠🍓🍓🍓上面的两个参数(0.5,0.5,0.5)是怎么得来的呢?这是根据数据集中的数据计算出的均值和标准差,所以往往不同的数据集这两个值是不同的🍏🍏🍏这里再举一个例子帮助大家理解其计算过程。同样采用上文例子中提到的数据。

  • 上文已经得到了经ToTensor转换后的数据,现需要求出该数据每个通道的mean和std。【这一部分建议大家自己运行看看每一步的结果🌵🌵🌵】
# 需要对数据进行扩维,增加batch维度
data = torch.unsqueeze(data,0)    #在pytorch中一般都是(batch,C,H,W)
nb_samples = 0.
#创建3维的空列表
channel_mean = torch.zeros(3)
channel_std = torch.zeros(3)
N, C, H, W = data.shape[:4]
data = data.view(N, C, -1)  #将数据的H,W合并
#展平后,w,h属于第2维度,对他们求平均,sum(0)为将同一纬度的数据累加
channel_mean += data.mean(2).sum(0)  
#展平后,w,h属于第2维度,对他们求标准差,sum(0)为将同一纬度的数据累加
channel_std += data.std(2).sum(0)
#获取所有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])
  • 将上述得到的mean和std带入公式,计算输出。
for i in range(3):
    data[i] = (data[i] - channel_mean[i]) / channel_std[i]
print(data)

输出结果:

f94e003694ee4c5af69a26cdad55144e.png

从结果可以看出,我们计算的mean和std并不是0.5,且最后的结果也没有在[-1,1]之间。


最后我们再来看一个有意思的例子,我们得到了最终的结果,要是我们想要变回去怎么办,其实很简单啦,就是一个逆运算,即input = std*output + mean,然后再乘上255就可以得到原始的结果了。很多人获取吐槽了,这也叫有趣!!??哈哈哈这里我想说的是另外的一个事,如果我们对一张图像进行了归一化,这时候你用归一化后的数据显示这张图像的时候,会发现同样会是原图。感兴趣的大家可以去试试🥗🥗🥗🥗这里给出一个参考链接:https://blog.csdn.net/xjp_xujiping/article/details/102981117


参考链接1:https://zhuanlan.zhihu.com/p/414242338

参考链接2:https://blog.csdn.net/peacefairy/article/details/108020179






相关文章
|
监控 算法
探秘Guava的RateLimiter:单机流量控制的黄金法宝
探秘Guava的RateLimiter:单机流量控制的黄金法宝
852 0
雷达波形之一——LFM线性调频波形
雷达波形之一——LFM线性调频波形
2145 1
|
机器学习/深度学习 并行计算 PyTorch
TensorRT部署系列 | 如何将模型从 PyTorch 转换为 TensorRT 并加速推理?
TensorRT部署系列 | 如何将模型从 PyTorch 转换为 TensorRT 并加速推理?
2480 0
|
Linux 计算机视觉 C++
【解决方案】Building wheel for opencv-python:安装卡顿的原因与解决方案
当你安装OpenCV时,命令行停在Building wheel for opencv-python (PEP 517) ... -似乎卡住了。这并非程序假死,而是其编译耗时巨大。本文将揭示原因,并提供优化安装体验的实用方法。
1535 88
|
机器学习/深度学习 自然语言处理 搜索推荐
预训练的词嵌入(Word Embedding)
预训练的词嵌入(Word Embedding)
891 2
|
11月前
|
机器学习/深度学习 监控 PyTorch
126_自定义损失:多目标训练 - 设计加权损失的独特平衡策略
在2025年的大型语言模型(LLM)训练领域,多目标学习已成为提升模型综合性能的关键技术之一。传统的单一损失函数训练方法逐渐显现出局限性,尤其在处理复杂的语言理解、生成和推理任务时。多目标训练通过同时优化多个互补的学习目标,能够显著提升模型的泛化能力、知识保留和任务适应性。
598 3
|
人工智能
逼真到离谱!1000个人类克隆进西部世界,AI相似度85%细节太炸裂
《生成式代理:1000人的模拟》由斯坦福大学等机构完成,利用AI技术成功模拟了1000个真实个体的态度和行为,准确率达85%。研究结合大型语言模型与定性访谈数据,旨在为社会科学研究提供新工具,减少偏见,提升公平性。论文还探讨了隐私和伦理问题,并强调了代理的局限性。
423 13
|
算法 数据可视化 定位技术
基于PCL库的通过ICP匹配多幅点云方法
基于PCL库的通过ICP匹配多幅点云方法
基于PCL库的通过ICP匹配多幅点云方法
|
机器学习/深度学习 自然语言处理 语音技术
《双向LSTM:序列建模的强大引擎》
双向长短时记忆网络(BiLSTM)是LSTM的扩展,通过同时处理序列的正向和反向信息,显著提升对序列数据的建模能力。它在每个时间步运行两个LSTM,分别按正向和反向顺序处理数据,融合前后向隐藏状态,捕捉长距离依赖关系和上下文信息,增强模型鲁棒性。BiLSTM广泛应用于文本分类、情感分析、命名实体识别、机器翻译、语音识别及时间序列预测等任务,表现出色。
1116 14
|
机器学习/深度学习 Serverless 定位技术
深入理解多重共线性:基本原理、影响、检验与修正策略
本文将深入探讨多重共线性的本质,阐述其重要性,并提供有效处理多重共线性的方法,同时避免数据科学家常犯的陷阱。
1669 3

热门文章

最新文章