Distinguish Your Own Digits (DYOD) - A NN Model Exercise
%load_ext autoreload
%autoreload 2
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
!pip install mnist
import mnist
train_images = mnist.train_images()
train_labels = mnist.train_labels()
train_images.shape, train_labels.shape
test_images = mnist.test_images()
test_labels = mnist.test_labels()
test_images.shape, test_labels.shape
image_index = 7776 # You may select anything up to 60,000
print(train_labels[image_index])
plt.imshow(train_images[image_index], cmap='Greys')
train_filter = np.where((train_labels == 3 ) | (train_labels == 8))
test_filter = np.where((test_labels == 3) | (test_labels == 8))
X_train, y_train = train_images[train_filter], train_labels[train_filter]
X_test, y_test = test_images[test_filter], test_labels[test_filter]
We normalize the pizel values in the 0 to 1 range
X_train = X_train/255.
X_test = X_test/255.
And setup the labels as 1 (when the digit is 3) and 0 (when the digit is 8)
y_train = 1*(y_train==3)
y_test = 1*(y_test==3)
X_train.shape, X_test.shape
We reshape the data to flatten the image pixels into a set of features or co-variates:
X_train = X_train.reshape(X_train.shape[0], -1)
X_test = X_test.reshape(X_test.shape[0], -1)
X_train.shape, X_test.shape
#libraries
from kudzu.data import Data, Dataloader, Sampler
from kudzu.callbacks import AccCallback
from kudzu.loss import MSE
from kudzu.layer import Affine, Sigmoid
from kudzu.model import Model
from kudzu.optim import GD
from kudzu.train import Learner
from kudzu.callbacks import ClfCallback
from kudzu.layer import Sigmoid
from kudzu.layer import Relu
class Config:
pass
config = Config()
config.lr = 0.001
config.num_epochs = 250
config.bs = 50
#data initialization
data = Data(X_train, y_train.reshape(-1,1))
loss = MSE()
opt = GD(config.lr)
sampler = Sampler(data, config.bs, shuffle=True)
dl = Dataloader(data, sampler)
#containers
training_xdata = X_train
testing_xdata = X_test
training_ydata = y_train.reshape(-1,1)
testing_ydata = y_test.reshape(-1,1)
#NN model initialization
layers = [Affine("first", 784, 100), Relu("first"), Affine("second", 100, 100), Relu("second"), Affine("third", 100, 2), Affine("final", 2, 1), Sigmoid("final")]
model_neural = Model(layers)
model_logistic = Model([Affine("logits", 784, 1), Sigmoid("sigmoid")])
learner1 = Learner(loss, model_neural, opt, config.num_epochs)
acc1 = ClfCallback(learner1, config.bs, training_xdata , testing_xdata, training_ydata, testing_ydata)
learner1.set_callbacks([acc1])
#learner call
learner1.train_loop(dl)
#LR model initalization
learner2 = Learner(loss, model_logistic, opt, config.num_epochs)
acc2 = ClfCallback(learner2, config.bs, training_xdata , testing_xdata, training_ydata, testing_ydata)
learner2.set_callbacks([acc2])
#learner call
learner2.train_loop(dl)
#Comparative Stats
plt.figure(figsize = (8,5))
plt.plot(acc1.val_accuracies, 'g-', label = "Neural_Network - Val_Accuracy")
plt.plot(acc1.accuracies, 'b-', label = "Neural_Network - Accuracies")
plt.plot(acc2.val_accuracies, 'r-', label = "Logistic_Regr - Val_Accuracies")
plt.plot(acc2.accuracies, 'y-', label = "Logistic_Regr - Accuracies")
plt.ylim(0.85,1) #check
plt.legend()
#2D Output
model_new = Model(layers[:-2])
plot_testing = model_new(testing_xdata)
plt.figure(figsize=(8,7)) #blows up
plt.scatter(plot_testing[:,0], plot_testing[:,1], alpha = 0.1, c = y_test.ravel());
#isolating affine -> sigmoid
model_prob = Model(layers[-2:])
xgrid = np.linspace(-4.5, 2, 100)
ygrid = np.linspace(-8, 8, 100)
xg, yg = np.meshgrid(xgrid, ygrid)
xg_interim = np.ravel(xg) #cant do; Check later
yg_interim = np.ravel(yg)
X_interim = np.vstack((xg_interim, yg_interim)) ## Please note vstack takes in a tuple
X = X_interim.T
probability_contour = model_prob(X).reshape(100,100)
plt.figure(figsize=(8,7))
plt.scatter(plot_testing[:,0], plot_testing[:,1], alpha = 0.1, c = y_test.ravel())
contours = plt.contour(xg,yg,probability_contour)
plt.clabel(contours, inline=True);