如果你曾经参与过 PyTorch 模型的微调,可能会遇到 PyTorch 的内置变换函数,这使得数据增强变得轻而易举。 即使你之前没有使用过这些功能,也不必担心。 在本文中,我们将深入研究 PyTorch 变换换函数的世界。 我们将探索你可以使用的各种转换以及它们如何帮助训练强大的模型。
本文是PyTorch微调终极指南的第三部分,前两部分点击这里查看:一、二。
在线工具推荐: Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器
转换函数是 PyTorch 库的一部分,可以轻松地对输入数据使用不同的数据增强技术。 这些功能允许你同时应用一项或多项更改。
可以在这里找到 PyTorch 官方文档。
请注意 - PyTorch 建议使用 torchvision.transforms.v2
变换而不是 torchvision.transforms
中的变换。
下面是一个读取图像并使用 PyTorch Transforms 更改图像大小的示例脚本:
from torchvision.transforms import v2
from PIL import Image
import matplotlib.pyplot as plt
# Load the image
image = Image.open('your_image.jpg') # Replace 'your_image.jpg' with the path to your image file
# Define a transformation
transform = v2.Compose([
v2.Resize((256, 256)), # Resize the image to 256x256 pixels
v2.ToTensor(), # Convert the image to a PyTorch tensor
])
# Apply the transformation to the image
transformed_image = transform(image)
在上面的示例中,我们可以看到对输入图像应用了两种变换。 首先,它被调整大小,其次,它被转换成张量。 这两种改变结合在一起,我们可以用其他类型的转换做同样的事情,依次应用它们。
我们可以将不同的变换函数分为四大类:
我们将详细研究每个类别。
顾名思义,几何变换是在不修改像素值的情况下改变图像几何形状的操作。 虽然像素值本身在这些变换过程中基本保持不变,但它们在图像中的位置发生了变化。
为什么需要这些几何变换?
几何变换能够以各种形式表示数据,提供对数据的不同视角并增强深度学习模型的稳健性。 在输入数据中加入几何变换可以增强模型对几何变化的适应能力。
以下是 PyTorch 中可用的各种几何变换:
顾名思义,resize有助于将图像大小调整为给定大小。 我们可以定义所需的大小,或者如果我们希望将随机调整大小应用于输入图像以获得更好的调整大小方差,则可以定义一个范围。
# To resize input image for specified size
img = v2.Resize((300, 300))(orig_img)
# To resize inpur randomly given two range; ps - here max_range > min_range
max_range, min_range = 400, 300
img = v2.RandomResize(max_range,min_range)(orig_img)
这有助于我们为输入图像应用不同的旋转(rotate)给定角度。 在通过将模型暴露于旋转图像的训练过程中,可以要求它保持方向不变。 这意味着模型应该识别对象或特征,无论其方向如何。 你可以应用不同的旋转变换。
# To apply rotation on input image with specified angle
angle = 140
img = v2.functional.rotate(orig_img, angle)
# To rotate image randomly given two range; ps - here max_range > min_range
max_range, min_range = 180, 0
img = v2.RandomRotation(degrees=(min_range, max_range))(orig_img)
您可以在设定的旋转角度或范围(最小和最大)上随机旋转图像。 随机旋转主要用于在训练模型时为数据添加更多多样性。
翻转(flip)与旋转非常相似,但它不是将图像旋转特定角度,而是水平或垂直旋转图像,即绕 x 轴或 y 轴旋转 180 度。
# to apply left-to-right flip
img = v2.functional.horizontal_flip(orig_img)
# to apply top-to-bottom flip
img = v2.functional.vertical_flip(orig_img)
# to apply these flips randomly on input image
# Here p is probabality, if p=1 then applies flip on all the input image during training
img = v2.RandomHorizontalFlip(p=1)(orig_img)
img = v2.RandomVerticalFlip(p=1)(orig_img)
当你随机翻转图像时,可以使用 p 来表示你希望它发生的频率。 如果 p 为 0.5(例如 50%),则意味着批次中的一半图像会被翻转。 我们在训练模型时主要使用随机翻转来使我们的数据更加多样化。
以下是旋转和翻转可能有益的一些实例:
填充(padding)在图像角周围添加额外的像素值以增加图像尺寸。 这样做可以确保图像具有一致的尺寸或纵横比,可以确保不会丢失信息或为特定模型架构准备图像。
# If a single int is provided this is used to pad all borders
padd_pixel = 100
img = v2.Pad(padding=padd_pixel)(orig_img)
# If sequence of length 2 is provided this is the padding on left/right and top/bottom respectively.
left_top, right_bottom = 100, 150
img = v2.Pad(padding=(left_top, right_bottom))(orig_img)
# If a sequence of length 4 is provided this is the padding for the left, top, right and bottom borders respectively.
left, right, top, bottom = 100, 100, 150, 150
img = v2.Pad(padding=(left, top, right, bottom))(orig_img)
这些 PyTorch 变换函数可帮助你将图像裁剪(crop)为所需大小或随机大小。
# Crop function expect exact co-ordinate x(left),y(top),w,h of crop region
top, left, height, width = 200, 50, 300, 300
img = v2.functional.crop(orig_img, top, left, height, width)
# We can also apply crop of specified size randomly on input image
height, width = 300, 300
img = v2.RandomCrop((height, width))(orig_img)
# We can also cropb the input at the centre of specified crop size
height, width = 300, 300
img = v2.CenterCrop((height, width))(orig_img)
这是另一种类型的裁剪变换,但它以独特的方式运作。 它首先随机选择图像的一部分,然后将所选区域的大小调整为指定的大小。
# randomly selects the region to crop then applies specified size to resize the crop
crop_size = (150, 150)
img = v2.RandomResizedCrop(size=crop_size)(orig_img)
这是非常有用的增强,广泛用于训练 Inception 网络。
以下是添加裁剪增强功能可能有益的一些实例:
通过将透视(perspective)转换应用于 2D 图像,你可以创建模拟不同视角和视点(在 3D 空间中)的新训练样本。
# apply a random perspective transform on an input image
img = v2.RandomPerspective(distortion_scale=0.5, p=1.0)(orig_img)
现在,让我们看看传递给 RandomPerspective
的不同参数:
Distortion_scale
:此参数控制图像上透视变换的程度。 扭曲比例为 0.2 表示图像可能会经历最多其宽度和高度 20% 的随机透视偏移。 这种转变改变了图像的视角,导致外观倾斜。p
:参数p设置为1.0,表示应用透视变换的概率为100%。 它使用代表概率得分的 p 值来确定是否应对图像应用变换。 当 p 等于 0 时,不应用变换。以下是一些示例,其中将随机透视变换添加到增强中可能是有益的:
这允许你对图像应用各种仿射(affine)变换,例如旋转、平移、缩放和剪切。 这与仅旋转不同,因为这考虑了其他参数而不仅仅是旋转角度。
关于这种特定增强的最好的部分是,你可以一起引入图像平移、缩放和旋转。 您必须格外小心传递给 Affine 函数的参数值。
# apply random affine transform on the input image
img = v2.RandomAffine(degrees=(30, 70), translate=(0.0, 0.1), scale=(0.5, 0.7))(orig_img)
现在,让我们看看传递给 RandomAffine 的不同参数:
旋转:
degrees=(30,70)
:这表示图像旋转的允许范围,其中 30 是最小度数,70 是最大度数。 旋转_度从范围 (30, 70) 中随机选择并应用于图像。degree=0
设置为 0,则禁用图像旋转并且不应用旋转。平移:
translate = (0.0,0.1)
:此参数控制随机图像平移或移动的程度。 这些值表示为图像宽度和高度的分数。 在这种情况下,图像在水平和垂直方向上可能会经历最多其宽度或高度 10% 的随机移动。缩放:
scale=(0.5, 0.7)
:此参数定义随机图像缩放的允许范围,使每个图像能够随机调整为 0.5 到 0.7 之间的系数。 这相当于将图像尺寸调整为原始尺寸的 50% 到 70% 之间。由于 RandomRotation 已经为你提供了旋转功能,因此可以使用 RandomAffine 实现图像缩放和平移变换。
图像平移和缩放变换可能有益的实例:
这就像图像变形一样,弹性(elastic)变换产生非常有趣的水状透视效果。
弹性变换模拟图像变形,如拉伸和扭曲,增强模型对现实世界中此类变化的适应能力。 它们有多种应用,但应明智地选择 alpha 值以避免过度使用。
# apply elastic transform on the input image
img = v2.ElasticTransform(alpha=250)(orig_img)
光度变换(photometric transforms)通过修改像素值同时保留图像几何形状来改变图像的光度属性。 它包括广泛的变换,如照明、颜色、图像纹理等。
为什么需要这些光度转换?
为了使我们的视觉模型更加稳健和通用,我们可以应用光度变换。 在图像上应用这些变换后,我们实现了更广泛的颜色和照明变化,这使得模型在现实场景中表现更好,在现实场景中,图像可能并不总是符合理想的照明和颜色标准。
以下是 PyTorch 中可用的各种光度转换:
该变换函数应用随机光度变换,即基于定义范围的亮度、色调、饱和度和对比度。 首先,让我们快速浏览一下代码,然后,我们将深入探讨每个转换的彻底解释。
# apply ColorJitter transformation to the input image
img = v2.ColorJitter(brightness=0.4,
contrast=0.5,
saturation=0.4,
hue=0.3)(org_img)
这些参数中的每一个(即亮度、色调、饱和度和对比度)都可以接受单个浮点数(例如 0.4)或指定范围的元组(例如(0.2,0.6))形式的值。 单个浮点指定固定值,而元组定义最小值和最大值。
以下是有关 ColorJitter 需要牢记的一些要点:
亮度(brightness)改变图像的整体光线。 可以通过缩放所有像素值来完成。 增加亮度使图像变亮,降低亮度使图像变暗。 让我们看一下代码:
# apply ColorJitter to alter image brightness
# to only apply brightness changes you must not sepcify other parameters # or set others to zero
img = v2.ColorJitter(brightness=(0.1, 1))(orig_img)
亮度应该是非负数,它可以是单个浮点值或浮点值的元组。 亮度值应介于 (0, inf) 之间。
下面关于亮度背景下的固定值和元组的解释至关重要,并且同样适用于饱和度和对比度。
如果亮度是单个固定浮点值,即 brightness=0.4
:
v2.ColorJitter(brightness=0.4)(orig_img)
那么这就是范围的计算方式如果亮度是浮点值的元组,即 brightness=(0.1, 1)
:
max > min
。Brightness_factor
是从给定的 (min,max)
范围中统一选择的。 在本例中 为 (0.1, 1)
。在模型训练期间改变图像亮度可能有益的情况:
对比度(contrast)是图像最暗部分和最亮部分之间的差异。 调整对比度会改变像素值的分布。 增加对比度会使暗区更暗,亮区更亮,从而增强整体视觉差异。
# alter only image contrast
img = v2.ColorJitter(contrast=(0, 10))(orig_img)
对比度应该是非负数,它可以是单个浮点值或浮点值的元组。 对比度值应介于 (0, inf)
之间。
请注意 - 请再次月度上面的亮度部分,以更好地理解对比度因子计算。
我们提供 contrast=0.4
单个值或元组 contrast=(0,10)
,将应用于图像的 contrast_factor
从范围中选择,其方式与计算 brightness_factor
相同。
在训练过程中改变图像对比度并将其添加为增强效果可能是有益的:
饱和度(saturation)调整控制图像中颜色的强度。 增加饱和度使颜色更加鲜艳,而减少饱和度则使颜色更加柔和。 无论颜色鲜艳度如何,这都可以帮助模型更加稳健并表现良好。
# alter just the image saturation
img = v2.ColorJitter(saturation=(0.1, 1))(orig_img)
饱和度应该是非负数,它可以是单个浮点值或浮点值的元组。 饱和度值应介于 (0, inf) 之间。
请注意 - 请访问上面的亮度部分,以更好地了解饱和度因子计算。
我们要么提供 saturation = 0.4
的单个值,要么提供元组 saturation = (0.1,1)
,将应用于图像的饱和度因子的选择方式与亮度因子的计算方式相同。
图像饱和度增强可能有益的实例:
色调(hue)调整沿着色轮移动图像中的颜色,而不改变图像亮度或饱和度。 色调可用于改变图像的整体色调。 这对于增强等各种问题都很有用。
# Create a color jitter transform to apply only hue changes
# Here, setting the hue range from 0.1 (minimum) to 0.4 (maximum)
img = v2.ColorJitter(hue=(0.1, 0.4))(orig_img)
hue =0.2
,则从范围 (-0.2, 0.2) 中统一选择色调因子使用色调变换可能有益的情况:
以给定的概率调整图像的清晰度(sharpness)。
# adjust the image sharpness
img = v2.RandomAdjustSharpness(sharpness_factor=10, p=0.8)(orig_img)
这里,p是概率,默认值为0.5, sharpness_factor
可以是任何非负数。
高斯模糊(Gaussian Blur)是平滑操作。 它通过对局部邻域内的像素值进行平均来引入受控的平滑量来模糊图像。 这有助于减少训练数据中的噪声和细粒度细节,从而使模型对现实数据中的噪声不太敏感。
# Apply blur on input image with GaussianBlur
img = v2.GaussianBlur(kernel_size=(11, 21), sigma=(5, 50)))(orig_img)
kernel_size
和 sigma
这两个因素共同决定图像中平滑或模糊的程度。 通过调整这些参数,你可以微调高斯模糊效果,以达到图像所需的平滑程度。
sigma:
sigma
控制用于模糊的高斯分布的标准偏差。 它确定应用于图像的平滑或模糊量。sigma
可以是单个固定值或元组 (min_sigma、max_sigma)
。sigma=0.5
为单个值,则 sigma
是固定的,如果是元组 (min_sigma, max_sigma)
则从范围 (min_sigma, max_sigma)
中均匀随机选择 sigma
。sigma
值越大,模糊范围越广、越强烈。kernel_size:
kernel_size
确定用于执行高斯模糊操作的卷积核的大小。kernel_size
应该是一个正数。 kernel_size
定义内核的宽度和高度。kernel_size
意味着模糊时会考虑更广泛的图像区域,从而产生更平滑、更明显的模糊效果。kernel_size
定义的高斯内核的大小控制模糊在图像区域上的传播方式。图像模糊增强可能有益的实例:
Solarize 是一种将图像中的像素值反转到超过特定阈值的操作。 换句话说,它翻转亮度值,使暗区域变亮,亮区域变暗。 此效果适用于高于指定阈值的像素值。
曝光图像的结果是令人震惊且常常超现实的外观。 它可以创造视觉上有趣和高对比度的效果,黑暗区域呈现出发光或“日光化”的质量。 曝光可用于艺术和创意图像处理。
# Solarize the input image
img = v2.RandomSolarize(threshold=5.0, Solarize)(orig_img)
阈值是像素值,因此如果阈值=5.0,则意味着所有超过5的像素值都被反转。
类型转换与前两者有很大不同; 它们更多地是作为效用转换而不是增强。 通过这些转换,我们可以在 PIL 图像和张量之间切换或根据需要更改输入数据类型。
请注意 - 在应用转换变换之前,请参阅此文档 ,因为其中一些转换可能会将数值从unit8缩放到float,反之亦然。
# Sample PIL image
pil_image = Image.open("sample_image.jpg")
以下是 PyTorch 中可用的各种转换:
# Convert PIL image to a PyTorch tensor
tensor_image = transforms.PILToTensor()(pil_image)
# Convert the tensor back to a PIL image
tensor_to_pil = transforms.ToPILImage()(tensor_image)
还有更多,请参阅文档了解更多详细信息。
合成(composition)变换就像将不同的变换函数组合在一起并将它们应用到输入图像上。 当你在图像上使用此转换管道时,它会遵循你为这些转换函数设置的顺序,一个接一个地应用它们。 创建脚本来加载数据以训练模型时,可以指定要在输入图像上使用的变换函数的组合。 让我们仔细看看这些函数。
PyTorch 中有两个主要使用的组合函数:
我们只会考虑这两个,因为它们更相关。
组合(compose)基本上允许你创建一系列可应用于数据集的数据转换,特别是图像数据。 它允许你将多个数据增强组合到单个转换管道中。
让我们看一下代码。
# Define a list of transformations you want to apply to your data
transformations_list = [
v2.Resize((224, 224)), # Resize the image to a fixed size
v2.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.2), # Randomly adjust color
v2.RandomHorizontalFlip(), # Randomly flip the image horizontally
v2.RandomRotation(15)] # Randomly rotate the image by up to 15 degrees
# Pass the list of transformations to Compose function
transformations = v2.Compose(transformations_list)
# Apply the transformations to the image
transformed_image = transformations(orig_img)
Compose
函数将转换函数列表作为输入。 当你通过此管道运行图像时,它会按照列出的顺序逐一应用每个转换。
compose
进行训练或推理,则可以使用 v2.Totensor()
将图像转换为 PyTorch 张量Transformed_imgae = Transformed_imgae.unsqueeze(0)
这是我第一次发现这一点,因为我通常使用 Compose
。 这也颇为有趣。 它的功能与 Compose
类似,主要区别在于它允许你指定要应用于输入图像的每个变换函数的概率 p
。 现在,让我们看一下代码,看看它是如何工作的。
# Define a list of transformations you want to apply to your data
transformations_list = [
v2.Resize((224, 224)), # Resize the image to a fixed size
v2.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.2), # Randomly adjust color
v2.RandomHorizontalFlip(), # Randomly flip the image horizontally
v2.RandomRotation(15)] # Randomly rotate the image by up to 15 degrees
# Pass the list of transformations to Compose function
transformations = v2.RandomApply(transformations_list, p=0.7)
# Apply the transformations to the image
transformed_image = transformations(orig_img)
RandomApply
函数接受一系列变换函数和概率分数作为输入。 当通过该管道处理输入图像时,它以概率 p
顺序将每个变换应用于图像。
在对 PyTorch 变换函数的深入探索中,我们涵盖了用于空间操作的几何变换、用于视觉变化的光度变换以及用于组合两个或多个变换的合成变换。 总之,充分了解这些功能和增强功能,我们可以提高数据质量并训练更强大的深度学习模型,确保它们为应对现实世界的挑战做好充分准备。
原文链接:PyTorch微调权威指南(3) - BimAnt