PyTorch之Dataset和TensorDataset
技術標籤:Deep Learning深度學習pytorchtensorflow人工智慧機器學習
Deep Learning系列 @cxx
Dataset v.s. TensorDataset
使用PyTorch搭建過Neural Network的小夥伴們都知道,在資料準備步驟裡,我們需要把訓練集的x和y分裝在dataset裡,然後將dataset分裝到DataLoader中去,便於之後在搭建好的模型中訓練。
簡言之,dataset是用來做打包和預處理(比如輸入資料路徑自動讀取);DataLoader則是將整個資料集(dataset)按照batch進行迭代分裝或者shuffle(可以得到一個iterator以利於for迴圈讀取)。
Dataset
如果使用繼承Dataset的方式,那麼在自定義的dataset類中必須給予__len__和__getitem__的定義。
進行圖片處理的時候,可以定義一個transforms來隨機旋轉訓練圖片,將圖片格式變成tensor等
(這裡有一個坑)
假設我們讀取了一個有如下格式的圖片
將圖片分裝到dataset裡,再放到dataloader裡
from torch.utils.data import TensorDataset
batch_size = 128
train_transform = transforms.Compose([
transforms.ToPILImage( ),
transforms.RandomHorizontalFlip(),
transforms.RandomRotation(15),
transforms.ToTensor(),]
)
test_transform = transforms.Compose(
[transforms.ToPILImage(),
transforms.ToTensor(),]
) #測試集不需要翻轉或旋轉圖片
#繼承Dataset
class ImgDataset(Dataset):
def __init__(self, x, y=None, transform= None):
self.x = x
self.y = y
# label is required to be a LongTensor
if y is not None:
self.y = torch.LongTensor(y)
self.transform = transform
def __len__(self):
return len(self.x)
def __getitem__(self, index):
X = self.x[index]
if self.transform is not None:
X = self.transform(X)
if self.y is not None:
Y = self.y[index]
return X, Y
else:
return X
#將dataset分裝到dataloader裡
train_dataloader = DataLoader(
train_dataset,
batch_size=batch_size,
shuffle=True
)
test_dataloader = DataLoader(
val_dataset,
batch_size=batch_size,
shuffle=False
)
接下來我們可以輸出一個batch看看圖片的格式
我們發現一個batch的x[0]的shape由原先的(128, 128, 3)變成了(3, 128, 128)。
原因在於transformers.toTensor()方法有自動轉換維度的功能,它會將channel變成第一維(奪麼坑爹的功能,導致我排查了好久不知道是哪裡出了問題==)
具體可以參照這篇部落格 transforms.ToTensor()本身有維度轉換功能
TensorDataset
張量資料集tensrdataset是最常見的形式,因為PyTorch本身有提供方便的TensorDataset給我們使用
torch.utils.data.TensorDataset(data_tensor, target_tensor)
用TensorDataset寫會少寫很多東西
#將資料轉換成tensor
tsr_x_train, tsr_y_train = torch.tensor(x_train), torch.tensor(y_train)
tsr_x_val, tsr_y_val = torch.tensor(x_val), torch.tensor(y_val)
tsr_x_testing = torch.tensor(x_test)
#然後只需要一行就可以啦
train_dataset = TensorDataset(tsr_x_train, tsr_y_train)
val_dataset = TensorDataset(tsr_x_val, tsr_y_val)
#裝入dataloader的步驟同上
train_dataloader = DataLoader(
train_dataset,
batch_size=batch_size,
shuffle=True
)
test_dataloader = DataLoader(
val_dataset,
batch_size=batch_size,
shuffle=False
)
我們跑一個loop看看這次維度是否被轉換了
答案是:這次沒有!
這次的x[0]的shape同我們一開始設定的shape,TensorDataset並沒有幫我們把channel數調成第一維。
這裡真的要注意呀。