Continuando la mia serie su come costruire reti neurali convoluzionali classiche che hanno rivoluzionato il campo della visione computazionale negli ultimi 1-2 decenni, prossimamente costruiremo VGG, una rete convoluzionale molto profonda, da zero utilizzando PyTorch. Puoi vedere gli articoli precedenti della serie nel mio profilo, principalmente LeNet5 e AlexNet.
Come prima, esaminerò l’architettura e l’intuito dietro VGG e come i risultati erano all’epoca. Poi esploreremo il nostro dataset, CIFAR100, e lo caricherò nel nostro programma utilizzando del codice efficiente in termini di memoria. Poi, implementerò VGG16 (il numero si riferisce al numero di layer, ci sono due versioni fondamentalmente VGG16 e VGG19) da zero utilizzando PyTorch e lo trainerò sul nostro dataset insieme all’valutarlo sul nostro set di test per vedere come si comporta su dati non visti
VGG
Sulla base del lavoro di AlexNet, VGG punta ad un’altra aspettiva cruciale delle reti neurali convoluzionali (CNN), la profondità. È stato sviluppato da Simonyan e Zisserman. Normalmente consiste in 16 layer convoluzionali, ma può essere esteso a 19 layer (e quindi ci sono due versioni, VGG-16 e VGG-19). Tutti i layer convoluzionali sono composti da filtri 3×3. Puoi leggere ulteriori informazioni sulla rete nel paper ufficiale qui
VGG16 architecture. Fonte
Caricamento Dati
Set Dati
Prima di costruire il modello, una delle cose più importanti in qualsiasi progetto di apprendimento automatico è caricare, analizzare e pre-processare il dataset. In questo articolo, userò il dataset CIFAR-100. Questo dataset è simile al CIFAR-10, ma differisce perché include 100 classi, ciascuna contenente 600 immagini. Ci sono 500 immagini di addestramento e 100 immagini di test per classe. Le 100 classi del CIFAR-100 sono raggruppate in 20 superclassi. Ogni immagine è accompagnata da una “label” “fine” (la classe a cui appartiene) e una “label” “grossa” (la superclasse a cui appartiene). Utilizzeremo la “label” “fine” qui. Ecco la lista delle classi nel CIFAR-100:
Lista delle classi per il dataset CIFAR-100
Importo le librerie
Procederemo principalmente con torch
(utilizzato per la costruzione del modello e l’addestramento), torchvision
(per il caricamento/processamento dei dati, contiene dataset e metodi per il processamento di quei dataset in computer vision) e numpy
(per la manipolazione matematica). Definiremo anche una variabile device
in modo da permettere al programma di utilizzare la GPU se disponibile.
Caricamento dei dati
torchvision
è una libreria che fornisce un accesso facile a molti dataset di computer vision e metodi per pre-processare questi dataset in un modo facile e intuitivo
- Definiamo una funzione
data_loader
che restituisce dati di allenamento/validazione o dati di test a seconda degli argomenti - Iniziamo definendo la variabile
normalize
con la media e le deviazioni standard di ciascuno dei canali (rosso, verde e blu) nel dataset. Questi possono essere calcolati manualmente, ma sono anche disponibili online. Questo viene usato nella variabiletransform
dove reimpostiamo i dati, li convertiamo in tensori e poi li normalizziamo - Se l’argomento
test
è vero, carichiamo semplicemente la parte di test del dataset e la restituiamo usando i data loaders (spiegati qui sotto) - Se l’
test
è falso (è anche il comportamento predefinito), carichiamo la parte di allenamento del dataset e lo dividiamo casualmente in allenamento e validazione (0.9:0.1) - Infine, usiamo i data loaders. Questo potrebbe non influenzare il rendimento in caso di dataset piccoli come CIFAR100, ma può davvero limitare il rendimento in caso di grandi dataset e viene considerata una buona pratica. I data loaders ci consentono di iterare sui dati in batch, e i dati sono caricati durante l’iterazione e non tutti all’inizio nell’RAM.
VGG16 da zero
Per costruire il modello da zero, prima bisogna capire come funzionano le definizioni di modelli in torch
e i diversi tipi di layer che utilizzeremo qui:
- Ogni modello personalizzato deve eredire dalla classe
nn.Module
poiché fornisce alcune funzionalità di base che aiutano il modello nell’addestramento. - In secondo luogo, ci sono due cose principali da fare. Prima, definire i diversi layer del nostro modello all’interno della funzione
__init__
e la sequenza in cui questi layer saranno eseguiti sull’input all’interno della funzioneforward
Ora definiamo i diversi tipi di layer che utilizziamo qui:
nn.Conv2d
: Queste sono le layer convoluzionali che accettano come argomenti il numero di canali di input e di output, insieme alla dimensione del kernel per il filtro. Accettano anche eventuali stride o padding se si desidera applicare questi.nn.BatchNorm2d
: Questo applica la normalizzazione in batch all’output della layer convoluzionale.nn.ReLU
: Questa è l’attivazione applicata agli output vari del network.nn.MaxPool2d
: Questo applica il pooling massimo all’output con la dimensione del kernel datann.Dropout
: Questo viene utilizzato per applicare il dropout all’output con una probabilità datann.Linear
: Questo in sostanza è un layer completamente connessonn.Sequential
: Questo non è letteralmente un tipo di layer, ma aiuta a combinare diverse operazioni che fanno parte dello stesso passo
Utilizzando questo knowledge, ora possiamo costruire il nostro modello VGG16 usando l’architettura del paper:
VGG16 da Scratch
Hyperparameters
Un importante aspetto di qualsiasi progetto di machine learning o deep learning è l’ottimizzazione degli hyper-parameters. Qui, non sperimenteremo valori diversi per questi, ma dovremo definirli prima. Questi includono la definizione del numero di epoch, del batch size, dell’learning rate, della funzione di perdita insieme all’ottimizzatore
Impostazione degli hyper-parameters
Training
Ora siamo pronti a addestrare il nostro modello. Prima guarderemo come addestriamo il modello in torch
e poi guarderemo il codice:
- Per ogni epoch, passiamo attraverso le immagini e le etichette all’interno del nostro
train_loader
e spostiamo queste immagini e etichette sul GPU se disponibile. Questo avviene automaticamente - Usiamo il nostro modello per predire sulle etichette (
model(images)
) e poi calcoliamo la perdita tra le predizioni e le etichette vere usando la nostra funzione di perdita (criterion(outputs, labels)
) - Poi usiamo quella perdita per il backpropagation (
loss.backward
) e aggiorniamo i pesi (optimizer.step()
). Ma ricordate di impostare i gradienti a zero prima di ogni aggiornamento. Questo viene fatto usandooptimizer.zero_grad()
- Anche alla fine di ogni epoch, usiamo il nostro set di validazione per calcolare l’accuratezza del modello. In questo caso, non abbiamo bisogno di gradienti, quindi usiamo
with torch.no_grad()
per una valutazione più veloce
Adesso, combiniamo tutto questo nel seguente codice:
Addestramento
Potete vedere l’output del codice sopra come segue, che dimostra che il modello stia imparando effettivamente, poiché la perdita si sta riducendo con ogni epoch:
Perdite di addestramento
Testing
Per le prove, usiamo esattamente lo stesso codice come validazione, ma con il test_loader
:
Testing
Utilizzando il codice precedente e addestrando il modello per 20 epoch, abbiamo ottenuto un’accuratezza del 75% sul set di test.
Conclusione
Ora concludiamo ciò che abbiamo fatto in questo articolo:
- Abbiamo iniziato capendo l’architettura e i diversi tipi di layer nella modello VGG-16
- Successivamente, abbiamo caricato e pre-processato il dataset CIFAR100 usando
torchvision
- Poi, abbiamo usato
PyTorch
per costruire il nostro modello VGG-16 da zero, incluso capire i diversi tipi di layer disponibili intorch
- Infine, abbiamo addestrato e testato il nostro modello sul dataset CIFAR100, e il modello sembrava funzionare bene sul set di test con un 75% di accuratezza
Lavoro futuro
Utilizzando questo articolo, ottieni una buona introduzione e apprendimento pratico, ma imparerai molto di più se estendi questo e vedi cosa puoi fare altrimenti:
- Puoi provare a utilizzare diversi dataset. Uno di questi è CIFAR10 o un sottoinsieme del dataset ImageNet.
- Puoi sperimentare con diversi hyperparametri e vedere la migliore combinazione di essi per il modello
- Infine, puoi provare ad aggiungere o rimuovere layer dal dataset per vedere il loro impatto sulla capacità del modello. Meglio ancora, prova a costruire la versione VGG-19 di questo modello.
Source:
https://www.digitalocean.com/community/tutorials/vgg-from-scratch-pytorch