Costruire una rete neurale convoluzionale con PyTorch

Creare una CNN con PyTorch

 

Introduzione

 

Una Convolutional Neural Network (CNN o ConvNet) è un algoritmo di deep learning specificamente progettato per compiti in cui il riconoscimento degli oggetti è cruciale, come la classificazione, la rilevazione e la segmentazione delle immagini. Le CNN sono in grado di raggiungere un’accuratezza di stato dell’arte su compiti complessi di visione, alimentando molte applicazioni reali come sistemi di sorveglianza, gestione dei magazzini e altro ancora.

Come esseri umani, possiamo facilmente riconoscere gli oggetti nelle immagini analizzando i modelli, le forme e i colori. Le CNN possono essere addestrate a eseguire anche questo riconoscimento, imparando quali modelli sono importanti per la differenziazione. Ad esempio, quando si cerca di distinguere tra una foto di un gatto e una di un cane, il nostro cervello si concentra sulla forma unica, le texture e le caratteristiche facciali. Una CNN impara a cogliere questi stessi tipi di caratteristiche distintive. Anche per compiti di categorizzazione molto dettagliata, le CNN sono in grado di apprendere rappresentazioni di caratteristiche complesse direttamente dai pixel.

In questo post del blog, impareremo le Convolutional Neural Networks e come utilizzarle per costruire un classificatore di immagini con PyTorch.

 

Come Funzionano le Convolutional Neural Networks?

 

Le reti neurali convoluzionali (CNN) sono comunemente utilizzate per compiti di classificazione delle immagini. A un alto livello, le CNN contengono tre tipi principali di strati:

  1. Strati convoluzionali. Applicano filtri convoluzionali all’input per estrarre le caratteristiche. I neuroni in questi strati vengono chiamati filtri e catturano i modelli spaziali nell’input.
  2. Strati di pooling. Ridimensionano le mappe delle caratteristiche degli strati convoluzionali per consolidare le informazioni. Le strategie più comuni sono il max pooling e il average pooling.
  3. Strati completamente connessi. Prendono le caratteristiche ad alto livello dagli strati convoluzionali e di pooling come input per la classificazione. È possibile impilare più strati completamente connessi.

I filtri convoluzionali agiscono come rilevatori di caratteristiche, imparando ad attivarsi quando vedono tipi specifici di modelli o forme nell’immagine di input. Quando questi filtri vengono applicati all’intera immagine, producono mappe delle caratteristiche che evidenziano dove sono presenti determinate caratteristiche.

Ad esempio, un filtro potrebbe attivarsi quando vede linee verticali, producendo una mappa delle caratteristiche che mostra le linee verticali nell’immagine. L’applicazione di più filtri allo stesso input produce una pila di mappe delle caratteristiche, che catturano diversi aspetti dell’immagine.

   

Impilando più strati convoluzionali, una CNN può apprendere gerarchie di caratteristiche, costruendo da bordi e modelli semplici a forme e oggetti più complessi. Gli strati di pooling aiutano a consolidare le rappresentazioni delle caratteristiche e forniscono invarianza rispetto alle traslazioni.

Gli strati completamente connessi finali prendono queste rappresentazioni di caratteristiche apprese e le utilizzano per la classificazione. Per un compito di classificazione delle immagini, lo strato di output utilizza tipicamente una funzione di attivazione softmax per produrre una distribuzione di probabilità sulle classi.

In PyTorch, possiamo definire gli strati convoluzionali, di pooling e completamente connessi per costruire un’architettura CNN. Ecco un esempio di codice:

# Strati convoluzionali 
self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size)
self.conv2 = nn.Conv2d(in_channels, out_channels, kernel_size)

# Strato di pooling
self.pool = nn.MaxPool2d(kernel_size)

# Strati completamente connessi 
self.fc1 = nn.Linear(in_features, out_features)
self.fc2 = nn.Linear(in_features, out_features)

 

Poi possiamo addestrare la CNN sui dati delle immagini, utilizzando la retropropagazione e l’ottimizzazione. Gli strati convoluzionali e di pooling impareranno automaticamente rappresentazioni di caratteristiche efficaci, consentendo alla rete di ottenere una forte prestazione sui compiti di visione.

 

Iniziare con le CNN

 

In questa sezione, caricheremo CIFAR10 e costruiremo e addestreremo un modello di classificazione basato su CNN utilizzando PyTorch. Il dataset CIFAR10 fornisce immagini RGB 32×32 per dieci classi, il che è utile per testare modelli di classificazione delle immagini. Ci sono dieci classi etichettate con numeri interi da 0 a 9.

Nota: Il codice di esempio è la versione modificata del blog MachineLearningMastery.com.

Per prima cosa, utilizzeremo torchvision per scaricare e caricare il dataset CIFAR10. Utilizzeremo anche torchvision per trasformare sia i set di testing che di addestramento in tensori.

import torch
import torch.nn as nn
import torch.optim as optim
import torchvision

transform = torchvision.transforms.Compose(
    [torchvision.transforms.ToTensor()]
)

train = torchvision.datasets.CIFAR10(
    root="data", train=True, download=True, transform=transform
)

test = torchvision.datasets.CIFAR10(
    root="data", train=False, download=True, transform=transform
)

 

Scaricamento in corso https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz in data/cifar-10-python.tar.gz

100%|██████████| 170498071/170498071 [00:10<00:00, 15853600.54it/s]

Estrazione in corso di data/cifar-10-python.tar.gz in data
File già scaricati e verificati

 

Dopo di ciò, utilizzeremo un caricatore di dati e divideremo le immagini in batch. 

batch_size = 32
trainloader = torch.utils.data.DataLoader(
    train, batch_size=batch_size, shuffle=True
)
testloader = torch.utils.data.DataLoader(
    test, batch_size=batch_size, shuffle=True
)

 

Per visualizzare l’immagine in un singolo batch di immagini, useremo la funzione di utilità matplotlib e torchvision. 

from torchvision.utils import make_grid
import matplotlib.pyplot as plt

def show_batch(dl):
    for images, labels in dl:
        fig, ax = plt.subplots(figsize=(12, 12))
        ax.set_xticks([]); ax.set_yticks([])
        ax.imshow(make_grid(images[:64], nrow=8).permute(1, 2, 0))
        break
show_batch(trainloader)

 

Come possiamo vedere, abbiamo immagini di automobili, animali, aerei e barche. 

   

Successivamente, costruiremo il nostro modello CNN. Per fare ciò, dobbiamo creare una classe Python e inizializzare le convoluzioni, il maxpool e i layer completamente connessi. La nostra architettura ha 2 layer convoluzionali con pooling e layer lineari. 

Dopo l’inizializzazione, non collegheremo tutti i layer in sequenza nella funzione forward. Se sei nuovo in PyTorch, dovresti leggere Interpretable Neural Networks with PyTorch per capire ogni componente in dettaglio. 

class CNNModel(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(3, 32, kernel_size=(3,3), stride=1, padding=1)
        self.act1 = nn.ReLU()
        self.drop1 = nn.Dropout(0.3)
 
        self.conv2 = nn.Conv2d(32, 32, kernel_size=(3,3), stride=1, padding=1)
        self.act2 = nn.ReLU()
        self.pool2 = nn.MaxPool2d(kernel_size=(2, 2))
 
        self.flat = nn.Flatten()
 
        self.fc3 = nn.Linear(8192, 512)
        self.act3 = nn.ReLU()
        self.drop3 = nn.Dropout(0.5)
 
        self.fc4 = nn.Linear(512, 10)
 
    def forward(self, x):
        # input 3x32x32, output 32x32x32
        x = self.act1(self.conv1(x))
        x = self.drop1(x)
        # input 32x32x32, output 32x32x32
        x = self.act2(self.conv2(x))
        # input 32x32x32, output 32x16x16
        x = self.pool2(x)
        # input 32x16x16, output 8192
        x = self.flat(x)
        # input 8192, output 512
        x = self.act3(self.fc3(x))
        x = self.drop3(x)
        # input 512, output 10
        x = self.fc4(x)
        return x

 

Ora inizieremo il nostro modello, impostiamo la funzione di loss e l’ottimizzatore. 

model = CNNModel()
loss_fn = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)

 

Nella fase di addestramento, addestreremo il nostro modello per 10 epoche.

  1. Stiamo utilizzando la funzione forward del modello per un passaggio in avanti, quindi un passaggio all’indietro utilizzando la funzione di perdita, e infine aggiornando i pesi. Questo passaggio è quasi simile in tutti i tipi di modelli di reti neurali.
  2. Dopo di ciò, stiamo utilizzando un caricatore di dati di test per valutare le prestazioni del modello alla fine di ogni epoca.
  3. Calcolando l’accuratezza del modello e stampando i risultati.
n_epochs = 10
for epoch in range(n_epochs):
    for i, (images, labels) in enumerate(trainloader):
        # Passaggio in avanti
        outputs = model(images)
        loss = loss_fn(outputs, labels)

        # Passaggio all'indietro e ottimizzazione
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
    corretto = 0
    totale = 0
    with torch.no_grad():
        for images, labels in testloader:
            outputs = model(images)
            _, predicted = torch.max(outputs.data, 1)
            totale += labels.size(0)
            corretto += (predicted == labels).sum().item()

    print('Epoch %d: Accuratezza: %d %%' % (epoch,(100 * corretto / totale)))

Il nostro modello semplice ha raggiunto un’accuratezza del 57%, che è bassa. Ma è possibile migliorare le prestazioni del modello aggiungendo più strati, eseguendolo per più epoche e ottimizzazione degli iperparametri.

Epoch 0: Accuratezza: 41 %
Epoch 1: Accuratezza: 46 %
Epoch 2: Accuratezza: 48 %
Epoch 3: Accuratezza: 50 %
Epoch 4: Accuratezza: 52 %
Epoch 5: Accuratezza: 53 %
Epoch 6: Accuratezza: 53 %
Epoch 7: Accuratezza: 56 %
Epoch 8: Accuratezza: 56 %
Epoch 9: Accuratezza: 57 %

Con PyTorch, non è necessario creare tutti i componenti delle reti neurali convoluzionali da zero in quanto sono già disponibili. Diventa ancora più semplice se si utilizza `torch.nn.Sequential`. PyTorch è progettato per essere modulare e offre una maggiore flessibilità nella costruzione, addestramento e valutazione delle reti neurali.

Conclusioni

In questo post abbiamo esplorato come costruire e addestrare una rete neurale convoluzionale per la classificazione delle immagini utilizzando PyTorch. Abbiamo coperto i componenti principali delle architetture CNN – strati convoluzionali per l’estrazione delle caratteristiche, strati di pooling per il downsampling e strati completamente connessi per la previsione.

Spero che questo post abbia fornito una panoramica utile dell’implementazione delle reti neurali convoluzionali con PyTorch. Le CNN sono un’architettura fondamentale nell’apprendimento approfondito per la visione artificiale e PyTorch ci offre la flessibilità di costruire, addestrare e valutare rapidamente questi modelli.

Abid Ali Awan (@1abidaliawan) è un professionista certificato di scienza dei dati che ama costruire modelli di apprendimento automatico. Attualmente si concentra sulla creazione di contenuti e sulla scrittura di blog tecnici su tecnologie di apprendimento automatico e scienza dei dati. Abid ha conseguito una laurea magistrale in gestione della tecnologia e una laurea triennale in ingegneria delle telecomunicazioni. La sua visione è quella di sviluppare un prodotto di intelligenza artificiale utilizzando una rete neurale grafica per gli studenti che lottano con disturbi mentali.