# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# + [markdown] deletable=true editable=true
# # Convolutional Neural Networks

# + [markdown] deletable=true editable=true
# ## Machine learning on images

# + deletable=true editable=true
import pandas as pd
import numpy as np
# %matplotlib inline
import matplotlib.pyplot as plt

# + [markdown] deletable=true editable=true
# ### MNIST

# + deletable=true editable=true
from keras.datasets import mnist

# + deletable=true editable=true
(X_train, y_train), (X_test, y_test) = mnist.load_data('/tmp/mnist.npz')

# + deletable=true editable=true
X_train.shape

# + deletable=true editable=true
X_test.shape

# + deletable=true editable=true
X_train[0]

# + deletable=true editable=true
plt.imshow(X_train[0], 
           cmap = 'gray')

# + deletable=true editable=true
# Flattening the input
X_train = X_train.reshape(-1, 28 * 28)
X_test = X_test.reshape(-1, 28 * 28)

# + deletable=true editable=true
X_train.shape

# + deletable=true editable=true
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train /= 255.0
X_test /= 255.0

# + deletable=true editable=true
X_train[0]

# + deletable=true editable=true
from keras.utils.np_utils import to_categorical

# + deletable=true editable=true
y_train_cat = to_categorical(y_train)
y_test_cat = to_categorical(y_test)

# + deletable=true editable=true
y_train[0]

# + deletable=true editable=true
# One-hot encoded labels
y_train_cat[0]

# + deletable=true editable=true
y_train_cat.shape

# + deletable=true editable=true
y_test_cat.shape

# + [markdown] deletable=true editable=true
# ### Fully connected on images

# + deletable=true editable=true
from keras.models import Sequential
from keras.layers import Dense
import keras.backend as K

K.clear_session()

model = Sequential()
model.add(Dense(10, 
                input_dim = 28 * 28, 
                activation = 'relu'))

model.add(Dense(256, 
                activation = 'relu'))
'''
model.add(Dense(128, 
                activation = 'relu'))
'''
model.add(Dense(16, 
                activation = 'relu'))
model.add(Dense(10, 
                activation = 'softmax'))
model.compile(loss = 'categorical_crossentropy',
              optimizer = 'rmsprop',
              metrics = ['accuracy'])


# + deletable=true editable=true
h = model.fit(X_train, 
              y_train_cat, 
              batch_size = 12, 
              epochs = 10, 
              verbose = 2, 
              validation_split = 0.3)

# + deletable=true editable=true
plt.figure(figsize = (12,7))
plt.plot(h.history['acc'])
plt.plot(h.history['val_acc'])
plt.legend(['Training', 'Validation'], loc = 'lower right')
plt.title('Accuracy')
plt.xlabel('Epochs')

# + deletable=true editable=true
test_accuracy = model.evaluate(X_test, y_test_cat)[1]
# Printing the accuracy
test_accuracy * 100

# + [markdown] deletable=true editable=true
# ### Tensor Math

# + deletable=true editable=true
A = np.random.randint(10, size = (2, 3, 4, 5))
B = np.random.randint(10, size = (2, 3))

# + deletable=true editable=true
A

# + deletable=true editable=true
A[0, 1, 0, 3]

# + deletable=true editable=true
B

# + [markdown] deletable=true editable=true
# #### A random colored image

# + deletable=true editable=true
img = np.random.randint(255, 
                        size = (4, 4, 3),
                        dtype = 'uint8')
img

# + deletable=true editable=true
plt.figure(figsize = (10, 7))
plt.subplot(221)
plt.imshow(img)
plt.title("All Channels combined")

plt.subplot(222)
plt.imshow(img[:, : , 0], 
           cmap = 'Reds')
plt.title("Red channel")

plt.subplot(223)
plt.imshow(img[:, : , 1], 
           cmap = 'Greens')
plt.title("Green channel")

plt.subplot(224)
plt.imshow(img[:, : , 2], 
           cmap = 'Blues')
plt.title("Blue channel")

# + [markdown] deletable=true editable=true
# ### Tensor operations

# + deletable=true editable=true
2 * A

# + deletable=true editable=true
A + A

# + deletable=true editable=true
A.shape

# + deletable=true editable=true
B.shape

# + deletable=true editable=true
np.tensordot(A, 
             B, 
             axes = ([0, 1], [0, 1]))

# + deletable=true editable=true
np.tensordot(A, 
             B, 
             axes = ([0], [0])).shape

# + [markdown] deletable=true editable=true
# ### 1D convolution

# + deletable=true editable=true
a = np.array([0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0], 
             dtype='float32')

# + deletable=true editable=true
b = np.array([-1, 1], 
             dtype='float32')

# + deletable=true editable=true
c = np.convolve(a, b)

# + deletable=true editable=true
a

# + deletable=true editable=true
b

# + deletable=true editable=true
c

# + deletable=true editable=true
plt.subplot(211)
plt.plot(a, 'o-')

plt.subplot(212)
plt.plot(c, 'o-')

# + [markdown] deletable=true editable=true
# ### Image filters with convolutions

# + deletable=true editable=true
from scipy.ndimage.filters import convolve
from scipy.signal import convolve2d
from scipy import misc

# + deletable=true editable=true
img = misc.ascent()

# + deletable=true editable=true
img.shape

# + deletable=true editable=true
plt.imshow(img, 
           cmap = 'gray')

# + deletable=true editable=true
h_kernel = np.array([[ 1,  2,  1],
                     [ 0,  0,  0],
                     [-1, -2, -1]])


# + deletable=true editable=true
plt.imshow(h_kernel, 
           cmap = 'gray')

# + deletable=true editable=true
res = convolve2d(img, h_kernel)

plt.imshow(res, 
           cmap = 'gray')

# + [markdown] deletable=true editable=true
# ## Convolutional neural networks

# + deletable=true editable=true
from keras.layers import Conv2D

# + deletable=true editable=true
img.shape

# + deletable=true editable=true
plt.figure(figsize = (7, 7))
plt.imshow(img, 
           cmap = 'gray')

# + deletable=true editable=true
img_tensor = img.reshape((1, 512, 512, 1))

# + deletable=true editable=true
model = Sequential()
model.add(Conv2D(filters = 1, 
                 kernel_size = (3, 3), 
                 strides = (2,1), 
                 input_shape = (512, 512, 1)))
model.compile('adam', 'mse')

# + deletable=true editable=true
img_pred_tensor = model.predict(img_tensor)

# + deletable=true editable=true
img_pred_tensor.shape

# + deletable=true editable=true
img_pred = img_pred_tensor[0, :, :, 0]

# + deletable=true editable=true
plt.imshow(img_pred, 
           cmap = 'gray')

# + deletable=true editable=true
weights = model.get_weights()

# + deletable=true editable=true
weights[0].shape

# + deletable=true editable=true
plt.imshow(weights[0][:, :, 0, 0], 
           cmap = 'gray')

# + deletable=true editable=true
weights[0] = np.ones(weights[0].shape)

# + deletable=true editable=true
model.set_weights(weights)

# + deletable=true editable=true
img_pred_tensor = model.predict(img_tensor)

# + deletable=true editable=true
img_pred = img_pred_tensor[0, :, :, 0]

# + deletable=true editable=true
plt.imshow(img_pred, 
           cmap = 'gray')

# + deletable=true editable=true
model = Sequential()
model.add(Conv2D(filters = 1, 
                 kernel_size = (3, 3), 
                 input_shape = (512, 512, 1), 
                 padding='same'))
model.compile('adam', 'mse')

img_pred_tensor = model.predict(img_tensor)


img_pred_tensor.shape

# + deletable=true editable=true
img_pred_tensor = img_pred_tensor[0, :, :, 0]

plt.imshow(img_pred_tensor, 
           cmap = 'gray')

# + [markdown] deletable=true editable=true
# ## Pooling layers

# + deletable=true editable=true
from keras.layers import MaxPool2D, AvgPool2D

# + deletable=true editable=true
model = Sequential()
model.add(MaxPool2D(pool_size = (5, 5), 
                    input_shape = (512, 512, 1)))
model.compile('adam', 'mse')

# + deletable=true editable=true
img_pred = model.predict(img_tensor)[0, :, :, 0]

# + deletable=true editable=true
plt.imshow(img_pred, 
           cmap = 'gray')

# + deletable=true editable=true
model = Sequential()
model.add(AvgPool2D(pool_size = (5, 5), 
                    input_shape = (512, 512, 1)))
model.compile('adam', 'mse')

# + deletable=true editable=true
img_pred = model.predict(img_tensor)[0, :, :, 0]
plt.imshow(img_pred, 
           cmap = 'gray')

# + [markdown] deletable=true editable=true
# ## Final architecture

# + deletable=true editable=true
X_train = X_train.reshape(-1, 28, 28, 1)
X_test = X_test.reshape(-1, 28, 28, 1)

# + deletable=true editable=true
X_train.shape

# + deletable=true editable=true
from keras.layers import Flatten, Activation

# + deletable=true editable=true
K.clear_session()

model = Sequential()

model.add(Conv2D(8, 
                 (3, 3), 
                 input_shape = (28, 28, 1)))
model.add(MaxPool2D(pool_size = (2, 2)))
model.add(Activation('relu'))

model.add(Flatten())

model.add(Dense(32, 
                activation = 'relu'))

model.add(Dense(10, 
                activation = 'softmax'))

model.compile(loss = 'categorical_crossentropy',
              optimizer = 'rmsprop',
              metrics = ['accuracy'])

# + deletable=true editable=true
model.summary()

# + deletable=true editable=true
model.fit(X_train, 
          y_train_cat, 
          batch_size = 12,
          epochs = 2, 
          verbose = 2, 
          validation_split = 0.3)

# + deletable=true editable=true
evaluated = model.evaluate(X_test, y_test_cat)

# + deletable=true editable=true
evaluated[1] * 100

# + [markdown] deletable=true editable=true
# ### Exercise 1
# You've been hired by a shipping company to overhaul the way they route mail, parcels and packages. They want to build an image recognition system  capable of recognizing the digits in the zipcode on a package, so that it can be automatically routed to the correct location.
# You are tasked to build the digit recognition system. Luckily, you can rely on the MNIST dataset for the intial training of your model!
#
# Build a deep convolutional neural network with at least two convolutional and two pooling layers before the fully connected layer.
#
# - Start from the network we have just built
# - Insert a `Conv2D` layer after the first `MaxPool2D`, give it 64 filters.
# - Insert a `MaxPool2D` after that one
# - Insert an `Activation` layer
# - retrain the model
# - does performance improve?
# - how many parameters does this new model have? More or less than the previous model? Why?
# - how long did this second model take to train? Longer or shorter than the previous model? Why?
# - did it perform better or worse than the previous model?

# + deletable=true editable=true
X_train.shape, X_test.shape, y_train_cat.shape, y_test_cat.shape

# + deletable=true editable=true
from keras.layers import Input, Dense, Conv2D, MaxPool2D, Activation, Flatten
import keras.backend as K
from keras.models import Model
from keras.optimizers import Adam

# + deletable=true editable=true
K.clear_session()
inp = Input(shape = (28, 28, 1 ))
net = Conv2D(filters = 64, 
             kernel_size = (2, 2), 
             activation = 'relu', 
             padding = 'valid')(inp)
net = MaxPool2D(pool_size = (2, 2), 
                strides = (2, 2), 
                padding = 'valid')(net)
net = Conv2D(filters = 8, 
             kernel_size = (2, 2), 
             activation = 'relu', 
             padding = 'valid')(net)
net = MaxPool2D(pool_size = (2, 2), 
                strides = (2, 2), 
                padding = 'valid')(net)
net = Activation(activation = 'relu')(net)
net = Flatten()(net)
prediction = Dense(10, activation = 'softmax')(net)

# + deletable=true editable=true
model = Model(inputs = inp, outputs = prediction)
model.compile(optimizer = Adam(), 
              loss = 'categorical_crossentropy', 
              metrics = ['accuracy'])

# + deletable=true editable=true
model.summary()

# + deletable=true editable=true
model.fit(X_train, 
          y_train_cat, 
          batch_size = 50, 
          validation_split = 0.2,
          epochs = 5,
          verbose = 2)

# + [markdown] deletable=true editable=true
# ### Exercise 2
#
# Pleased with your performance with the digits recognition task, your boss decides to challenge you with a harder task. Their online branch allows people to upload images to a website that generates and prints a postcard that is shipped to destination. Your boss would like to know what images people are loading on the site in order to provide targeted advertising on the same page, so he asks you to build an image recognition system capable of recognizing a few objects. Luckily for you, there's a dataset ready made with a collection of labeled images. This is the [Cifar 10 Dataset](http://www.cs.toronto.edu/~kriz/cifar.html), a very famous dataset that contains images for 10 different categories:
#
# - airplane 										
# - automobile 										
# - bird 										
# - cat 										
# - deer 										
# - dog 										
# - frog 										
# - horse 										
# - ship 										
# - truck
#
# In this exercise we will reach the limit of what you can achieve on your laptop and get ready for the next session on cloud GPUs.
#
# Here's what you have to do:
# - load the cifar10 dataset using `keras.datasets.cifar10.load_data()`
# - display a few images, see how hard/easy it is for you to recognize an object with such low resolution
# - check the shape of X_train, does it need reshape?
# - check the scale of X_train, does it need rescaling?
# - check the shape of y_train, does it need reshape?
# - build a model with the following architecture, and choose the parameters and activation functions for each of the layers:
#     - conv2d
#     - conv2d
#     - maxpool
#     - conv2d
#     - conv2d
#     - maxpool
#     - flatten
#     - dense
#     - output
# - compile the model and check the number of parameters
# - attempt to train the model with the optimizer of your choice. How fast does training proceed?
# - If training is too slow (as expected) stop the execution and move to the next session!

# + deletable=true editable=true
from keras.datasets import cifar10

# + deletable=true editable=true
(X_train, y_train), (X_test, y_test) = cifar10.load_data()
# -

X_train.shape

X_train[0, :, :, 0]

X_train[0, :, :, 1]

X_train[0, :, :, 2]

np.max(X_train[0, :, :, :])

np.min(X_train[0, :, :, :])

# +
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')

X_train = X_train / 255.0
X_test = X_test / 255.0
# -

from keras.utils import to_categorical
y_train_cat = to_categorical(y_train)
y_test_cat = to_categorical(y_test)

y_train_cat[:5]

print(y_train_cat.shape)

y_test_cat[:5]

print(y_test_cat.shape)

# +
'''conv2d
conv2d
maxpool

conv2d
conv2d
maxpool
flatten
dense
output
'''

from keras.models import Model
from keras.layers import Input, Dense, Conv2D, MaxPool2D, Flatten
from keras.regularizers import l2

# Inputs 32 x 32 x 3
inp = Input(shape = (32, 32, 3))

net = Conv2D(filters = 8, 
             kernel_size = (2, 2), 
             padding = 'same')(inp)
net = Conv2D(filters = 8, 
             kernel_size = (2, 2), 
             padding = 'same')(net)
net = MaxPool2D(pool_size = (2, 2), padding = 'valid')(net)


net = Conv2D(filters = 8, 
             kernel_size = (2, 2), 
             padding = 'same')(net)
net = Conv2D(filters = 8, 
             kernel_size = (2, 2), 
             padding = 'same')(net)
net = MaxPool2D(pool_size = (2, 2), padding = 'valid')(net)


net = Flatten()(net)
net = Dense(units = 10, 
            activation = 'relu')(net)
prediction = Dense(units = 10, 
                   activation = 'softmax')(net)
# -

model = Model(inputs = [inp], outputs = [prediction])

from keras.optimizers import Adam

model.compile(optimizer = Adam(), 
              loss = 'categorical_crossentropy', 
              metrics = ['accuracy'])

model.summary()

model.fit(X_train, 
          y_train_cat, 
          batch_size = 50, 
          validation_split = 0.2,
          epochs = 5,
          verbose = 2)

StarcoderdataJupyterScriptsDedupFiltered