In [ ]:
print('Hello ex02!')

In [ ]:
import numpy as np
import pandas as pd

Exercise 3.2

Write a function that can shift an MNIST image in any direction (left, right, up, or down) by one pixel. Then, for each image in the training set, create four shifted copies (one per direction) and add them to the training set. Finally, train your best model on this expanded training set and measure its accuracy on the test set. You should observe that your model performs even better now! This technique of artificially growing the training set is called data augmentation or training set expansion.

Note: You can use the shift() function from the scipy.ndimage.interpolation module. For example, shift(image, [2, 1], cval=0) shifts the image 2 pixels down and 1 pixel to the right.

3.1 MNIST

  • Download the dataset from here
  • See the stackoverflow discussion here

In [ ]:
from scipy.io import loadmat
mnist = loadmat('./datasets/mnist-original.mat')

In [ ]:
mnist

In [ ]:
X, y = mnist['data'], mnist['label']

In [ ]:
X = X.T
X.shape

In [ ]:
y = y.T
y.shape

In [ ]:
type(y)

In [ ]:
%matplotlib inline
import matplotlib
import matplotlib.pyplot as plt

In [ ]:
from scipy.ndimage.interpolation import shift

In [ ]:
some_digit = X[36000]
some_digit_image = some_digit.reshape((28, 28))
some_digit_image_shifted = shift(some_digit_image, [1, 1], cval=0)

In [ ]:
fig, ax = plt.subplots(2,1)
ax[0].imshow(some_digit_image, cmap = matplotlib.cm.binary, interpolation="nearest")
ax[1].imshow(some_digit_image_shifted, cmap = matplotlib.cm.binary, interpolation="nearest")

In [ ]:
def shift_image(digit, dist=1, DEBUG=0):
    sz = 28
    digit_image = digit.reshape((sz, sz))
    digit_image_u = shift(digit_image, [-dist, 0], cval=0)
    digit_image_d = shift(digit_image, [+dist, 0], cval=0)
    digit_image_l = shift(digit_image, [0, -dist], cval=0)
    digit_image_r = shift(digit_image, [0, +dist], cval=0)
    
    if DEBUG:
        fig, ax = plt.subplots(5, 1)
        ax[0].imshow(digit_image, cmap = matplotlib.cm.binary, interpolation="nearest")
        ax[1].imshow(digit_image_u, cmap = matplotlib.cm.binary, interpolation="nearest")
        ax[2].imshow(digit_image_d, cmap = matplotlib.cm.binary, interpolation="nearest")
        ax[3].imshow(digit_image_l, cmap = matplotlib.cm.binary, interpolation="nearest")
        ax[4].imshow(digit_image_r, cmap = matplotlib.cm.binary, interpolation="nearest")
    
    ret = np.concatenate([image.reshape(1,sz**2) for image in [digit_image, digit_image_u, digit_image_d, digit_image_l, digit_image_r]])
    return ret

shift_image(some_digit, 5, 0)

In [ ]:
X_train, X_test, y_train, y_test = X[:60000], X[60000:], y[:60000], y[60000:]
shuffle_index = np.random.permutation(len(X_train))
X_train, y_train = X_train[shuffle_index], y_train[shuffle_index]

In [ ]:
X_train_shifted = np.concatenate([shift_image(image) for image in X_train])

In [ ]:
X_train_shifted.shape

In [ ]:
a = np.asarray([[0], [1]])
a.repeat(2, axis=1).reshape(-1, 1)

In [ ]:
y_train_shifed = y_train.repeat(5, axis=1).reshape(-1, 1)
y_train_shifed.shape

In [ ]:
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score

forest_clf = RandomForestClassifier(random_state=42)

In [ ]:
cross_val_score(forest_clf, X_train, y_train, cv=3, scoring="accuracy")

In [ ]:
cross_val_score(forest_clf, X_train_shifted, y_train_shifed, cv=3, scoring="accuracy")