-
Notifications
You must be signed in to change notification settings - Fork 0
/
Week 2 Programming Assignment.py
317 lines (203 loc) · 10.3 KB
/
Week 2 Programming Assignment.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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
#!/usr/bin/env python
# coding: utf-8
# # Programming Assignment
# ## CNN classifier for the MNIST dataset
# ### Instructions
#
# In this notebook, you will write code to build, compile and fit a convolutional neural network (CNN) model to the MNIST dataset of images of handwritten digits.
#
# Some code cells are provided you in the notebook. You should avoid editing provided code, and make sure to execute the cells in order to avoid unexpected errors. Some cells begin with the line:
#
# `#### GRADED CELL ####`
#
# Don't move or edit this first line - this is what the automatic grader looks for to recognise graded cells. These cells require you to write your own code to complete them, and are automatically graded when you submit the notebook. Don't edit the function name or signature provided in these cells, otherwise the automatic grader might not function properly. Inside these graded cells, you can use any functions or classes that are imported below, but make sure you don't use any variables that are outside the scope of the function.
#
# ### How to submit
#
# Complete all the tasks you are asked for in the worksheet. When you have finished and are happy with your code, press the **Submit Assignment** button at the top of this notebook.
#
# ### Let's get started!
#
# We'll start running some imports, and loading the dataset. Do not edit the existing imports in the following cell. If you would like to make further Tensorflow imports, you should add them here.
# In[1]:
#### PACKAGE IMPORTS ####
# Run this cell first to import all required packages. Do not make any imports elsewhere in the notebook
import tensorflow as tf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
get_ipython().run_line_magic('matplotlib', 'inline')
# If you would like to make further imports from Tensorflow, add them here
# ![MNIST overview image](data/mnist.png)
#
# #### The MNIST dataset
#
# In this assignment, you will use the [MNIST dataset](http://yann.lecun.com/exdb/mnist/). It consists of a training set of 60,000 handwritten digits with corresponding labels, and a test set of 10,000 images. The images have been normalised and centred. The dataset is frequently used in machine learning research, and has become a standard benchmark for image classification models.
#
# - Y. LeCun, L. Bottou, Y. Bengio, and P. Haffner. "Gradient-based learning applied to document recognition." Proceedings of the IEEE, 86(11):2278-2324, November 1998.
#
# Your goal is to construct a neural network that classifies images of handwritten digits into one of 10 classes.
# #### Load and preprocess the data
# In[2]:
# Run this cell to load the MNIST data
mnist_data = tf.keras.datasets.mnist
(train_images, train_labels), (test_images, test_labels) = mnist_data.load_data()
# First, preprocess the data by scaling the training and test images so their values lie in the range from 0 to 1.
# In[6]:
#### GRADED CELL ####
# Complete the following function.
# Make sure to not change the function name or arguments.
def scale_mnist_data(train_images, test_images):
"""
This function takes in the training and test images as loaded in the cell above, and scales them
so that they have minimum and maximum values equal to 0 and 1 respectively.
Your function should return a tuple (train_images, test_images) of scaled training and test images.
"""
train_images = train_images/255.0
test_images =test_images/255.0
return (train_images, test_images)
# In[33]:
# Run your function on the input data
scaled_train_images, scaled_test_images = scale_mnist_data(train_images, test_images)
# In[34]:
# Add a dummy channel dimension
scaled_train_images = scaled_train_images[..., np.newaxis]
scaled_test_images = scaled_test_images[..., np.newaxis]
scaled_train_images.shape
# #### Build the convolutional neural network model
# We are now ready to construct a model to fit to the data. Using the Sequential API, build your CNN model according to the following spec:
#
# * The model should use the `input_shape` in the function argument to set the input size in the first layer.
# * A 2D convolutional layer with a 3x3 kernel and 8 filters. Use 'SAME' zero padding and ReLU activation functions. Make sure to provide the `input_shape` keyword argument in this first layer.
# * A max pooling layer, with a 2x2 window, and default strides.
# * A flatten layer, which unrolls the input into a one-dimensional tensor.
# * Two dense hidden layers, each with 64 units and ReLU activation functions.
# * A dense output layer with 10 units and the softmax activation function.
#
# In particular, your neural network should have six layers.
# In[35]:
#### GRADED CELL ####
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Flatten, Conv2D, MaxPooling2D
# Complete the following function.
# Make sure to not change the function name or arguments.
def get_model(input_shape):
"""
This function should build a Sequential model according to the above specification. Ensure the
weights are initialised by providing the input_shape argument in the first layer, given by the
function argument.
Your function should return the model.
"""
model = Sequential([
Conv2D(8, (3,3) , activation = 'relu', padding='same', input_shape=(28,28,1)),
MaxPooling2D((2,2)),
Flatten(),
Dense(64, activation='relu'),
Dense(64, activation='relu'),
Dense(10, activation='softmax')
])
return model
# In[36]:
# Run your function to get the model
model = get_model(scaled_train_images[0].shape)
# #### Compile the model
#
# You should now compile the model using the `compile` method. To do so, you need to specify an optimizer, a loss function and a metric to judge the performance of your model.
# In[41]:
#### GRADED CELL ####
# Complete the following function.
# Make sure to not change the function name or arguments.
def compile_model(model):
"""
This function takes in the model returned from your get_model function, and compiles it with an optimiser,
loss function and metric.
Compile the model using the Adam optimiser (with default settings), the cross-entropy loss function and
accuracy as the only metric.
Your function doesn't need to return anything; the model will be compiled in-place.
"""
model.compile(
optimizer = 'Adam',
loss = 'sparse_categorical_crossentropy',
metrics= ['accuracy']
)
# In[42]:
# Run your function to compile the model
compile_model(model)
# #### Fit the model to the training data
#
# Now you should train the model on the MNIST dataset, using the model's `fit` method. Set the training to run for 5 epochs, and return the training history to be used for plotting the learning curves.
# In[43]:
#### GRADED CELL ####
# Complete the following function.
# Make sure to not change the function name or arguments.
def train_model(model, scaled_train_images, train_labels):
"""
This function should train the model for 5 epochs on the scaled_train_images and train_labels.
Your function should return the training history, as returned by model.fit.
"""
history = model.fit(scaled_train_images, train_labels, epochs = 5)
return history
# In[44]:
# Run your function to train the model
history = train_model(model, scaled_train_images, train_labels)
# #### Plot the learning curves
#
# We will now plot two graphs:
# * Epoch vs accuracy
# * Epoch vs loss
#
# We will load the model history into a pandas `DataFrame` and use the `plot` method to output the required graphs.
# In[45]:
# Run this cell to load the model history into a pandas DataFrame
frame = pd.DataFrame(history.history)
# In[46]:
# Run this cell to make the Accuracy vs Epochs plot
acc_plot = frame.plot(y="accuracy", title="Accuracy vs Epochs", legend=False)
acc_plot.set(xlabel="Epochs", ylabel="Accuracy")
# In[47]:
# Run this cell to make the Loss vs Epochs plot
acc_plot = frame.plot(y="loss", title = "Loss vs Epochs",legend=False)
acc_plot.set(xlabel="Epochs", ylabel="Loss")
# #### Evaluate the model
#
# Finally, you should evaluate the performance of your model on the test set, by calling the model's `evaluate` method.
# In[54]:
#### GRADED CELL ####
# Complete the following function.
# Make sure to not change the function name or arguments.
def evaluate_model(model, scaled_test_images, test_labels):
"""
This function should evaluate the model on the scaled_test_images and test_labels.
Your function should return a tuple (test_loss, test_accuracy).
"""
test_loss,test_accuracy = model.evaluate(scaled_test_images,test_labels, verbose=2)
return (test_loss,test_accuracy)
# In[55]:
# Run your function to evaluate the model
test_loss, test_accuracy = evaluate_model(model, scaled_test_images, test_labels)
print(f"Test loss: {test_loss}")
print(f"Test accuracy: {test_accuracy}")
# #### Model predictions
#
# Let's see some model predictions! We will randomly select four images from the test data, and display the image and label for each.
#
# For each test image, model's prediction (the label with maximum probability) is shown, together with a plot showing the model's categorical distribution.
# In[56]:
# Run this cell to get model predictions on randomly selected test images
num_test_images = scaled_test_images.shape[0]
random_inx = np.random.choice(num_test_images, 4)
random_test_images = scaled_test_images[random_inx, ...]
random_test_labels = test_labels[random_inx, ...]
predictions = model.predict(random_test_images)
fig, axes = plt.subplots(4, 2, figsize=(16, 12))
fig.subplots_adjust(hspace=0.4, wspace=-0.2)
for i, (prediction, image, label) in enumerate(zip(predictions, random_test_images, random_test_labels)):
axes[i, 0].imshow(np.squeeze(image))
axes[i, 0].get_xaxis().set_visible(False)
axes[i, 0].get_yaxis().set_visible(False)
axes[i, 0].text(10., -1.5, f'Digit {label}')
axes[i, 1].bar(np.arange(len(prediction)), prediction)
axes[i, 1].set_xticks(np.arange(len(prediction)))
axes[i, 1].set_title(f"Categorical distribution. Model prediction: {np.argmax(prediction)}")
plt.show()
# Congratulations for completing this programming assignment! In the next week of the course we will take a look at including validation and regularisation in our model training, and introduce Keras callbacks.