【pytorch】土堆pytorch教程学习(四)Transforms 的使用
transforms 在计算机视觉工具包 torchvision下,用来对图像进行预处理:
- 数据中心化
- 数据标准化
- 缩放
- 裁剪
- 旋转
- 翻转
- 填充
- 噪声添加
- 灰度变换
- 线性变换
- 仿射变换
- 亮度、饱和度以及对比度变换等。
transforms 本质就是一个python文件,相当于一个工具箱,里面包含诸如 Resize
、ToTensor
、Normalize
等类,这些类就是我们需要用到的图像预处理工具。
transforms 的使用无非是将图像通过工具转换成我们需要的结果。
我们需要关注两个问题:
- 该如何使用 transforms 里的工具?
- 为什么需要 Tensor 数据类型?
工具的使用方法
我们先来看下 ToTensor
和 Resize
这两个工具的源码。
# ToTensor 源码
class ToTensor:
"""Convert a PIL Image or ndarray to tensor and scale the values accordingly.
"""
def __init__(self) -> None:
_log_api_usage_once(self)
def __call__(self, pic):
"""
Args:
pic (PIL Image or numpy.ndarray): Image to be converted to tensor.
Returns:
Tensor: Converted image.
"""
return F.to_tensor(pic)
# Resize 源码
class Resize(torch.nn.Module):
"""Resize the input image to the given size.
"""
def __init__(self, size, interpolation=InterpolationMode.BILINEAR, max_size=None, antialias="warn"):
super().__init__()
_log_api_usage_once(self)
if not isinstance(size, (int, Sequence)):
raise TypeError(f"Size should be int or sequence. Got {type(size)}")
if isinstance(size, Sequence) and len(size) not in (1, 2):
raise ValueError("If size is a sequence, it should have 1 or 2 values")
self.size = size
self.max_size = max_size
if isinstance(interpolation, int):
interpolation = _interpolation_modes_from_int(interpolation)
self.interpolation = interpolation
self.antialias = antialias
def forward(self, img):
"""
Args:
img (PIL Image or Tensor): Image to be scaled.
Returns:
PIL Image or Tensor: Rescaled image.
"""
return F.resize(img, self.size, self.interpolation, self.max_size, self.antialias)
一目了然,这两个工具都没有一堆乱七八糟的方法迷惑我们,其核心功能代码在 __call__
和 forward
里,这是想让我们通过可调用对象方式来使用工具。
使用 transforms 工具大致为以下两个步骤:
- 实例化工具
tensor_trans = transforms.ToTensor()
- 传入合适的参数调用实例化对象
img_path = 'dataset/train/ants/0013035.jpg'
img = Image.open(img_path)
# 输入什么类型的参数可以进到源码里看
tensor_img = tensor_trans(img)
补充:
我们需要关注三种图像类型还有如何得到三种图像类型,分别是 PIL.Image
、numpy.ndarray
和 Tensor
。
Image.open(img_path)
得到PIL.Image
类型cv2.imread(img_path)
得到numpy.ndarray
类型transforms.ToTensor()(pic)
得到Tensor
类型
在 transforms 中存在工具灵活地转换图像类型,如ToTensor
, PILToTensor
,ToPILImage
。
Tensor 数据类型
from torchvision import transforms
from PIL import Image
img_path = 'dataset/train/ants/0013035.jpg'
img = Image.open(img_path)
tensor_trans = transforms.ToTensor()
tensor_img = tensor_trans(img)
print(tensor_img)
输出 Tensor
类型的数据,乍一看怎么和 numpy.ndarray
差不多。其实不然,进入断点调式里可以看到其还包装了神经网络所需要的理论基础参数,诸如grad
、grad_fn
、is_cpu
等。这就是我们需要 Tensor 数据类型的原因,一切都是为了神经网络而服务。
常用的工具
仅仅列出几个常用的工具的一些简单用法,以进一步体会tansforms工具的用法,其他详细信息还需关注官方文档和源码。
ToTensor
将
PIL.Image
或narray
类型的图像转换为tensor
类型并相应地缩放值。
trans_totensor = transforms.ToTensor()
img_tensor = trans_totensor(img)
Normalize
用均值和标准差标准化张量图像。
torchvision.transforms.Normalize(mean, std, inplace=False)
逐channel地对图像进行标准化(均值变为0,标准差变为1),可以加快模型的收敛。
n个通道,给出 平均值: (mean[1],...,mean[n]) 和 标准差: (std[1],..,std[n])
计算公式:output[channel] = (input[channel] - mean[channel]) / std[channel]
- mean: 各通道的均值
- std: 各通道的标准差
- inplace: 是否原地操作
trans_normalize = transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
img_normalize = trans_normalize(img_tensor)
Resize
改变图像的大小
trans_resize = transforms.Resize((512,512))
img_resize = trans_resize(img)
Compose
将多个变换组合在一起。
# transforms.Compose(transforms)
trans_compose = transforms.Compose([
transforms.Resize(512),
transforms.ToTensor()
transforms.Nomalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
])
img_resize = trans_compose(img)
简单理解 ToTense 和 Normalize
数值归一化处理是数据挖掘中的一项基本工作,不同的评价指标具有不同的量纲和量纲单位,如果根据原始数据进行分析的话会受到量纲的影响,为了消除指标之间的量纲影响,需要对原始数据进行标准化。
归一化也就是量纲统一化。目的就是为了把不同来源的数据统一到同一数量级(或者是一个参考坐标系)下,这样使得比较起来有意义。
归一化能提高梯度下降法求解最优解的速度。
归一化方法:
- 线性归一化,也称min-max标准化、离差标准化;是对原始数据的线性变换,使得结果值映射到 [0, 1] 之间。转换函数如下:
x' = (x - min(x)) / (max(x) - min(x))
- 标准差归一化,,也叫Z-score标准化,这种方法给予原始数据的均值(mean,μ)和标准差(standard deviation,σ)进行数据的标准化。处理后的数据均值为0,标准差为1。转换函数如下:
x* = (x - μ) / σ
- 非线性归一化,这种方法一般使用在数据分析比较大的场景,有些数值很大,有些很小,通过一些数学函数,将原始值进行映射。一般使用的函数包括log、指数、正切等,需要根据数据分布的具体情况来决定非线性函数的曲线。
ToTensor
干了两件事:
- 把
PIL
图像或numpy.narray
转换成Tensor
, 形状也从HWC
->CHW
。 - 如果
PIL
图像是属于(L, LA, P, I, F, RGB, YCbCr, RGBA, CMYK, 1)
中的一种模式,或者numpy.ndarray
的dtype
是np.uint8
,还会将数值从 [0, 255] 归一化到 [0, 1]。
Normalize
是对数据按通道进行标准化,即均值为0,标准差为1。这能加快模型的收敛速度。
计算公式:
output[channel] = (input[channel] - mean[channel]) / std[channel]
实际应用中是需要我们自己计算出每个通道的均值和标准差,然后再传入 Normalize
。
'''
以 MNIST 数据集为例计算其均值和标准差
先查看 mnist 的最大值和最小值
mnist.data.float().min() # 0
mnist.data.float().max() # 255
可以看到数据范围是 [0, 255],在转成 Tensor 类型时会归一化到 [0, 1],故我们需要计算的是[0, 1]范围下的数据集的均值和标准差
'''
mean = (mnist.data.floatt()/255).mean()
std = (mnist.data.floatt()/255).std()
可能会有人疑问确定了数据集不也就确定了均值和标准差,为什么还要我们自己计算再传入呢?
这是因为数据集一般都是很庞大的,如果交给 Normalize
计算就会影响性能了。
本文来自博客园,作者:hzyuan,转载请注明原文链接:https://www.cnblogs.com/hzyuan/p/17367979.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)