9
9
* 2020-04-08: Initial coding
10
10
* 2021-03-24: Added more detailed comments also removed part of
11
11
check_accuracy which would only work specifically on MNIST.
12
-
12
+ * 2022-09-23: Updated with more detailed comments, docstrings to functions, and checked code still functions as intended.
13
13
"""
14
14
15
15
# Imports
27
27
# inheriting from nn.Module, this is the most general way to create your networks and
28
28
# allows for more flexibility. I encourage you to also check out nn.Sequential which
29
29
# would be easier to use in this scenario but I wanted to show you something that
30
- # "always" works.
30
+ # "always" works and is a general approach .
31
31
class NN (nn .Module ):
32
32
def __init__ (self , input_size , num_classes ):
33
+ """
34
+ Here we define the layers of the network. We create two fully connected layers
35
+
36
+ Parameters:
37
+ input_size: the size of the input, in this case 784 (28x28)
38
+ num_classes: the number of classes we want to predict, in this case 10 (0-9)
39
+
40
+ Returns:
41
+ None
42
+ """
33
43
super (NN , self ).__init__ ()
34
44
# Our first linear layer take input_size, in this case 784 nodes to 50
35
45
# and our second linear layer takes 50 to the num_classes we have, in
@@ -42,6 +52,12 @@ def forward(self, x):
42
52
x here is the mnist images and we run it through fc1, fc2 that we created above.
43
53
we also add a ReLU activation function in between and for that (since it has no parameters)
44
54
I recommend using nn.functional (F)
55
+
56
+ Parameters:
57
+ x: mnist images
58
+
59
+ Returns:
60
+ out: the output of the network
45
61
"""
46
62
47
63
x = F .relu (self .fc1 (x ))
@@ -52,15 +68,14 @@ def forward(self, x):
52
68
# Set device cuda for GPU if it's available otherwise run on the CPU
53
69
device = torch .device ("cuda" if torch .cuda .is_available () else "cpu" )
54
70
55
- # Hyperparameters of our neural network which depends on the dataset, and
56
- # also just experimenting to see what works well (learning rate for example).
71
+ # Hyperparameters
57
72
input_size = 784
58
73
num_classes = 10
59
74
learning_rate = 0.001
60
75
batch_size = 64
61
76
num_epochs = 3
62
77
63
- # Load Training and Test data
78
+ # Load Data
64
79
train_dataset = datasets .MNIST (root = "dataset/" , train = True , transform = transforms .ToTensor (), download = True )
65
80
test_dataset = datasets .MNIST (root = "dataset/" , train = False , transform = transforms .ToTensor (), download = True )
66
81
train_loader = DataLoader (dataset = train_dataset , batch_size = batch_size , shuffle = True )
@@ -83,38 +98,63 @@ def forward(self, x):
83
98
# Get to correct shape
84
99
data = data .reshape (data .shape [0 ], - 1 )
85
100
86
- # forward
101
+ # Forward
87
102
scores = model (data )
88
103
loss = criterion (scores , targets )
89
104
90
- # backward
105
+ # Backward
91
106
optimizer .zero_grad ()
92
107
loss .backward ()
93
108
94
- # gradient descent or adam step
109
+ # Gradient descent or adam step
95
110
optimizer .step ()
96
111
97
112
98
113
# Check accuracy on training & test to see how good our model
99
114
def check_accuracy (loader , model ):
115
+ """
116
+ Check accuracy of our trained model given a loader and a model
117
+
118
+ Parameters:
119
+ loader: torch.utils.data.DataLoader
120
+ A loader for the dataset you want to check accuracy on
121
+ model: nn.Module
122
+ The model you want to check accuracy on
123
+
124
+ Returns:
125
+ acc: float
126
+ The accuracy of the model on the dataset given by the loader
127
+ """
128
+
100
129
num_correct = 0
101
130
num_samples = 0
102
131
model .eval ()
103
132
133
+ # We don't need to keep track of gradients here so we wrap it in torch.no_grad()
104
134
with torch .no_grad ():
135
+ # Loop through the data
105
136
for x , y in loader :
137
+
138
+ # Move data to device
106
139
x = x .to (device = device )
107
140
y = y .to (device = device )
141
+
142
+ # Get to correct shape
108
143
x = x .reshape (x .shape [0 ], - 1 )
109
144
145
+ # Forward pass
110
146
scores = model (x )
111
147
_ , predictions = scores .max (1 )
148
+
149
+ # Check how many we got correct
112
150
num_correct += (predictions == y ).sum ()
151
+
152
+ # Keep track of number of samples
113
153
num_samples += predictions .size (0 )
114
154
115
155
model .train ()
116
156
return num_correct / num_samples
117
157
118
-
158
+ # Check accuracy on training & test to see how good our model
119
159
print (f"Accuracy on training set: { check_accuracy (train_loader , model )* 100 :.2f} " )
120
- print (f"Accuracy on test set: { check_accuracy (test_loader , model )* 100 :.2f} " )
160
+ print (f"Accuracy on test set: { check_accuracy (test_loader , model )* 100 :.2f} " )
0 commit comments