Ich habe lange Zeit Deep Learning-Programme nur in Keras geschrieben, aber jetzt muss ich in PyTorch schreiben. Nach dem Studium habe ich versucht, etwas zu erstellen, das am Beispiel von MNIST funktioniert.
[Korrekturgeschichte] -Flatten () und Softmax () werden jetzt im Modell verwendet
Vorerst wird es zunächst ein Tutorial sein, daher habe ich von Anfang an mit PyTorch Tutorial begonnen.
Dies ist jedoch sehr schwer zu verstehen. Ich konnte "Autograd" nicht sinnlich erfassen und meine Motivation sank auf weniger als 10%.
Ich denke, es wäre besser gewesen, mit "Was ist torch.nn wirklich?" zu beginnen, als von vorne zu beginnen. ..
Ich hatte so ein Gefühl, also begann ich mit dem Tutorial und kaufte ein Buch. Nachdem ich verschiedene Dinge recherchiert hatte, wählte ich die folgenden zwei Bücher.
Ich werde dies sorgfältig lesen, während ich es kopiere.
Es ist also zunächst MNIST, oder? Extrahieren Sie unter Bezugnahme auf PyTorch-Code nur die erforderlichen Teile und ändern Sie sie, damit Sie sie verstehen können ** Ich versuchte zu.
Zur Zeit mache ich es mit Windows 10 + Anaconda + CUDA.
import
import torch
import torch.nn as nn
import torch.optim as optim
from torch.optim.lr_scheduler import StepLR
from torchvision import datasets, transforms
from torchsummary import summary
Im Grunde ist es immer noch ein Beispiel, aber ich habe "Fackelzusammenfassung" zur Bestätigung hinzugefügt. Leider kann es nicht mit conda installiert werden, deshalb habe ich es mit pip installiert. Außerdem stimmte die Version von torchvision nicht überein und ich konnte sie nicht über die GUI installieren. (Installiert mit conda)
seed = 1
epochs = 14
batch_size = 64
log_interval = 100
lr = 1.0
gamma = 0.7
In der Stichprobe war es ein Argument, aber ich habe nur die erforderlichen Variablen extrahiert und sie zu festen Werten gemacht. Der Wert ist die Standardnummer. (Ich habe nur log_interval geändert)
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(1, 32, kernel_size=3, stride=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1)
self.relu = nn.ReLU(inplace=True)
self.maxpool = nn.MaxPool2d(kernel_size=2)
self.dropout1 = nn.Dropout2d(0.25)
self.dropout2 = nn.Dropout2d(0.5)
self.flatten = nn.Flatten()
self.fc1 = nn.Linear(9216, 128)
self.fc2 = nn.Linear(128, 10)
self.softmax = nn.Softmax(dim=1)
def forward(self, x):
x = self.conv1(x)
x = self.relu(x)
x = self.conv2(x)
x = self.relu(x)
x = self.maxpool(x)
x = self.flatten(x)
x = self.fc1(x)
x = self.relu(x)
x = self.dropout1(x)
x = self.fc2(x)
x = self.relu(x)
x = self.dropout2(x)
output = self.softmax(x)
return output
Ich habe es so weit wie möglich zu einer internen Variablen mit \ _ \ _ init__ () gemacht. Der letzte ist Softmax ().
Ich habe auch darüber nachgedacht, das Modell mit der sequentiellen API zu schreiben, aber ich habe das Gefühl, dass ich darauf basierend damit herumspielen werde, also habe ich es als funktionale API belassen.
def train(model, loss_fn, device, train_loader, optimizer, epoch):
model.train()
for batch_idx, (data, target) in enumerate(train_loader):
data, target = data.to(device), target.to(device)
optimizer.zero_grad()
output = model(data)
loss = loss_fn(output, target)
loss.backward()
optimizer.step()
if batch_idx % log_interval == 0:
print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
epoch, batch_idx * len(data), len(train_loader.dataset),
100. * batch_idx / len(train_loader), loss.item()/len(data)))
Es ist im Grunde eine Probe. Die Verlustfunktion wird jetzt vom Anrufer festgelegt.
Ich mag den Mechanismus, die Epoche auf der Anruferseite zu drehen und den Stapel hier zu drehen, weil er leicht zu verstehen ist.
def test(model, loss_fn, device, test_loader):
model.eval()
test_loss = 0
correct = 0
with torch.no_grad():
for data, target in test_loader:
data, target = data.to(device), target.to(device)
output = model(data)
test_loss += loss_fn(output, target) # sum up batch loss
pred = output.argmax(dim=1, keepdim=True) # get the index of the max log-probability
correct += pred.eq(target.view_as(pred)).sum().item()
test_loss /= len(test_loader.dataset)
print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
test_loss, correct, len(test_loader.dataset),
100. * correct / len(test_loader.dataset)))
Wieder entschied ich mich, die Verlustfunktion auf der Anruferseite anzugeben.
Es scheint, dass PyTorch nicht das Konzept der "Vorhersage" hat, daher denke ich, dass der Code hier hilfreich sein wird, wenn Sie später auf die Verwendung des trainierten Modells schließen. (Ich habe den Inferenzcode noch nicht geschrieben)
view_as () ist zu bequem und ich bin überrascht.
torch.manual_seed(seed)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
Betten Sie zunächst einen zufälligen Startwert ein und geben Sie die Ausführungsumgebung (CUDA) an.
transform=transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.0,), (1.0,))
])
kwargs = {'batch_size': batch_size,
'num_workers': 1,
'pin_memory': True,
'shuffle': True}
dataset1 = datasets.MNIST('../data', train=True, download=True, transform=transform)
dataset2 = datasets.MNIST('../data', train=False, transform=transform)
train_loader = torch.utils.data.DataLoader(dataset1,**kwargs)
test_loader = torch.utils.data.DataLoader(dataset2, **kwargs)
Laden Sie dann den MNIST-Datensatz. Beim Lesen ist der Durchschnitt 0 und die Standardabweichung 1. (Ich habe dies aus dem Beispiel geändert)
Bereiten Sie jetzt einen Datenlader vor. Dieser ist sehr praktisch. Ich hoffe, dass dieser Typ die Daten erweitern wird. (Noch nicht untersucht)
Ich bin auch froh, dass die Zielvariable nicht im One-Hot-Format vorliegen muss.
model = Net().to(device)
summary(model, (1,28,28))
loss_fn = nn.CrossEntropyLoss()
optimizer = optim.Adadelta(model.parameters(), lr=lr)
scheduler = StepLR(optimizer, step_size=1, gamma=gamma)
Ich habe ein Modell erstellt und dessen Inhalt angezeigt. Fackelzusammenfassung, ausgezeichnet. Wer Keras mag, ist ein Muss. Ich kann nicht erleichtert sein, wenn ich das nicht sehe. Dieses Mal wird es übrigens so angezeigt.
----------------------------------------------------------------
Layer (type) Output Shape Param #
================================================================
Conv2d-1 [-1, 32, 26, 26] 320
ReLU-2 [-1, 32, 26, 26] 0
Conv2d-3 [-1, 64, 24, 24] 18,496
ReLU-4 [-1, 64, 24, 24] 0
MaxPool2d-5 [-1, 64, 12, 12] 0
Flatten-6 [-1, 9216] 0
Linear-7 [-1, 128] 1,179,776
ReLU-8 [-1, 128] 0
Dropout2d-9 [-1, 128] 0
Linear-10 [-1, 10] 1,290
ReLU-11 [-1, 10] 0
Dropout2d-12 [-1, 10] 0
Softmax-13 [-1, 10] 0
================================================================
Total params: 1,199,882
Trainable params: 1,199,882
Non-trainable params: 0
----------------------------------------------------------------
Input size (MB): 0.00
Forward/backward pass size (MB): 1.04
Params size (MB): 4.58
Estimated Total Size (MB): 5.62
----------------------------------------------------------------
Ich bin mit dem vertrauten Display zufrieden. Übrigens ist zu beachten, dass die Reihenfolge der Anordnung unterschiedlich ist. Da es die ganze Zeit war (Charge, Höhe, Breite, Kanal), habe ich das Gefühl, dass etwas nicht stimmt (Charge, Kanal, Höhe, Breite).
Vergessen Sie nicht, die Verlustfunktion vorzubereiten. Ich verwende CrossEntropyLoss () für das Modell Softmax ().
Danach entscheiden Sie den Optimierungsalgorithmus und wie die Lernrate angepasst werden soll. Es wäre schön, einen Mechanismus zur Änderung der Lernrate einfach integrieren zu können.
for epoch in range(1, epochs + 1):
train(model, loss_fn, device, train_loader, optimizer, epoch)
test(model, loss_fn, device, test_loader)
scheduler.step()
Ich werde mit der Epoche weiter lernen. Lernen → Auswertung → Anpassung der Lernrate Es ist sehr leicht zu verstehen.
torch.save(model.state_dict(), "mnist_cnn.pt")
model.load_state_dict(torch.load("mnist_cnn.pt"))
Als Bonus schrieb ich darüber, wie man das trainierte Modell speichert und lädt. Ich habe den Inhalt mit einem Binäreditor betrachtet, aber er war erfrischend.
Ich bin noch nicht damit vertraut, aber ich hatte das Gefühl, dass es die folgenden Funktionen hat.
Ich werde härter lernen!