教程參考:
https://pytorch.org/tutorials/
https://github.com/TingsongYu/PyTorch_Tutorial
https://github.com/yunjey/pytorch-tutorial
詳細(xì)的transform的使用樣例可以參考:ILLUSTRATION OF TRANSFORMS
為什么要使用transforms
你得到的原始數(shù)據(jù),可能并不是你期望的用于模型訓(xùn)練的數(shù)據(jù)的形式,比如數(shù)據(jù)中圖像的大小不同、數(shù)據(jù)的格式不對。這時就需要你對數(shù)據(jù)進行統(tǒng)一的處理,torchvision.transforms就提供了一些幫助我們進行數(shù)據(jù)處理的簡易手段。
在pytorch官方教程最開始,給了這樣一個示例。
示例中使用自帶的datasets:FashionMNIST,為了便于訓(xùn)練,對于原始數(shù)據(jù)和label分別使用了transform的方法。
對于數(shù)據(jù)本身,使用的方法是 ToTensor(),
對于標(biāo)簽,使用的方法是one-hot。
在后面的部分我們會詳細(xì)介紹一下不同的transform方法。
import torch
from torchvision import datasets
from torchvision.transforms import ToTensor, Lambda
ds = datasets.FashionMNIST(
root="data",
train=True,
download=True,
transform=ToTensor(),
target_transform=Lambda(lambda y: torch.zeros(10, dtype=torch.float).scatter_(0, torch.tensor(y), value=1))
)
torchvision.transforms中提供了多個方法,并且這些方法可以使用Compose進行連接,并按順序執(zhí)行。其中的大部分transforms方法都可以接受PIL圖像和tensor圖像作為輸入,當(dāng)然也有一部分在輸入上有限制。
transforms方法舉例
我們使用opencv讀入一張cifar10中的圖片作為例子,并將其通道從BGR轉(zhuǎn)為RGB通道。使用opencv讀入的圖片,為numpy.ndarray格式。下圖是我們的例子,一個類別為airplane的圖像。
ToTensor()
ToTensor()方法可以把一個PIL圖像或者numpy.ndarray數(shù)據(jù)轉(zhuǎn)成FloatTensor的形式,并且將圖像規(guī)范化到0和1之間。
更細(xì)致地來說,它會把一共PIL圖像,或者范圍在[0,255]的大小為(HxWxC)的numpy.ndarray轉(zhuǎn)成一個大小為(CxHxW)的范圍在[0.0,1.0]的floattensor。ndarray數(shù)據(jù)的dtype必須是np.uint8。
使用ToTensor()方法對我們的img進行處理,可以看到它原本為uint8的ndarray,變成了float32的tensor,它的形狀從(32, 32, 3)轉(zhuǎn)為(3, 32, 32),并且它的像素值的大小從51 到 255被轉(zhuǎn)變?yōu)?.2到1.0。
我們也可以將圖像讀取為PIL Image的形式,并使用同樣的方法處理。得到的結(jié)果是完全相同的。
Normalize()
Normalize()方法可以把一個tensor數(shù)據(jù)進行歸一化/標(biāo)準(zhǔn)化處理。在使用時,需要你提供數(shù)據(jù)的均值和方差,Normalize()會對輸入數(shù)據(jù)的每一個通道進行歸一化處理。使用的方法是:
o
u
t
p
u
t
[
c
h
a
n
n
e
l
]
=
i
n
p
u
t
[
c
h
a
n
n
e
l
]
?
m
e
a
n
[
c
h
a
n
n
e
l
]
s
t
d
[
c
h
a
n
n
e
l
]
output[channel] = \frac{input[channel] - mean[channel]}{std[channel]}
output[channel]=std[channel]input[channel]?mean[channel]?
要注意它的輸入是tensor格式,所以一般把它放到ToTensor()后面使用。
使用之后數(shù)據(jù)的大小類型都沒有發(fā)生變化,但是值的范圍發(fā)生了變化。
Geometry
主要對圖像的大小形狀等進行調(diào)整,沒有改變圖像的顏色信息。
transforms.Resize()
torchvision.transforms.Resize(size, interpolation=InterpolationMode.BILINEAR, max_size=None, antialias='warn')
Resize()的輸入可以是PIL圖像也可以是tensor。給定一張圖片,Resize()會對圖像的長款進行縮放,把它變成我們期望的大小。
輸入的size可以是一個整數(shù)也可以是一個序列[h,w],如果是單個整數(shù)的話,則被認(rèn)為是期望的短邊的大小,長邊會按比例縮放。
輸入的interpolation是一個插值方法。
輸入max_size定義了一個目標(biāo)圖像的長邊大小的上限,如果超過上限,則會重新resize。
transforms.CenterCrop( size )
CenterCrop()的輸入可以是PIL圖像也可以是Tensor。給定一張圖片,CenterCrop()會從圖中心開始對圖像進行裁剪,只保留我們期望的大小。假如輸入的圖像大小比我們期望的size小,則會在圖像周圍進行補0操作。
下圖的第一張圖為32x32大小的原圖,第二張圖為10x10的crop結(jié)果,第三張圖為40x40的crop結(jié)果。
transforms.RandomCrop(size)
torchvision.transforms.RandomCrop(size, padding=None, pad_if_needed=False, fill=0, padding_mode='constant')
RandomCrop()的輸入可以是PIL圖像也可以是Tensor。給定一張圖像,RandomCrop()會在隨機位置對圖像進行裁剪
輸入的size可以是一個整數(shù)也可以是一個序列[h,w],如果是單個整數(shù)的話,認(rèn)為crop的圖像的大小是[size,size]。
輸入的padding可以是一個整數(shù)也可以是一個序列,如果是一個整數(shù),會使用這個整數(shù)對所有的邊進行padding。如果是一個長度為2的序列,則會分別用來擴充left/right和top/bottom。如果是一個長度為4的整數(shù),則分別對應(yīng)了每一個邊。
輸入的padding_mode有四個選項,分別是constant(常數(shù)填充), edge(邊緣填充),reflect(鏡像填充),symmetric (對稱填充)。
鏡像填充在填充時以邊界為鏡面形成鏡像。對稱填充則是使用對稱值。具體來說,對[1,2]在左右進行一個像素大小的填充,使用鏡像填充得到的結(jié)果為[2,1,2,1],使用對稱填充得到的結(jié)果為[1,1,2,2]。
下圖的第一張圖為32x32大小的原圖,第二張和第三張為10x10的crop結(jié)果,因為randomcrop,所以兩個圖的結(jié)果不一樣。
transforms.RandomResizedCrop()
torchvision.transforms.RandomResizedCrop(size, scale=(0.08, 1.0), ratio=(0.75, 1.3333333333333333), interpolation=InterpolationMode.BILINEAR, antialias: Optional[Union[str, bool]] = 'warn')
RandomResizedCrop()的輸入可以是PIL圖像也可以是Tensor。給定一張圖像,RandomResizedCrop()會在隨機位置對圖像進行隨機大小的裁剪,并把它resize成期望的大小。
輸入的size可以是一個整數(shù)也可以是一個序列[h,w],如果是單個整數(shù)的話,認(rèn)為crop的圖像的大小是[size,size]。
輸入的scale要求是一個tuple,定義了crop的區(qū)域大小的下限和上限,它使用的是一個基于原圖大小的比例值。
輸入的ratio要求是一個tuple,定義了crop區(qū)域的長寬比的下限和上限。
scale和ratio的區(qū)別是,scale代表了取長寬的基準(zhǔn),ratio是在這個基準(zhǔn)上參考的長寬比。
輸入的interpolation要求是一個插值方法,在RandomResizedCrop()中沒有padding,因為隨即裁剪得到的圖像會使用插值方法resize到期望的大小。
下圖的第一張圖為32x32大小的原圖,第二張和第三張為40x40的crop結(jié)。
transforms.FiveCrop(size)
FiveCrop()的輸入可以是PIL圖像也可以是Tensor,給定一張圖像,獲得圖像四個角和中心的crop結(jié)果。
要注意,F(xiàn)iveCrop()返回的結(jié)果是五張圖,而不是一張圖。
對于一個大小為(b, c, h, w)的tensor的輸入,它返回的結(jié)果為(b, ncrop, c, size_h, size_w)。
transforms.TenCrop(size, vertical_flip = False)
TenCrop()和FiveCrop()類型,只不過在其基礎(chǔ)上增加了翻轉(zhuǎn)。默認(rèn)是使用水平翻轉(zhuǎn),如果vertical_clip設(shè)為True,就會使用垂直翻轉(zhuǎn)。
RandomHorizontalFlip and RandomVerticalFlip
torchvision.transforms.RandomHorizontalFlip(p=0.5)
torchvision.transforms.RandomVerticalFlip(p=0.5)
兩個函數(shù)的輸入可以是PIL圖像也可以是tensor。
輸入P代表反轉(zhuǎn)圖像的概率,默認(rèn)為0.5,即有50%的概率該圖像會被翻轉(zhuǎn)。
RandomRotation()
torchvision.transforms.RandomRotation(degrees, interpolation=InterpolationMode.NEAREST, expand=False, center=None, fill=0)
RandomRotation()的輸入可以是PIL圖像也可以是tensor。
輸入degrees可以是一個整數(shù)或者一個序列。如果是整數(shù)則代表旋轉(zhuǎn)的范圍是 - degrees,+ degrees,如果是一組數(shù)則分別代表了最小值和最大值。
輸入interpolation是一個插值方法。
輸入expand代表是否要對圖片進行擴展,經(jīng)過旋轉(zhuǎn)后圖片的形狀發(fā)生變化,如果expand = False,則會默認(rèn)保持輸出和輸入圖像大小一致。
輸入center代表旋轉(zhuǎn)中心,默認(rèn)是圖片中心。
輸入fill代表填充圖片邊界外 區(qū)域所用的數(shù)值,默認(rèn)是0。
第一行的是expand = False時隨機旋轉(zhuǎn)的結(jié)果,輸出圖像和輸入圖像保持一樣的大小。第二行是expand = True時的結(jié)果,輸出圖像的大小發(fā)生了變化。
Color
主要對圖像的顏色信息進行調(diào)整,沒有改變圖像的形狀大小。
ColorJitter()
torchvision.transforms.ColorJitter(brightness: Union[float, Tuple[float, float]] = 0, contrast: Union[float, Tuple[float, float]] = 0, saturation: Union[float, Tuple[float, float]] = 0, hue: Union[float, Tuple[float, float]] = 0)
ColorJitter()的輸入可以是PIL圖像也可以是tensor。假如輸入的是tensor,期望tensor的數(shù)據(jù)格式為[…, 1 or 3, H, W]。ColorJitter()可以隨即調(diào)整圖像的亮度,對比度,飽和度,色調(diào)等。
可以看到使用ColorJitter()后只有圖像的顏色發(fā)生了變化,幾何信息沒有受到影響。
RandomGrayscale(p = 0.1)
RandomGrayscale()的輸入可以是PIL圖像是也可以是tensor,但是要求tensor的通道數(shù)是3。RandomGrayscale()有p的概率將一個圖像轉(zhuǎn)換為灰度圖。
GaussianBlur(kernel_size, sigma=(0.1, 2.0))
GaussianBlur()的輸入可以是PIL圖像也可以是tensor。給定一張圖像,它可以隨機使用高斯模糊來把圖像變得模糊。
輸入kernel_size是一個整數(shù)或者序列,表示高斯核的大小。
輸入sigma是代表標(biāo)準(zhǔn)差的上下界。
下圖為kernel_size = 5時的結(jié)果。
RandomInvert(p=0.5)
RandomInvert()的輸入可以是PIL圖像也可以是tensor。給定一張圖像,RandomInvert()有p的概率翻轉(zhuǎn)圖像的顏色。
Composition
主要是不同的transforms的組合方式。
Compose(transforms)
Compose()將多個transforms方法組合在一起,在使用時會按順序進行。
如以下例子,首先將圖片進行CenterCrop,然后轉(zhuǎn)變?yōu)閠ensor格式,最后又將圖像的dtype變?yōu)閒loat。
>>> transforms.Compose([
>>> transforms.CenterCrop(10),
>>> transforms.PILToTensor(),
>>> transforms.ConvertImageDtype(torch.float),
>>> ])
Compose()方法可以用torch.nn.Sequential()替代。
RandomApply(transforms, p)
RandomApply()將多個transforms方法組合在一起,在使用時按照概率p決定是否執(zhí)行,要么全都執(zhí)行,全么全都不執(zhí)行。
RandomChoice(transforms,p)
RandomChoice() 參考random.choices方法,從多個transforms方法中選擇一個使用。
RandomOrder(transforms)
RandomOrder()將多個transforms方法而在一起,在使用時會按隨機順序進行。
Miscellaneous
RandomErasing()
torchvision.transforms.RandomErasing(p=0.5, scale=(0.02, 0.33), ratio=(0.3, 3.3), value=0, inplace=False)
RandomErasing()方法的輸入必須是tensor,這個函數(shù)不支持PIL圖像。給定一個圖像,RandomErasing()方法會隨機選擇圖像中的一塊并擦除他的元素值。
輸入p代表執(zhí)行擦除操作的概率。
輸入scale代表擦除區(qū)域占輸入圖像的范圍。
輸入ratio代表擦除區(qū)域的長寬比。
輸入value代表擦除后用來替換的值。
輸入inplace代表是否在原圖像上進行操作。
因為輸入必須是tensor,所以只能放在ToTensor()后面使用。
>>> transform = transforms.Compose([
>>> transforms.RandomHorizontalFlip(),
>>> transforms.PILToTensor(),
>>> transforms.ConvertImageDtype(torch.float),
>>> transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225)),
>>> transforms.RandomErasing(),
>>> ])
Lambda(lambda)
Lambda()就是在最開始的例子中,target_transform使用的方法。
該例子定義了一個one-hot編碼的函數(shù),對于輸入的整數(shù)類型的圖像類別,可以將其轉(zhuǎn)為特殊的one-hot編碼格式
target_transform=Lambda(lambda y: torch.zeros(10, dtype=torch.float).scatter_(0, torch.tensor(y), value=1))
Auto-Augmentation
pytorch 提供了一些policy供使用者選擇,比如 IMAGENET, CIFAR10 and SVHN. 依靠這些policy,使用者可以直接套用前人的augmentation方法,而不需要自己編寫代碼。文章來源:http://www.zghlxwxcb.cn/news/detail-480929.html
- AutoAugment(policy) 使用你給定的policy執(zhí)行augmentation方法。
- RandAugment() https://arxiv.org/abs/1909.13719
- TrivialAugmentWide() https://arxiv.org/abs/2103.10158
- AugMix() https://arxiv.org/abs/1912.02781
之后有時間的話再介紹一下別的augmentation常用的包。文章來源地址http://www.zghlxwxcb.cn/news/detail-480929.html
到了這里,關(guān)于第二章 數(shù)據(jù)處理篇:transforms的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!