Polkadot Prisanalys 13 sep

Convolutional Neural Network – PyTorch-implementering på CIFAR-10 Dataset

Källnod: 1866263

Denna artikel publicerades som en del av Data Science Blogathon

Beskrivning

Cifar 10 | Konvolutionella neurala nätverk pytorch
                                    Bild 1

Konvolutionella neurala nätverk, även kallade ConvNets, introducerades först på 1980 -talet av Yann LeCun, en datavetenskaplig forskare som arbetade i bakgrunden. LeCun byggde på arbetet från Kunihiko Fukushima, en japansk forskare, ett grundläggande nätverk för bildigenkänning.

Den gamla versionen av CNN, kallad LeNet (efter LeCun), kan se handskrivna siffror. CNN hjälper till att hitta pinkoder från posten. Men trots deras expertis höll ConvNets sig nära datorseende och artificiell intelligens eftersom de stod inför ett stort problem: De kunde inte skala mycket. CNN: er kräver mycket data och integrerar resurser för att fungera bra för stora bilder.

På den tiden var denna metod endast tillämplig på bilder med låg upplösning. Pytorch är ett bibliotek som kan utföra djupinlärningsoperationer. Vi kan använda detta för att utföra konvolutionella neurala nätverk. Konvolutionella neurala nätverk innehåller många lager av artificiella neuroner. Syntetiska neuroner, komplexa simuleringar av biologiska motsvarigheter, är matematiska funktioner som beräknar den viktade massan av flera ingångar och produktvärdesaktivering.

Konvolutionella neurala nätverk pytorch
Bild 2

Bilden ovan visar oss en CNN-modell som tar in en sifferliknande bild av 2 och ger oss resultatet av vilken siffra som visades i bilden som ett tal. Vi kommer att diskutera i detalj hur vi får detta i den här artikeln.

CIFAR-10 är en dataset som har en samling bilder av 10 olika klasser. Denna datamängd används i stor utsträckning för forskningsändamål för att testa olika maskininlärningsmodeller och särskilt för datorsynproblem. I den här artikeln kommer vi att försöka bygga en Neural-nätverksmodell med hjälp av Pytorch och testa den på CIFAR-10-datauppsättningen för att kontrollera vilken precision av förutsägelse som kan erhållas.

Importera PyTorch-biblioteket 

importera numpy som np importera pandor som pd
import fackla import fackla.nn.funktionell som F från fackla visning import datamängder, transformerar från fackla import nn import matplotlib.pyplot som plt import numpy som np import seaborn som sns #från tqdm.notebook import tqdm från tqdm import tqdm

I det här steget importerar vi de nödvändiga biblioteken. Vi kan se att vi använder NumPy för numeriska operationer och pandor för dataramoperationer. Fackelbiblioteket används för att importera Pytorch.

Pytorch har en nn -komponent som används för abstraktion av maskininlärningsoperationer och funktioner. Detta importeras som F. Torchvision-biblioteket används så att vi kan importera CIFAR-10-datasetet. Detta bibliotek har många bilddatauppsättningar och används ofta för forskning. Transformerna kan importeras så att vi kan ändra storleken på bilden till lika stor storlek för alla bilder. Tqdm används för att vi ska kunna hålla koll på framstegen under träning och används för visualisering.

Läs den obligatoriska datauppsättningen

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

När vi läser datamängden kan vi se olika etiketter som groda, lastbil, rådjur, bil, etc.

Analyserar data med PyTorch

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

Produktion:

Antal poäng: 50000 Antal funktioner: 2 funktioner: ['id' 'etikett'] Antal unika värden id: 50000 etikett: 10

I detta steg analyserar vi datauppsättningen och ser att våra tågdata har cirka 50000 rader med sitt ID och tillhörande etikett. Det finns totalt 10 klasser som i namnet CIFAR-10.

Hämta valideringsinställningen med PyTorch

från torch.utils.data importera random_split val_size = 5000 train_size = len (dataset) - val_size train_ds, val_ds = random_split (dataset, [train_size, val_size]) len (train_ds), len (val_ds)

Detta steg är detsamma som träningssteget, men vi vill dela upp data i tåg- och valideringsuppsättningar.

(45000, 5000)
från 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 datalastare som kan hjälpa oss att ladda den nödvändiga informationen genom att kringgå olika parametrar, till exempel arbetarnummer eller batchstorlek.

Definiera nödvändiga funktioner

@torch.no_grad () def precision (utgångar, etiketter): _, preds = torch.max (utgångar, 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) returförlust, accu def validation_step (self, batch): bilder, labels = batch out = self (images) # Generera förutsägelser förlust = F.cross_entropy (out, labels) # Beräkna förlust acc = precision (out, labels) # Beräkna noggrannhetsavkastning {'Loss': loss.detach (), 'Accuracy': acc} def validation_epoch_end (self, outputs): batch_losses = [x ['Loss'] för x in output] epoch_loss = torch.stack (batch_losses ) .mean () # Kombinera förluster batch_accs = [x ['' Noggrannhet '] för x i utgångar] epoch_acc = torch.stack (batch_accs) .mean () # Kombinera noggrannheter returnera {' Förlust ': epoch_loss.item (),' Noggrannhet ': epoch_acc.item ()} def epoch_end (self, epoch, result): pr int ("Epok:", epok + 1) print (f'Train Accuracy: {result ["train_accuracy"]*100: .2f}% Validation Accuracy: {result ["Accuracy"]*100: .2f}% ' ) print (f'Train Loss: {result ["train_loss"] :. 4f} Valideringsförlust: {result ["Loss"] :. 4f} ')

Som vi kan se här har vi använt klassimplementering av ImageClassification och det krävs en parameter som är nn.Module. Inom denna klass kan vi implementera de olika funktionerna eller olika steg som utbildning, validering etc. Funktionerna här är enkla pythonimplementeringar.

Utbildningssteget tar bilder och etiketter i omgångar. vi använder korsentropi för förlustfunktion och beräknar förlusten och returnerar förlusten. Detta liknar valideringssteget som vi kan se i funktionen. Epokändarna kombinerar förluster och noggrannheter och slutligen skriver vi ut noggrannheterna och förlusterna.

Implementering av konvolutionell neural nätverksmodul

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, steg = 1, stoppning = 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)

Detta är den viktigaste delen av implementering av neurala nätverk. Genomgående använder vi nn -modulen som vi importerade från facklan. Som vi kan se på första raden är Conv2d en modul som hjälper till att implementera ett konvolutionellt neuralt nätverk. Den första parametern 3 här representerar att bilden är färgad och i RGB -format. Om det var en gråtonbild hade vi gått för 1.

32 är storleken på den ursprungliga utgångskanalen och när vi går till nästa conv2d -lager skulle vi ha denna 32 som ingångskanal och 64 som utgångskanal.

Den tredje parametern på den första raden kallas kärnstorlek och den hjälper oss att ta hand om de filter som används. Vaddering är den sista parametern.

Konvolutionsoperationen är ansluten till ett aktiveringsskikt och Relu här. Efter två Conv2d-lager har vi en maximal poolning av storlek 2 * 2. Värdet som kommer ut från detta är batch-normaliserat för stabilitet och för att undvika internt kovariatskifte. Dessa operationer upprepas med fler lager för att fördjupa nätverket och minska storleken. Slutligen plattar vi ut lagret så att vi kan bygga ett linjärt lager för att kartlägga värdena till 10 värden. Sannolikheten för varje neuron av dessa 10 neuroner kommer att avgöra vilken klass en viss bild tillhör baserat på den maximala sannolikheten.

Träna 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 = Ingen historik = [] optimizer = torch.optim.Adam (model.parameters (), learning_rate, weight_decay = 0.0005) för epok inom intervall (epoker): # Training Phase model.train ( ) train_losses = [] train_accuracy = [] för 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 () # Valideringsfasresultat = utvärdera (modell, val_loader) resultat ['train_loss'] = torch.stack (train_losses) .mean (). item () result ['train_accuracy'] = torch.stack (train_accuracy). mean (). item () model.epoch_end (epok, resultat) if (best_valid == None eller best_valid
historik = passform (modell, tåg_dl, val_dl)

Detta är ett grundläggande steg för att träna vår modell för att få det önskade resultatet. passformsfunktionen här passar tåg- och Val -data med modellen vi skapade. Passningsfunktionen tar inledningsvis en lista som kallas historia som tar hand om iterationsdata för varje epok. Vi kör en for loop så att vi kan iterera över varje epok. För varje sats ser vi till att vi visar framstegen med tqdm. Vi kallar utbildningssteget som vi genomförde tidigare och beräknar noggrannhet och förlust. Gå för bakåtförökning och köroptimering som vi definierade tidigare. När vi väl har gjort detta håller vi koll på vår lista och funktionerna hjälper oss att skriva ut detaljer och framsteg.

Utvärderingsfunktionen, å andra sidan, använder funktionen eval, och för varje steg tar vi den batch som laddats från datalastaren och utmatningen beräknas. Värdet överförs sedan till valideringsepokens slut som vi definierade tidigare och respektive värde returneras.

Plotta resultaten

I detta steg kommer vi att visualisera noggrannheten mot varje epok. Vi kan observera att i takt med att epoken ökar kommer systemets noggrannhet att öka och på samma sätt minskar förlusten. Den röda linjen här indikerar framsteg för träningsdata och blå för validering. Vi kan se att det har varit en bra överanpassning i våra resultat eftersom träningsdata är bättre än valideringsresultatet och på samma sätt vid förlust. Efter 10 epoker verkar tågdata kringgå 90% noggrannhet men har en förlust på cirka 0.5. Testdata kommer runt 81% och förlusterna är nära 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 ('epok') plt.ylabel ('precision') plt.legend (['Training', 'Validation']) plt.title ('Exakthet vs. antal epoker') ; plot_accuracies (historik)
Noggrannhetsdiagram
def plot_losses (historik): train_losses = [x.get ('train_loss') för x i historien] val_losses = [x ['förlust'] för x i historia] plt.plot (train_losses, '-bx') plt.plot (val_losses, '-rx') plt.xlabel ('epoke') plt.ylabel ('loss') plt.legend (['Training', 'Validation']) plt.title ('Förlust vs. antal epoker '); plot_losses (historik)

test_dataset = ImageFolder (data_dir+'/test', transform = ToTensor ()) test_loader = DeviceDataLoader (DataLoader (test_dataset, batch_storlek), enhet) resultat = utvärdera (final_model, test_loader) print (f'Testnoggrannhet: {resultat ["Noggrannhet" ]*100: .2f}%')
Testnoggrannhet: 81.07%

Vi kan se att vi slutar med en noggrannhet på 81.07%.

Slutsats:

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

Om mig: Jag är en forskarstudent som är intresserad av djupinlärning och naturligt språkbearbetning och för närvarande fortsätter efter examen i artificiell intelligens.

Image Source

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

Anslut mig gärna på:

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

Media som visas i denna artikel ägs inte av Analytics Vidhya och används efter författarens gottfinnande.

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

Tidsstämpel:

Mer från Analys Vidhya