Polkadot -prisanalyse 13. sep

Konvolusjonelt neuralt nettverk-PyTorch-implementering på CIFAR-10 datasett

Kilde node: 1866263

Denne artikkelen ble publisert som en del av Data Science Blogathon

Introduksjon

Cifar 10 | Konvolusjonelle nevrale nettverk pytorch
                                    Bilde 1

Konvolusjonelle nevrale nettverk, også kalt ConvNets, ble først introdusert på 1980 -tallet av Yann LeCun, en datavitenskapelig forsker som jobbet i bakgrunnen. LeCun bygde på arbeidet til Kunihiko Fukushima, en japansk forsker, et grunnleggende nettverk for bildegjenkjenning.

Den gamle versjonen av CNN, kalt LeNet (etter LeCun), kan se håndskrevne sifre. CNN hjelper til med å finne pinkoder fra posten. Men til tross for deres ekspertise, holdt ConvNets seg i nærheten av datasyn og kunstig intelligens fordi de sto overfor et stort problem: De kunne ikke skalere mye. CNN -er krever mye data og integrerer ressurser for å fungere godt for store bilder.

På den tiden var denne metoden bare gjeldende for bilder med lav oppløsning. Pytorch er et bibliotek som kan utføre dype læringsoperasjoner. Vi kan bruke dette til å utføre konvolusjonelle nevrale nettverk. Konvolusjonelle nevrale nettverk inneholder mange lag med kunstige nevroner. Syntetiske nevroner, komplekse simuleringer av biologiske motstykker, er matematiske funksjoner som beregner den veide massen til flere innganger og aktivering av produktverdier.

Konvolusjonelle nevrale nettverk pytorch
Bilde 2

Bildet ovenfor viser oss en CNN-modell som tar inn et sifferlignende bilde av 2 og gir oss resultatet av hvilket siffer som ble vist i bildet som et tall. Vi vil diskutere i detalj hvordan vi får dette til i denne artikkelen.

CIFAR-10 er et datasett som har en samling bilder av 10 forskjellige klasser. Dette datasettet er mye brukt til forskningsformål for å teste forskjellige maskinlæringsmodeller og spesielt for problemer med datasyn. I denne artikkelen vil vi prøve å bygge en nevral nettverksmodell ved hjelp av Pytorch og teste den på CIFAR-10-datasettet for å kontrollere hvilken nøyaktighet av prediksjon som kan oppnås.

Importerer PyTorch-biblioteket 

import numpy som np import pandaer som pd
import fakkel import fakkel.nn.funksjonell som F fra fakkelvisjon import datasett, transformerer fra fakkel import nn import matplotlib.pyplot som plt import numpy som np import seaborn som sns #frå tqdm. notatbok import tqdm fra tqdm import tqdm

I dette trinnet importerer vi de nødvendige bibliotekene. Vi kan se at vi bruker NumPy for numeriske operasjoner og pandaer for datarammeoperasjoner. Fakkelbiblioteket brukes til å importere Pytorch.

Pytorch har en nn -komponent som brukes til abstraksjon av maskinlæringsoperasjoner og -funksjoner. Dette importeres som F. Torchvision-biblioteket brukes slik at vi kan importere CIFAR-10-datasettet. Dette biblioteket har mange bildedatasett og er mye brukt til forskning. Transformene kan importeres slik at vi kan endre størrelsen på bildet til samme størrelse for alle bildene. Tqdm brukes slik at vi kan holde oversikt over fremdriften under trening og brukes til visualisering.

Les det nødvendige datasettet

trainData = pd.read_csv ('cifar-10/trainLabels.csv') trainData.head ()

Når vi har lest datasettet, kan vi se forskjellige etiketter som frosken, lastebilen, hjorten, bilen, etc.

Analyserer dataene med PyTorch

print ("Number of points:", trainData.shape [0]) print ("Number of features:", trainData.shape [1]) print ("Features:", trainData.columns.values) print ("Number of Unique Values ​​") for col in trainData: print (col,": ", len (trainData [col] .unique ())) plt.figure (figsize = (12,8))

Utgang:

Antall poeng: 50000 Antall funksjoner: 2 Funksjoner: ['id' 'label'] Antall unike verdier id: 50000 label: 10

I dette trinnet analyserer vi datasettet og ser at togdataene våre har rundt 50000 rader med ID og tilhørende etikett. Det er totalt 10 klasser som i navnet CIFAR-10.

Får valideringssettet ved hjelp av PyTorch

fra torch.utils.data import random_split val_size = 5000 train_size = len (datasett) - val_size train_ds, val_ds = random_split (datasett, [train_size, val_size]) len (train_ds), len (val_ds)

Dette trinnet er det samme som treningstrinnet, men vi ønsker å dele dataene i tog- og valideringssett.

(45000, 5000)
fra torch.utils.data.dataloader import DataLoader batch_size = 64 train_dl = DataLoader (train_ds, batch_size, shuffle = True, num_workers = 4, pin_memory = True) val_dl = DataLoader (val_ds, batch_size, num_workers = 4, pin_memory = True)

Torch.utils har en datalaster som kan hjelpe oss med å laste inn nødvendige data ved å omgå forskjellige parametere, for eksempel arbeidernummer eller batchstørrelse.

Definere nødvendige funksjoner

@torch.no_grad () def nøyaktighet (outputs, labels): _, preds = torch.max (outputs, dim = 1) return torch.tensor (torch.sum (preds == labels) .item () / len (preds )) class ImageClassificationBase (nn.Module): def training_step (self, batch): images, labels = batch out = self (images) # Generate predictions loss = F.cross_entropy (out, labels) # Calculate loss accu = precision (out , etiketter) returtap, accu def validation_step (self, batch): bilder, labels = batch out = self (bilder) # Generer spådommer tap = F.cross_entropy (out, labels) # Beregn tap acc = nøyaktighet (out, labels) # Beregn nøyaktighetsavkastning {'Tap': loss.detach (), 'Accuracy': acc} def validation_epoch_end (self, outputs): batch_losses = [x ['Loss'] for x in output] epoch_loss = torch.stack (batch_losses ) .mean () # Kombiner tap batch_accs = [x ['Nøyaktighet'] for x i utganger] epoch_acc = torch.stack (batch_accs) .mean () # Kombiner nøyaktigheter returnerer {'Tap': epoch_loss.item (), ' Nøyaktighet ': epoch_acc.item ()} def epoch_end (self, epoch, result): pr int ("Epoke:", epoke + 1) print (f'Train Accuracy: {result ["train_accuracy"]*100: .2f}% Validation Accuracy: {result ["Accuracy"]*100: .2f}% ' ) print (f'Train Loss: {result ["train_loss"] :. 4f} Valideringstap: {result ["Loss"] :. 4f} ')

Som vi kan se her har vi brukt klasseimplementering av ImageClassification, og det tar en parameter som er nn.Module. Innenfor denne klassen kan vi implementere de forskjellige funksjonene eller forskjellige trinn som trening, validering, etc. Funksjonene her er enkle python -implementeringer.

Treningstrinnet tar bilder og etiketter i grupper. vi bruker kryssentropi for tapsfunksjon og beregner tapet og returnerer tapet. Dette ligner valideringstrinnet som vi kan se i funksjonen. Epokens ender kombinerer tap og nøyaktigheter, og til slutt skriver vi ut nøyaktighetene og tapene.

Implementering av konvolusjonell nevral nettverksmodul

class Cifar10CnnModel (ImageClassificationBase): def __init __ (self): super () .__ init __ () self.network = nn.Sequential (nn.Conv2d (3, 32, kernel_size = 3, padding = 1), nn.ReLU (), nn.Conv2d (32, 64, kernel_size = 3, stride = 1, padding = 1), nn.ReLU (), nn.MaxPool2d (2, 2), # output: 64 x 16 x 16 nn.BatchNorm2d (64) , nn.Conv2d (64, 128, kernel_size = 3, stride = 1, padding = 1), nn.ReLU (), nn.Conv2d (128, 128, kernel_size = 3, stride = 1, padding = 1), nn .ReLU (), nn.MaxPool2d (2, 2), # output: 128 x 8 x 8 nn.BatchNorm2d (128), nn.Conv2d (128, 256, kernel_size = 3, stride = 1, padding = 1), nn.ReLU (), nn.Conv2d (256, 256, kernel_size = 3, stride = 1, padding = 1), nn.ReLU (), nn.MaxPool2d (2, 2), # output: 256 x 4 x 4 nn.BatchNorm2d (256), nn.Flatten (), nn.Linear (256*4*4, 1024), nn.ReLU (), nn.Linear (1024, 512), nn.ReLU (), nn.Linear (512, 10)) def forward (self, xb): return self.network (xb)

Dette er den viktigste delen av implementering av nevrale nettverk. Gjennomgående bruker vi nn -modulen vi importerte fra fakkelen. Som vi kan se på den første linjen, er Conv2d en modul som hjelper til med å implementere et konvolusjonelt neuralt nettverk. Den første parameteren 3 her representerer at bildet er farget og i RGB -format. Hvis det var et gråtonebilde hadde vi gått for 1.

32 er størrelsen på den opprinnelige utgangskanalen, og når vi går for det neste conv2d -laget vil vi ha denne 32 som inngangskanal og 64 som utgangskanal.

Den tredje parameteren i den første linjen kalles kjernestørrelse, og den hjelper oss med å ta vare på filtrene som brukes. Polstring er den siste parameteren.

Konvolusjonsoperasjonen er koblet til et aktiveringslag og Relu her. Etter to Conv2d-lag har vi en maksimal pooling av størrelse 2 * 2. Verdien som kommer ut av dette er batch-normalisert for stabilitet og for å unngå internt kovariatskifte. Disse operasjonene gjentas med flere lag for å dypere nettverket og redusere størrelsen. Til slutt flater vi laget slik at vi kan bygge et lineært lag for å kartlegge verdiene til 10 verdier. Sannsynligheten for hvert nevron av disse 10 nevronene vil avgjøre hvilken klasse et bestemt bilde tilhører basert på maksimal sannsynlighet.

Tren modellen

@torch.no_grad () def evalu (model, data_loader): model.eval () outputs = [model.validation_step (batch) for batch in data_loader] return model.validation_epoch_end (outputs) def fit (model, train_loader, val_loader, epochs = 10, learning_rate = 0.001): best_valid = None history = [] optimizer = torch.optim.Adam (model.parameters (), learning_rate, weight_decay = 0.0005) for epoke i rekkevidde (epoker): # Training Phase model.train ( ) train_losses = [] train_accuracy = [] for batch i tqdm (train_loader): loss, accu = model.training_step (batch) train_losses.append (loss) train_accuracy.append (accu) loss.backward () optimizer.step () optimizer .zero_grad () # Valideringsfaseresultat = evaluere (modell, val_loader) resultat ['train_loss'] = torch.stack (train_losses) .mean (). item () result ['train_accuracy'] = torch.stack (train_accuracy). mean (). item () model.epoch_end (epoke, result) if (best_valid == None or best_valid
historie = passform (modell, tog_dl, val_dl)

Dette er et grunnleggende trinn for å trene modellen vår for å få det nødvendige resultatet. passform -funksjonen her vil passe til tog- og Val -dataene med modellen vi opprettet. Tilpassingsfunksjonen tar i utgangspunktet en liste kalt historie som tar seg av iterasjonsdataene for hver epoke. Vi kjører en for loop slik at vi kan iterere over hver epoke. For hver batch sørger vi for at vi viser fremdriften ved hjelp av tqdm. Vi kaller opplæringstrinnet vi implementerte før og beregner nøyaktighet og tap. Gå for bakoverspredning og kjør optimizer som vi definerte tidligere. Når vi gjør dette, holder vi oversikt over listen vår og funksjonene hjelper oss med å skrive ut detaljer og fremgang.

Evalueringsfunksjonen, derimot, bruker evalueringsfunksjonen, og for hvert trinn tar vi batchen lastet fra datalasteren, og utdata beregnes. Verdien sendes deretter til valideringsepoken som vi definerte tidligere, og den respektive verdien returneres.

Plotte resultatene

I dette trinnet vil vi visualisere nøyaktigheten mot hver epoke. Vi kan observere at etter hvert som epoken øker, fortsetter nøyaktigheten til systemet å øke og på samme måte fortsetter tapet å synke. Den røde linjen her indikerer fremdrift i treningsdata og blå for validering. Vi kan se at det har vært en god mengde overmontering i resultatene våre, da treningsdataene er ganske gode enn valideringsresultatet og tilsvarende i tilfelle tap. Etter 10 epoker ser det ut til at togdata omgår 90% nøyaktighet, men har et tap på rundt 0.5. Testdataene kommer rundt 81% og tapene er nær 0.2.

def plot_accuracies (history): Validation_accuracies = [x ['Accuracy'] for x in history] Training_Accuracies = [x ['train_accuracy'] for x in history] plt.plot (Training_Accuracies, '-rx') plt.plot (Validation_accuracies) , '-bx') plt.xlabel ('epoke') plt.ylabel ('nøyaktighet') plt.legend (['Training', 'Validation']) plt.title ('Nøyaktighet vs. antall epoker') ; plot_accuracies (historie)
Presisjonsplott
def plot_losses (historie): train_losses = [x.get ('train_loss') for x i historien] val_losses = [x ['tap'] for x i historien] plt.plot (train_losses, '-bx') plt.plot (val_losses, '-rx') plt.xlabel ('epoke') plt.ylabel ('loss') plt.legend (['Training', 'Validation']) plt.title ('Tap vs. Antall epoker '); plot_losses (historie)

test_dataset = ImageFolder (data_dir+'/test', transform = ToTensor ()) test_loader = DeviceDataLoader (DataLoader (test_dataset, batch_størrelse), enhet) resultat = evaluere (final_model, test_loader) print (f'Testnøyaktighet: {resultat ["Nøyaktighet" ]*100: .2f}%')
Testnøyaktighet: 81.07%

Vi kan se at vi ender med en nøyaktighet på 81.07%.

Konklusjon:

Bilde: https: //unsplash.com/photos/5L0R8ZqPZHk

Om meg: Jeg er en forskerstudent som er interessert i dybdelæring og naturlig språkbehandling og som for tiden fortsetter etter eksamen i kunstig intelligens.

Image Source

  1. Image 1: https://becominghuman.ai/cifar-10-image-classification-fd2ace47c5e8
  2. Bilde 2: https://www.analyticsvidhya.com/blog/2021/05/convolutional-neural-networks-cnn/

Ta gjerne kontakt med meg på:

  1.  Linkedin: https://www.linkedin.com/in/siddharth-m-426a9614a/
  2.  Github: https://github.com/Siddharth1698

Media vist i denne artikkelen eies ikke av Analytics Vidhya og brukes etter forfatterens skjønn.

Kilde: https://www.analyticsvidhya.com/blog/2021/09/convolutional-neural-network-pytorch-implementation-on-cifar10-dataset/

Tidstempel:

Mer fra Analytics Vidhya