作者????♂?:讓機(jī)器理解語(yǔ)言か
專(zhuān)欄??:PyTorch
描述??:PyTorch 是一個(gè)基于 Torch 的 Python 開(kāi)源機(jī)器學(xué)習(xí)庫(kù)。
寄語(yǔ)??:??沒(méi)有白走的路,每一步都算數(shù)!???
?
介紹??
??torchvision.transforms
?是一個(gè)包含了常用的圖像變化方法的工具包,該工具包主要用于圖像預(yù)處理、數(shù)據(jù)增強(qiáng)等工作之中。本實(shí)驗(yàn),將詳細(xì)介紹?torchvision.transforms
?中常用的數(shù)據(jù)處理函數(shù)。
知識(shí)點(diǎn)??
- ??預(yù)處理的批操作:將預(yù)處理操作打包? →? 預(yù)處理集合器
- ??葡萄酒數(shù)據(jù)的預(yù)處理
- ??圖像數(shù)據(jù)的預(yù)處理
數(shù)據(jù)的預(yù)處理??
Compose
????????首先讓我們先來(lái)學(xué)習(xí)?torchvision.transforms.Compose()
,它的參數(shù)是一個(gè)由多個(gè) transforms 包中的方法組成的列表。簡(jiǎn)單的說(shuō),該函數(shù)的主要目的就是將所有的預(yù)處理操作進(jìn)行打包,當(dāng)有數(shù)據(jù)來(lái)時(shí),我們只需要將數(shù)據(jù)傳入該函數(shù)中,就能一次性對(duì)數(shù)據(jù)進(jìn)行所有的預(yù)處理操作。如下:
import torch
import torchvision
class ToTensor:
# 定義一個(gè)將原數(shù)據(jù)轉(zhuǎn)為 Torch 的操作
def __call__(self, X):
return torch.from_numpy(X)
class MulTransform:
# 定義一個(gè)將所有數(shù)據(jù)翻倍的預(yù)處理操作
def __call__(self, X):
X *= 2
return X
# 定義預(yù)處理集合器
composed = torchvision.transforms.Compose([ToTensor(), MulTransform()])
composed
"""
Compose(
<__main__.ToTensor object at 0x7fa24c2c6450>
<__main__.MulTransform object at 0x7fa24bbfdf90>
)
"""
????????上面我們定義了一個(gè)預(yù)處理的集合器,我們只需要將數(shù)據(jù)傳入?composed
?中,PyTorch 就會(huì)自動(dòng)對(duì)數(shù)據(jù)進(jìn)行?ToTensor()
?和?MulTransform()
?操作。如下:
import numpy as np
data = np.array([1, 2, 3])
composed(data)
# tensor([2, 4, 6])
????????從結(jié)果可以看出,盡管我們的數(shù)據(jù)需要進(jìn)行很多次預(yù)處理,但是我們只需要將這些預(yù)處理全部放入?Compose
?中進(jìn)行打包,就能形成一個(gè)數(shù)據(jù)預(yù)處理集合。當(dāng)我們需要處理某些數(shù)據(jù)時(shí),只需要簡(jiǎn)單的將數(shù)據(jù)傳入這個(gè)集合即可。
????????接下來(lái),我們以葡萄酒的數(shù)據(jù)預(yù)處理為例,修改上一個(gè)試驗(yàn)中的?WineDataset
?類(lèi),使其能夠輸出歸一化后的 Tensor 數(shù)據(jù)集。
葡萄酒數(shù)據(jù)的預(yù)處理??
首先,還是讓我們先來(lái)定義數(shù)據(jù)集合:
from torch.utils.data import Dataset
import pandas as pd
class WineDataset(Dataset):
# 建立一個(gè)數(shù)據(jù)集合繼承 Dataset 即可
def __init__(self, transform):
# I初始化數(shù)據(jù)
# 以pandas的形式讀入數(shù)據(jù)
xy = pd.read_csv(
"https://labfile.oss.aliyuncs.com/courses/2316/wine.csv", header=None)
self.n_samples = xy.shape[0]
# 這里我們就不做Tensor的轉(zhuǎn)換了,將其全部放入 transform 中
self.x_data = xy.values[:, 1:]
self.y_data = xy.values[:, 0].reshape(-1,1) # 轉(zhuǎn)為二維向量,和x匹配
# 數(shù)據(jù)預(yù)處理集合
self.transform = transform
# 返回 dataset[index]
def __getitem__(self, index):
sample = self.x_data[index], self.y_data[index]
if self.transform:
sample = self.transform(sample)
return sample
# 返回?cái)?shù)據(jù)長(zhǎng)度
def __len__(self):
return self.n_samples
????????可以看出?WineDataset
?類(lèi)中的代碼和上一個(gè)試驗(yàn)大致相同,我們只是多加了一個(gè) transform 變量,即數(shù)據(jù)預(yù)處理操作的集合。該變量并沒(méi)有在?WineDataset
?類(lèi) 中被定義,只是作為一個(gè)參數(shù)被傳入。
????????這樣做有一個(gè)好處就是,當(dāng)我們需要在原來(lái)的基礎(chǔ)上添加新的預(yù)處理操作時(shí),我們只需要在模型外重新定義 transform 變量即可,無(wú)需修改原來(lái)類(lèi)中的代碼。
????????接下來(lái),就讓我們來(lái)定義預(yù)處理操作了。首先,讓我們來(lái)定義數(shù)據(jù)的歸一化操作,這里使用最大最小歸一化:
class Normalization:
def __call__(self, sample):
inputs, targets = sample
amin, amax = inputs.min(), inputs.max() # 求最大最小值
inputs = (inputs-amin)/(amax-amin) # (矩陣元素-最小值)/(最大值-最小值)
return inputs, targets
# 測(cè)試代碼
a = 10*np.random.random((5, 5))
# 測(cè)試數(shù)據(jù) 前4列表示特征,最后一列表示標(biāo)簽
data = [a[:, 0:4], a[:, 4]]
Normalization()(data)
???
????????接下來(lái),讓我們來(lái)定義數(shù)據(jù)的轉(zhuǎn)化操作,即將原數(shù)據(jù)類(lèi)型轉(zhuǎn)為 Tensor :
class ToTensor:
def __call__(self, sample):
inputs, targets = sample
return torch.from_numpy(inputs), torch.from_numpy(targets)
# 測(cè)試代碼
a = 10*np.random.random((5, 5))
# 測(cè)試數(shù)據(jù) 前4列表示特征,最后一列表示標(biāo)簽
data = [a[:, 0:4], a[:, 4]]
ToTensor()(data)
??? ? ? ? 最后,讓我們使用這兩個(gè)預(yù)處理操作,來(lái)處理葡萄酒數(shù)據(jù)。
????????我們無(wú)需修改上面代碼,只需將其封裝到?Compose
?中,再傳入即可。
# 定義 composed
composed = torchvision.transforms.Compose([Normalization(), ToTensor()])
# 傳入該參數(shù),即可獲得一系列預(yù)處理之后的數(shù)據(jù)
dataset = WineDataset(transform=composed)
first_data = dataset[0]
features, labels = first_data
# 輸出類(lèi)型觀察數(shù)據(jù)是否發(fā)生改變
print(type(features), type(labels))
# 輸出內(nèi)容觀察數(shù)據(jù)是否進(jìn)行了歸一
print(features, labels)
??????????如上,我們使用了自定義的預(yù)處理方法,完成了 PyTorch 類(lèi)型的數(shù)據(jù)集的預(yù)處理。當(dāng)然,除了自定義的預(yù)處理方法外,PyTorch 還為我們提供了很多封裝好的預(yù)處理操作。
圖像的預(yù)處理??
??torchvision.transforms
?中有很多關(guān)于圖像預(yù)處理的函數(shù)。接下來(lái),讓我們對(duì)一些常用的圖像處理函數(shù)進(jìn)行闡述。如果你需要查看所有的函數(shù),可以訪問(wèn)?官方網(wǎng)址。
為了能夠更好的闡述這些函數(shù),讓我們以一張圖片為例。首先,讓我們來(lái)加載這張圖片:
!wget -nc "https://labfile.oss.aliyuncs.com/courses/2534/cat.jpg"
import torchvision.transforms as transforms
from PIL import Image
import matplotlib.pyplot as plt
from matplotlib.pyplot import imshow
%matplotlib inline
img = Image.open("cat.jpg")
imshow(img)
??
?????????從中心開(kāi)始,裁剪給定大小的 PIL 圖像:transforms.CenterCrop
。
# torchvision.transforms.CenterCrop(size):從中心開(kāi)始,裁剪給定大小的 PIL 圖像
transform = transforms.CenterCrop((64, 200))
new_img = transform(img)
imshow(new_img)
??
?????????改變圖片的亮度、對(duì)比度和飽和度:transforms.ColorJitter
。
# transforms.ColorJitter(brightness=0, contrast=0, saturation=0, hue=0):
# 改變圖片的亮度、對(duì)比度和飽和度
plt.subplot(221)
imshow(img)
# r隨機(jī)改變亮度
my_img1 = transforms.ColorJitter((0.5, 0.6))(img)
plt.subplot(222)
imshow(my_img1)
# 隨機(jī)改變對(duì)比度
my_img2 = transforms.ColorJitter(0, (0.5, 0.6))(img)
plt.subplot(223)
imshow(my_img2)
# 隨機(jī)改變飽和度
my_img3 = transforms.ColorJitter(0, 0, (0.5, 0.6))(img)
plt.subplot(224)
imshow(my_img3)
plt.show()
??
?將圖像轉(zhuǎn)為灰度圖像:torchvision.transforms.Grayscale(num_output_channels )
。
- 如果返回的圖像是單通道 num_output_channels = 1。
- 如果返回的圖像是 3 通道,其中 num_output_channels = 3。
plt.subplot(1, 3, 1)
imshow(img)
my_img1 = transforms.Grayscale(1)(img)
plt.subplot(132)
imshow(my_img1, 'gray')
my_img2 = transforms.Grayscale(3)(img)
plt.subplot(133)
imshow(my_img2)
??
?????????使用給定的 pad 值將給定的 PIL 圖像四處填充:ransforms.Pad(padding,fill,padding_mode)
。
# transforms.Pad(padding,fill = 0,padding_mode ='constant' ):
# 使用給定的 pad 值將給定的 PIL 圖像四處填充
plt.subplot(121)
imshow(img)
# 四周加邊界
my_img = transforms.Pad(padding=20, fill=(0, 255, 255),
padding_mode='constant')(img)
plt.subplot(122).set_title("Pad")
imshow(my_img)
??
?????????保持圖像中心不變的中心仿射變換(可以理解為不同程度的旋轉(zhuǎn),再在空余位置補(bǔ) 0):transforms.RandomAffine (degrees, translate, scale, shear, resample, fillcolor)
。
# transforms.RandomAffine(degrees, translate=None, scale=None,
# shear=None, resample=False, fillcolor=0):
# 保持圖像中心不變的中心仿射變換(可以理解為不同程度的旋轉(zhuǎn),再在空余位置補(bǔ) 0)
my_img1 = transforms.RandomAffine(60)(img)
plt.subplot(221).set_title("rotate_only")
imshow(my_img1)
my_img2 = transforms.RandomAffine(60, translate=(0.3, 0.3))(img)
plt.subplot(222).set_title("rotate_translate")
imshow(my_img2)
my_img3 = transforms.RandomAffine(60, scale=(2.0, 2.1))(img)
plt.subplot(223).set_title("rotate_scale")
imshow(my_img3)
my_img4 = transforms.RandomAffine(0, shear=60)(img)
plt.subplot(224).set_title("shear_only")
imshow(my_img4)
plt.tight_layout()
??
?????????將原圖像進(jìn)行隨機(jī)裁剪、裁剪后重新放縮到 size 大?。?span style="color:#fe2c24;">torchvision.transforms.RandomResizedCrop(size, scale,ratio,interpolation)
。
#torchvision.transforms.RandomResizedCrop(size, scale,ratio,interpolation)
new_img = transforms.RandomResizedCrop((128, 126), scale=(0.08, 1.0),
ratio=(0.75, 1.333333333), interpolation=2)(img)
imshow(new_img)
??
?????????當(dāng)然除了上面這些相關(guān)圖像的處理外,torchvision.transforms
?中還有很多圖像處理的函數(shù),你可以按照上面代碼的思路對(duì)其他函數(shù)進(jìn)行檢驗(yàn)。官方 API?請(qǐng)點(diǎn)擊這里。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-422228.html
實(shí)驗(yàn)總結(jié)??
????????本實(shí)驗(yàn)詳細(xì)的闡述了?torchvision.transforms
?的使用方法和?torchvision.transforms
?中內(nèi)置的圖像處理函數(shù)。這些預(yù)處理操作時(shí)非常重要的,一系列好的數(shù)據(jù)預(yù)處理操作,可以大大的加快模型的收斂速度,提高模型的準(zhǔn)確率和魯棒性。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-422228.html
到了這里,關(guān)于【PyTorch】第八節(jié):數(shù)據(jù)的預(yù)處理的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!