-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtuts7optimization.py
162 lines (123 loc) · 5.95 KB
/
tuts7optimization.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# Optimizing Model Parameters
# Now that we have a model and data it's time to train,
# validate and test our model by optimizing its parameters on our data.
# Training a model is an iterative process; in each iteration the model
# makes a guess about the output, calculates the error in its guess (loss),
# collects the derivatives of the error with respect to its parameters (as we saw in the previous section),
# and optimizes these parameters using gradient descent.
# https://pytorch.org/tutorials/beginner/basics/optimization_tutorial.html
import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets
from torchvision.transforms import ToTensor
training_data = datasets.FashionMNIST(
root="data",
train=True,
download=True,
transform=ToTensor()
)
test_data = datasets.FashionMNIST(
root="data",
train=False,
download=True,
transform=ToTensor()
)
train_dataloader = DataLoader(training_data, batch_size=64)
test_dataloader = DataLoader(test_data, batch_size=64)
class NeuralNetwork(nn.Module):
def __init__(self):
super().__init__()
self.flatten = nn.Flatten()
self.linear_relu_stack = nn.Sequential(
nn.Linear(28*28, 512),
nn.ReLU(),
nn.Linear(512, 512),
nn.ReLU(),
nn.Linear(512, 10),
)
def forward(self, x):
x = self.flatten(x)
logits = self.linear_relu_stack(x)
return logits
model = NeuralNetwork()
# Hyperparameters
# Hyperparameters are adjustable parameters that let you control the model optimization process.
# Different hyperparameter values can impact model training and convergence rates.
# Learning Rate: how much to update models parameters at each batch/epoch.
# Smaller values yield slow learning speed, while large values may result in unpredictable behavior
# during training.
# Batch Size: the number of data samples propagated through the network before the parameters are updated.
# Number of Epochs: the number times to iterate over the dataset.
learning_rate = 1e-3
batch_size = 64
epochs = 5
# Optimization Loop
# Once we set our hyperparameters, we can then train and optimize our model with an optimizaiton loop.
# Each iteration of the optimization loop is called an epoch.
# Each epoch consists of two main parts:
# The Train Loop - iterate over the training dataset and try to converge to optimal parameters.
# The Validation / Test Loop - iterate over the test dataset to check if model performance is improving.
# Loss Function
# When presented with some training data, our untrained network is likely not to give the correct answer.
# Loss function measures the degree of dissimilarity of obtained result to the target value,
# and it is the loss function that we want to minimize during training.
# To calculate the loss we make a prediction using the inputs of our given data sample
# and compare it against the true data label value.
# We pass our model's output logits to nn.CrossEntropyLoss, which will normalize the logits and compute the prediction error.
# Initialize the loss function.
loss_fn = nn.CrossEntropyLoss()
# Optimizer
# Optimization is the process of adjusting model parameters to reduce model error in each training step.
# All optimization logic is encapsulate in the optimizer object. Here, we use the SGD optimizer.
# We initialize the optimizer by registering the model's parameters that need to be trained,
# and passing in the learning rate hyperparameter.
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)
# Training Loop
# Inside the training loop, optimization happens in three steps:
# Call optimizer.zero_grad() to reset the gradients of model parameters.
# Gradients by default add up; to prevent double-counting, we explicitly zero them at each iteration.
# Backpropagate the prediction loss with a call to loss.backward().
# PyTorch deposits the gradients of the loss w.r.t each parameter.
# Once we have our gradients, we call optimizer.step() to adjust the parameters by the gradients collected in the backward pass.
def train_loop(dataloader, model, loss_fn, optimizer):
size = len(dataloader.dataset)
# Set the model to training mode as it is required for batch normalization and dropout layers.
model.train()
for batch, (X, y) in enumerate(dataloader):
# Compute prediction and loss.
pred = model(X)
loss = loss_fn(pred, y)
# Backpropagation.
loss.backward()
optimizer.step()
optimizer.zero_grad()
if batch % 100 == 0:
loss, current = loss.item(), batch * batch_size + len(X)
print(f"loss: {loss:>7f} [{current: >5d}/{size:>5d}]")
def test_loop(dataloader, model, loss_fn):
# Set the model to evaluation mode, which is important for batch normalization and dropout layers.
model.eval()
size = len(dataloader.dataset)
num_batches = len(dataloader)
test_loss, correct = 0, 0
# Evaluating the model with torch.no_grad() ensures that no gradients are computed during test mode
# also serves to reduce unnecessary gradient computations and memory usage for tensors with requires_grad=True
with torch.no_grad():
for X, y in dataloader:
pred = model(X)
test_loss += loss_fn(pred, y).item()
correct += (pred.argmax(1) == y).type(torch.float).sum().item()
test_loss /= num_batches
correct /= size
print(f"Test Error: \n Accuracy: {(100*correct):>0.1f}%, Avg loss: {test_loss:>8f} \n")
# We initialize the loss function and optimizer, and pass it to train_loop and test_loop.
# Increase the number of epochs to track the model's improving performance.
loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)
epochs = 10
for t in range(epochs):
print(f"Epoch {t+1}\n------------------------------")
train_loop(train_dataloader, model, loss_fn, optimizer)
test_loop(test_dataloader, model, loss_fn)
print("Done!")