[PYTHON] Die CIFAR-10-Klassifizierung wurde in PyTorch in praktisch 60 Zeilen implementiert

Überblick

Ich habe Deep Learning noch nicht implementiert, daher möchte ich vorerst Deep Learning implementieren! Dies ist ein Artikel für diejenigen, die sagen.

Dieses Mal haben wir alles implementiert, vom Lesen von Bilddaten bis zur Ausgabe von Trainingsfehlern und Generalisierungsfehlern in einem einfachen Diagramm in 60 Zeilen.

"Tatsächlich" ist, wenn Sie keine Zeilenumbrüche oder Kommentaranweisungen berücksichtigen, um das Lesen des Codes zu erleichtern, und der tatsächliche Code etwa 100 Zeilen umfasst.

** Ich werde den vollständigen Code am Ende des Artikels einfügen **

Prozessablauf

Grob gesagt ist der Fluss wie folgt.

Werfen wir einen Blick auf den Quellcode.

Was zu importieren

Lassen Sie uns zuerst die Bibliothek usw. importieren, die dieses Mal zuerst verwendet wurde.

test.py


import torch
import numpy as np
import torch.nn as nn
from torch import optim
import torch.nn.init as init
import torchvision.transforms as transforms
from torchvision import models
from torch.utils.data import Dataset,DataLoader
import torchvision.datasets as dsets
import matplotlib.pyplot as plt

Allein darin gibt es 10 Zeilen (lacht)

Datenaufbereitung

Die Bilddaten verwenden einen bekannten Datensatz namens CIFAR-10.

10 bedeutet, dass es 10 Klassen gibt, sodass 50.000 Trainingsbilder (5.000 für jede Klasse) und 10.000 Testbilder (1000 für jede Klasse) erstellt werden.

Sie können CIFAR-10 wie folgt laden.

test.py


#Bilder laden
batch_size = 100

train_data = dsets.CIFAR10(root='./tmp/cifar-10', train=True, download=False, transform=transforms.Compose([transforms.RandomHorizontalFlip(p=0.5), transforms.ToTensor(),transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5]), transforms.RandomErasing(p=0.5, scale=(0.02, 0.33), ratio=(0.3, 3.3), value=0, inplace=False)]))

train_loader = DataLoader(train_data,batch_size=batch_size,shuffle=True)

test_data = dsets.CIFAR10(root='./tmp/cifar-10', train=False, download=False, transform=transforms.Compose([transforms.ToTensor(),transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])]))

test_loader = DataLoader(test_data,batch_size=batch_size,shuffle=False)

Setzen Sie zum ersten Mal download = True. Der CIFAR-10-Datensatz wird heruntergeladen.

Es gibt einen langen Punkt mit transform = transforms.Compose ([...]), aber dies ist ein Element, um die Bilddaten auf verschiedene Arten zu verarbeiten.

--RandomHorizonalFlip: Drehen Sie das Bild nach links und rechts

Ich fühle mich gesagt. Dies erleichtert die Berechnung und verhindert das Überlernen durch Datenerweiterung.

Es gibt viele andere Transformationen. Weitere Informationen finden Sie unter hier.

Überprüfen Sie, ob eine GPU verwendet werden kann

Überprüfen Sie vor dem Definieren des Modells, ob es mit der GPU berechnet werden kann. Es wird empfohlen, die GPU zu verwenden, da diese um ein Vielfaches schneller ist.

test.py


device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(device)

Wenn die GPU verwendet werden kann, wird sie als cuda ausgegeben, und wenn nur die CPU verwendet werden kann, wird sie als CPU ausgegeben.

Modelldefinition

Es ist ein Modell, das für tiefes Lernen unerlässlich ist, aber jetzt können Sie mit hervorragenden Modellen umgehen, ohne selbst über das Modell nachdenken zu müssen.

Dieses Mal werden wir ein Modell namens Resnet verwenden.

test.py


model_ft = models.resnet50(pretrained=True)
model_ft.fc = nn.Linear(model_ft.fc.in_features, 10)
net = model_ft.to(device)

Mit models.resnet50 (pretrained = True) können Sie die trainierten Modelle von Resnet verwenden. Es ist einfach ...

Übrigens, wenn Sie pretrained = False setzen, können Sie Resnet verwenden, das Sie noch nicht gelernt haben. Es wird jedoch empfohlen, es auf True zu setzen, da die Lernzeit lang ist.

Die zweite Zeile hat eine Ausgabeschicht von 10. Es kann 40 oder 100 sein.

In der dritten Zeile wird das Modell einer Variablen namens net zugewiesen. Wenn Sie in .to (Gerät) eine GPU verwenden können, wird diese von der GPU berechnet (Verschiedenes).

Definition der Verlustfunktion / Optimierungsmethode

Damit das Modell lernen kann, muss die Verlustfunktion einen Fehler aus der richtigen Antwort ergeben. Die Methode zur Fehlerreduzierung ist die Optimierung.

Hier verwenden wir Kreuzentropie für die Verlustfunktion und SGD für den Optimierungsalgorithmus.

test.py


criterion = nn.CrossEntropyLoss()

optimizer = optim.SGD(net.parameters(),lr=0.01,momentum=0.9,weight_decay=0.00005)

lr ist die Lernrate, die nicht zu groß oder zu klein sein kann. Hier ist es auf 0,01 eingestellt.

weight_decay wird als "Gewichtsabschwächung" bezeichnet und ist auch eine der Regularisierungsmethoden, um ein Überlernen zu verhindern.

Lernen / Denken

Jetzt, da wir bereit sind, treten wir in die Lern- / Argumentationsphase ein.

test.py


loss,epoch_loss,count = 0,0,0
acc_list = []
loss_list = []
for i in range(50):
  
  #Lerne von hier
  net.train()
  
  for j,data in enumerate(train_loader,0):
    optimizer.zero_grad()

    #1:Trainingsdaten lesen
    inputs,labels = data
    inputs = inputs.to(device)
    labels = labels.to(device)

    #2:Berechnung
    outputs = net(inputs)

    #3:Finden Sie den Fehler
    loss = criterion(outputs,labels)

    #4:Aus Fehlern lernen
    loss.backward()
    optimizer.step()

    epoch_loss += loss
    count += 1
    print('%d: %.3f'%(j+1,loss))

  print('%depoch:mean_loss=%.3f\n'%(i+1,epoch_loss/count))
  loss_list.append(epoch_loss/count)

  epoch_loss = 0
  count = 0
  correct = 0
  total = 0
  accuracy = 0.0

  #Von hier abgeleitet
  net.eval()
 
  for j,data in enumerate(test_loader,0):

    #Bereiten Sie die Testdaten vor
    inputs,labels = data
    inputs = inputs.to(device)
    labels = labels.to(device)

    #Berechnung
    outputs = net(inputs)

    #Finden Sie den vorhergesagten Wert
    _,predicted = torch.max(outputs.data,1)

    #Berechnen Sie die Genauigkeit
    correct += (predicted == labels).sum()
    total += batch_size

  accuracy = 100.*correct / total
  acc_list.append(accuracy)

  print('epoch:%d Accuracy(%d/%d):%f'%(i+1,correct,total,accuracy))
  torch.save(net.state_dict(),'Weight'+str(i+1))

Es ist ein bisschen lang.

Die Lernphase ist von net.train () bis vor net.eval () und die Inferenzphase ist nach net.eval ().

Lernphase

Im obigen Code ist die Lernphase

  1. Lesen Sie die Trainingsdaten
  2. Berechnen
  3. Ermitteln Sie die Differenz zwischen dem vorhergesagten und dem tatsächlichen Wert
  4. Lernen Sie aus dem Fehler 3

Es ist ein Fluss geworden.

Bilder werden von batch_size (← definiert in „Datenaufbereitung“) in eine Schleife der for-Anweisung geladen. Die for-Anweisung endet, wenn alle Trainingsbilder geladen sind.

(Beispiel) Wenn 50.000 Lerndaten vorhanden sind und die Stapelgröße 100 beträgt, beträgt die Anzahl der Schleifen 500.

Inferenzphase

Im obigen Code ist die Inferenzphase

  1. Testdaten lesen
  2. Berechnen
  3. Finden Sie den vorhergesagten Wert
  4. Finden Sie die Genauigkeit (richtige Antwortrate)

Es ist ein Fluss geworden.

1 und 2 sind die gleichen wie beim Lernen.

In 3 wird der vorhergesagte Wert berechnet. Es ist wie "Dieses Bild ist Klasse 5!" Tatsächlich ist der bei der Berechnung von 2 erhaltene Wert ** die Wahrscheinlichkeit, dass das gelesene Bild in jede Klasse klassifiziert wird **.

Wenn Sie beispielsweise ein Bild lesen und [0,01,0,04,0,95] ausgeben,

Die Wahrscheinlichkeit, Klasse 1 zu sein, beträgt 0,01 (1%) Die Wahrscheinlichkeit, Klasse 2 zu sein, beträgt 0,04 (4%) Die Wahrscheinlichkeit, Klasse 3 zu sein, beträgt 0,95 (95%)

Es bedeutet das.

In diesem Fall ist der vorhergesagte Wert Klasse 3.

torch.save (net.state_dict (), 'Weight' + str (i + 1)) kann die gelernten Gewichte speichern.

Grafikausgabe

In der Lern- / Inferenzphase wurde eine Liste mit den Namen acc_list und loss_list definiert. In dieser Liste werden jedoch der Trainingsfehler und die Genauigkeit für jede Epoche gespeichert.

Gehen Sie wie folgt vor, um dies grafisch darzustellen:

test.py


plt.plot(acc_list)
plt.show(acc_list)
plt.plot(loss_list)
plt.show(loss_list)

Dies ist die einfachste Grafikausgabemethode.

Übrigens ist die Grafikausgabe, wenn dieser Code ausgeführt wird, wie folgt. Richtigkeit acc_short.png Trainingsfehler loss_short.png

Die Genauigkeit sinkt für einen Moment um 8,9 Epochen. Die Genauigkeit beträgt weniger als 88%.

Schließlich

Diesmal war es ein Artikel über die Implementierung einer Reihe von Deep-Learning-Flows in 60 Zeilen.

** Natürlich ist mehr Einfallsreichtum erforderlich, um die Genauigkeit zu verbessern **, aber wenn Sie die Infrastruktur vorerst implementieren möchten, lesen Sie bitte.

Zum Schluss werde ich den gesamten Code hier einfügen.

test.py


import torch
import numpy as np
import torch.nn as nn
from torch import optim
import torch.nn.init as init
import torchvision.transforms as transforms
from torchvision import models
from torch.utils.data import Dataset,DataLoader
import torchvision.datasets as dsets
import matplotlib.pyplot as plt

#Bilder laden
batch_size = 100
train_data = dsets.CIFAR10(root='./tmp/cifar-10', train=True, download=False, transform=transforms.Compose([transforms.RandomHorizontalFlip(p=0.5), transforms.ToTensor(),transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5]), transforms.RandomErasing(p=0.5, scale=(0.02, 0.33), ratio=(0.3, 3.3), value=0, inplace=False)]))
train_loader = DataLoader(train_data,batch_size=batch_size,shuffle=True)
test_data = dsets.CIFAR10(root='./tmp/cifar-10', train=False, download=False, transform=transforms.Compose([transforms.ToTensor(),transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])]))
test_loader = DataLoader(test_data,batch_size=batch_size,shuffle=False)

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(device)

model_ft = models.resnet50(pretrained=True)
model_ft.fc = nn.Linear(model_ft.fc.in_features, 10)
net = model_ft.to(device)

criterion = nn.CrossEntropyLoss()

optimizer = optim.SGD(net.parameters(),lr=0.01,momentum=0.9,weight_decay=0.00005)

loss, epoch_loss, count = 0, 0, 0
acc_list = []
loss_list = []

#Training / Argumentation
for i in range(50):
  
  #Lerne von hier
  net.train()
  
  for j,data in enumerate(train_loader,0):
    optimizer.zero_grad()

    #1:Trainingsdaten lesen
    inputs,labels = data
    inputs = inputs.to(device)
    labels = labels.to(device)

    #2:Berechnung
    outputs = net(inputs)

    #3:Finden Sie den Fehler
    loss = criterion(outputs,labels)

    #4:Aus Fehlern lernen
    loss.backward()
    optimizer.step()

    epoch_loss += loss
    count += 1
    print('%d: %.3f'%(j+1,loss))

  print('%depoch:mean_loss=%.3f\n'%(i+1,epoch_loss/count))
  loss_list.append(epoch_loss/count)

  epoch_loss, count = 0, 0
  correct,total = 0, 0
  accuracy = 0.0

  #Von hier abgeleitet
  net.eval()
 
  for j,data in enumerate(test_loader,0):

    #Bereiten Sie die Testdaten vor
    inputs,labels = data
    inputs = inputs.to(device)
    labels = labels.to(device)

    #Berechnung
    outputs = net(inputs)

    #Finden Sie den vorhergesagten Wert
    _,predicted = torch.max(outputs.data,1)

    #Berechnen Sie die Genauigkeit
    correct += (predicted == labels).sum()
    total += batch_size

  accuracy = 100.*correct / total
  acc_list.append(accuracy)

  print('epoch:%d Accuracy(%d/%d):%f'%(i+1,correct,total,accuracy))
  torch.save(net.state_dict(),'Weight'+str(i+1))

plt.plot(acc_list)
plt.show(acc_list)
plt.plot(loss_list)
plt.show(loss_list)

Recommended Posts

Die CIFAR-10-Klassifizierung wurde in PyTorch in praktisch 60 Zeilen implementiert
[PyTorch] Bildklassifizierung von CIFAR-10
Implementiert in Python PRML Kapitel 4 Klassifizierung nach Perceptron-Algorithmus
SimRank in Python implementiert
Hard-Swish mit Keras implementiert
Shiritori in Python implementiert