123
123
# - ``pretrained_model`` - path to the pretrained MNIST model which was
124
124
# trained with
125
125
# `pytorch/examples/mnist <https://github.com/pytorch/examples/tree/master/mnist>`__.
126
- # For simplicity, download the pretrained model `here <https://drive.google.com/drive/folders/1fn83DF14tWmit0RTKWRhPq5uVXt73e0h ?usp=sharing >`__.
126
+ # For simplicity, download the pretrained model `here <https://drive.google.com/file/d/1HJV2nUHJqclXQ8flKvcWmjZ-OU5DGatl/view ?usp=drive_link >`__.
127
127
#
128
128
# - ``use_cuda`` - boolean flag to use CUDA if desired and available.
129
129
# Note, a GPU with CUDA is not critical for this tutorial as a CPU will
154
154
class Net (nn .Module ):
155
155
def __init__ (self ):
156
156
super (Net , self ).__init__ ()
157
- self .conv1 = nn .Conv2d (1 , 10 , kernel_size = 5 )
158
- self .conv2 = nn .Conv2d (10 , 20 , kernel_size = 5 )
159
- self .conv2_drop = nn .Dropout2d ()
160
- self .fc1 = nn .Linear (320 , 50 )
161
- self .fc2 = nn .Linear (50 , 10 )
157
+ self .conv1 = nn .Conv2d (1 , 32 , 3 , 1 )
158
+ self .conv2 = nn .Conv2d (32 , 64 , 3 , 1 )
159
+ self .dropout1 = nn .Dropout (0.25 )
160
+ self .dropout2 = nn .Dropout (0.5 )
161
+ self .fc1 = nn .Linear (9216 , 128 )
162
+ self .fc2 = nn .Linear (128 , 10 )
162
163
163
164
def forward (self , x ):
164
- x = F .relu (F .max_pool2d (self .conv1 (x ), 2 ))
165
- x = F .relu (F .max_pool2d (self .conv2_drop (self .conv2 (x )), 2 ))
166
- x = x .view (- 1 , 320 )
167
- x = F .relu (self .fc1 (x ))
168
- x = F .dropout (x , training = self .training )
165
+ x = self .conv1 (x )
166
+ x = F .relu (x )
167
+ x = self .conv2 (x )
168
+ x = F .relu (x )
169
+ x = F .max_pool2d (x , 2 )
170
+ x = self .dropout1 (x )
171
+ x = torch .flatten (x , 1 )
172
+ x = self .fc1 (x )
173
+ x = F .relu (x )
174
+ x = self .dropout2 (x )
169
175
x = self .fc2 (x )
170
- return F .log_softmax (x , dim = 1 )
176
+ output = F .log_softmax (x , dim = 1 )
177
+ return output
171
178
172
179
# MNIST Test dataset and dataloader declaration
173
180
test_loader = torch .utils .data .DataLoader (
174
181
datasets .MNIST ('../data' , train = False , download = True , transform = transforms .Compose ([
175
182
transforms .ToTensor (),
176
- ])),
183
+ transforms .Normalize ((0.1307 ,), (0.3081 ,)),
184
+ ])),
177
185
batch_size = 1 , shuffle = True )
178
186
179
187
# Define what device we are using
@@ -184,7 +192,7 @@ def forward(self, x):
184
192
model = Net ().to (device )
185
193
186
194
# Load the pretrained model
187
- model .load_state_dict (torch .load (pretrained_model , weights_only = True , map_location = 'cpu' ))
195
+ model .load_state_dict (torch .load (pretrained_model , map_location = device ))
188
196
189
197
# Set the model in evaluation mode. In this case this is for the Dropout layers
190
198
model .eval ()
@@ -219,6 +227,26 @@ def fgsm_attack(image, epsilon, data_grad):
219
227
# Return the perturbed image
220
228
return perturbed_image
221
229
230
+ # restores the tensors to their original scale
231
+ def denorm (batch , mean = [0.1307 ], std = [0.3081 ]):
232
+ """
233
+ Convert a batch of tensors to their original scale.
234
+
235
+ Args:
236
+ batch (torch.Tensor): Batch of normalized tensors.
237
+ mean (torch.Tensor or list): Mean used for normalization.
238
+ std (torch.Tensor or list): Standard deviation used for normalization.
239
+
240
+ Returns:
241
+ torch.Tensor: batch of tensors without normalization applied to them.
242
+ """
243
+ if isinstance (mean , list ):
244
+ mean = torch .tensor (mean ).to (device )
245
+ if isinstance (std , list ):
246
+ std = torch .tensor (std ).to (device )
247
+
248
+ return batch * std .view (1 , - 1 , 1 , 1 ) + mean .view (1 , - 1 , 1 , 1 )
249
+
222
250
223
251
######################################################################
224
252
# Testing Function
@@ -273,11 +301,17 @@ def test( model, device, test_loader, epsilon ):
273
301
# Collect ``datagrad``
274
302
data_grad = data .grad .data
275
303
304
+ # Restore the data to its original scale
305
+ data_denorm = denorm (data )
306
+
276
307
# Call FGSM Attack
277
- perturbed_data = fgsm_attack (data , epsilon , data_grad )
308
+ perturbed_data = fgsm_attack (data_denorm , epsilon , data_grad )
309
+
310
+ # Reapply normalization
311
+ perturbed_data_normalized = transforms .Normalize ((0.1307 ,), (0.3081 ,))(perturbed_data )
278
312
279
313
# Re-classify the perturbed image
280
- output = model (perturbed_data )
314
+ output = model (perturbed_data_normalized )
281
315
282
316
# Check for success
283
317
final_pred = output .max (1 , keepdim = True )[1 ] # get the index of the max log-probability
0 commit comments