La guida completa alla creazione di set di dati e caricatori di dati personalizzati per diversi modelli in PyTorch
Prima di poter creare un modello di machine learning, devi caricare i dati in un set di dati. Fortunatamente, PyTorch ha molti comandi che aiutano con l'intero processo (se non hai familiarità con PyTorch ti consiglio di aggiornare le nozioni di base Qui).
PyTorch dispone di una buona documentazione per aiutare in questo processo, ma non ho trovato alcuna documentazione completa o tutorial sui set di dati personalizzati. Inizierò innanzitutto con la creazione di set di dati predefiniti di base e poi proseguirò fino alla creazione di set di dati da zero per diversi modelli!
Prima di immergerci nel codice per i diversi casi d'uso, comprendiamo la differenza tra i due termini. In genere, prima crei il tuo set di dati e poi crei un caricatore di dati. UN set di dati contiene le caratteristiche e le etichette di ciascun punto dati che verranno inserite nel modello. UN caricatore di dati è un iterabile PyTorch personalizzato che semplifica il caricamento dei dati con funzionalità aggiunte.
DataLoader(dataset, batch_size=1, shuffle=False, sampler=None,
batch_sampler=None, num_workers=0, collate_fn=None,
pin_memory=False, drop_last=False, timeout=0,
worker_init_fn=None, *, prefetch_factor=2,
persistent_workers=False)
Gli argomenti più comuni nel caricatore dati sono dimensione del lotto, mescolata (di solito solo per i dati di allenamento), num_lavoratori (per caricare i dati in più processi) e pin_memory (per inserire i tensori dei dati recuperati nella memoria bloccata e consentire un trasferimento dei dati più rapido alle GPU abilitate CUDA).
Si consiglia di impostare pin_memory = True invece di specificare num_workers a causa di complicazioni legate al multiprocessing con CUDA.
Nel caso in cui il tuo set di dati venga scaricato online o localmente, sarà estremamente semplice creare il set di dati. Penso che PyTorch sia buono documentazione su questo, quindi sarò breve.
Se sai che il set di dati proviene da PyTorch o è compatibile con PyTorch, chiama semplicemente le importazioni necessarie e il set di dati preferito:
from torch.utils.data import Dataset
from torchvision import datasets
from torchvision.transforms imports ToTensordata = torchvision.datasets.CIFAR10('path', train=True, transform=ToTensor())
Ogni set di dati avrà argomenti univoci da passare al suo interno (found Qui). In generale, sarà il percorso in cui è archiviato il set di dati, un valore booleano che indica se deve essere scaricato o meno (chiamato comodamente download), se si tratta di training o test e se è necessario applicare trasformazioni.
Ho sottolineato che le trasformazioni possono essere applicate a un set di dati alla fine dell'ultima sezione, ma cos'è in realtà una trasformazione?
UN trasformare è un metodo di manipolazione dei dati per la preelaborazione di un'immagine. Ci sono molti aspetti diversi nelle trasformazioni. La trasformazione più comune, Al tensore()convertirà il set di dati in tensori (necessari per l'inserimento in qualsiasi modello). Altre trasformazioni integrate in PyTorch (torchvision.transforms) includono capovolgimento, rotazione, ritaglio, normalizzazione e spostamento delle immagini. Questi vengono in genere utilizzati in modo che il modello possa generalizzarsi meglio e non si adatti eccessivamente ai dati di training. Se necessario, è possibile utilizzare l'aumento dei dati anche per aumentare artificialmente la dimensione del set di dati.
Attenzione, la maggior parte delle trasformazioni di torchvision accetta solo formati immagine Pillow o tensore (non numpy). Per convertire, utilizzare semplicemente
Per convertire da numpy, crea un tensore torcia o utilizza quanto segue:
From PIL import Image
# assume arr is a numpy array
# you may need to normalize and cast arr to np.uint8 depending on format
img = Image.fromarray(arr)
Le trasformazioni possono essere applicate simultaneamente utilizzando torchvision.transforms.compose. È possibile combinare tutte le trasformazioni necessarie per il set di dati. Un esempio è mostrato di seguito:
import torchvision.transforms.Composedataset_transform = transforms.Compose((
transforms.RandomResizedCrop(256),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225))
))
Assicurati di passare la trasformazione salvata come argomento nel set di dati affinché venga applicata nel caricatore dati.
Nella maggior parte dei casi di sviluppo del tuo modello, avrai bisogno di un set di dati personalizzato. Un caso d'uso comune sarebbe il trasferimento dell'apprendimento per applicare il proprio set di dati su un modello preaddestrato.
Ci sono 3 parti richieste per una classe del set di dati PyTorch: inizializzazione, lunghezzaE recupero di un elemento.
__dentro__: per inizializzare il set di dati, passare i dati grezzi ed etichettati. La procedura migliore consiste nel trasmettere separatamente i dati dell'immagine grezza e i dati etichettati.
__len__: restituisce la lunghezza del set di dati. Prima di creare il set di dati, è necessario verificare che i dati grezzi ed etichettati abbiano la stessa dimensione.
__getoggetto__: È qui che avviene tutta la gestione dei dati per restituire un determinato indice (idx) dei dati grezzi ed etichettati. Se è necessario applicare delle trasformazioni, i dati devono essere convertiti in un tensore e trasformati. Se l'inizializzazione conteneva un percorso per il set di dati, il percorso deve essere aperto ed è necessario accedere/preelaborare i dati prima di poterli restituire.
Set di dati di esempio per un modello di segmentazione semantica:
from torch.utils.data import Dataset
from torchvision import transformsclass ExampleDataset(Dataset):
"""Example dataset"""
def __init__(self, raw_img, data_mask, transform=None):
self.raw_img = raw_img
self.data_mask = data_mask
self.transform = transform
def __len__(self):
return len(self.raw_img)
def __getitem__(self, idx):
if torch.is_tensor(idx):
idx = idx.tolist()
image = self.raw_img(idx)
mask = self.data_mask(idx)
sample = {'image': image, 'mask': mask}
if self.transform:
sample = self.transform(sample)
return sample
Fonte: towardsdatascience.com