# MNIST tutorial (handwritten printed digits recognition tutorial)
# modified from
# https://elitedatascience.com/keras-tutorial-deep-learning-in-python
# for SDSC SI2017
# ----------- IMPORT STATEMENTS ---------------
import numpy as np
np.random.seed(1) # for reproducibility
from keras.models import Sequential #Sequential models are the standard stack of layers models
from keras.layers import Dense, Dropout, Activation, Flatten #These are core layer specification functions
from keras.layers import Convolution2D, MaxPooling2D #These are convolution layer functions
from keras.utils import np_utils #Some utilities
from keras import optimizers #For training algorithm
#---------------------------------------------
print('import done')
#--------------- LOAD and PREPARE DATA STATEMENTS ----------------
# Load some numpy arrays that have the MNIST data
# (these are subsets extracted from the MNIST data set in Keras)
X_train=np.load('X_train5k.npy')
Y_train=np.load('Y_train5k.npy')
X_test =np.load('X_test.npy')
Y_test =np.load('Y_test.npy')
print(X_train.shape) #review the dimensions Note python3 uses print(X..) python 2 uses print X...
#save a few training images with the label in the file name
from PIL import Image
for i in range(0,3):
im = Image.fromarray(X_train[i,:,:])
im.save("Xtrain_num"+str(i)+"_cat_"+str(Y_train[i])+".jpeg")
print('img load done')
# --------- Reshape input data ------------
# b/c Keras expects N-3D images (ie 4D matrix)
X_train = X_train.reshape(X_train.shape[0], 1, 28, 28)
X_test = X_test.reshape(X_test.shape[0], 1, 28, 28)
#To confirm, we can print X_train's dimensions again:
print(X_train.shape)
#convert and put into 0-1 range
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train /= 255
X_test /= 255
# Convert 1-dimensional class arrays to 10-dimensional class matrices
Y_train = np_utils.to_categorical(Y_train, 10)
Y_test = np_utils.to_categorical(Y_test, 10)
# ------------- End loading and preparing data --------------
np.amax(X_train) #this gets the max value over a flattened numpy array
print('prep done')
# --------------Set up Model ---------------------
mymodel = Sequential()
numfilters = 16
#add convolution layer of 32 or 16 or __ filters, 3x3 each, After a first run, try 9x9
# input shape for 1 image, channels refers to color dimension of input image
#mymodel.add(Convolution2D(numfilters, (3,3),strides=1, data_format="channels_first",activation='relu', input_shape=(1,28,28)))
mymodel.add(Convolution2D(numfilters, (9,9),strides=1, data_format="channels_first",activation='relu', input_shape=(1,28,28)))
print('modeldef and first conv layer done')
mymodel.layers[0].output # use this to check sizes of output
#-----------------Now add more Convolution layers
mymodel.add(Convolution2D(numfilters, (3, 3), activation='relu'))
mymodel.add(MaxPooling2D(pool_size=(2,2))) #get Max over 2D region,and slide
#optional?
mymodel.add(Dropout(0.25))
mymodel.add(Flatten()) #reorganize 2DxFilters output into 1D
mymodel.layers[2].output #size of output layer for max pooling
#----------------Now add final classification layers
mymodel.add(Dense(128, activation='relu')) #enter number of hidden units (no good rule, but start with ~ num of previous output)
mymodel.add(Dropout(0.5))
mymodel.add(Dense(10, activation='softmax'))
print('assemble model done')
# --------- Now assemble (ie compile TensorFlow commands) and run -----
mymodel.compile(loss='categorical_crossentropy',
optimizer='sgd',
metrics=['accuracy'])
#------------ Now Run Training
mymodel.fit(X_train, Y_train,
batch_size=32, epochs=15, verbose=1) #batch up 32 examples before adjusting weights,
#sweep through training data 'epochs' times
#--------- Get overall prediction score
trainscore = mymodel.evaluate(X_train, Y_train, verbose=1) # get overal score
testscore = mymodel.evaluate(X_test, Y_test, verbose=1) # get overal score
#somepred = mymodel.predict(X_test,verbose=0) # get predicted labels
print(trainscore)
print(testscore)
#-----------Optional: View some of the output
#print(somepred[1:3])
#Notice each row is 10 elements, each element is a prediction of the number labels
print(Y_test[1:3])
#To view a sample image
import matplotlib.pyplot as plt #These provide matlab type of plotting functions
import matplotlib.image as mpimg
img_filename = "Xtrain_num0_cat_5.jpeg" #% scriptDir
im = mpimg.imread(img_filename)
plt.figure()
plt.imshow(im,'gray')
plt.show()
print('im loaded')
# ------------ GET WEIGHTS From Convolution Layer and make mosaic image
Wlist =mymodel.layers[0].get_weights()
W3D =np.squeeze(Wlist[0])
W3D.shape
W3Dchan =W3D.swapaxes(1,2).swapaxes(0,1) #get 32 as 1st dimension
Wmin =np.amin(W3Dchan)
Wmax =np.amax(W3Dchan-Wmin)
Wsc =np.int_(255*(W3Dchan-Wmin)/Wmax)
ncol =4
nrow =np.ceil(numfilters/ncol)
print(nrow)
plt.figure()
for i in range(Wsc.shape[0]):
plt.subplot(nrow,ncol,i+1)
plt.imshow(Wsc[i],'gray')
plt.axis('off')
#plt.savefig("test.png", bbox_inches='tight')
plt.show()
print('done plotting weights mosaic')
# ---------------- NOW Visualize the activations for the first training example --------
from keras import backend as K #backend is tensorflow
get_layer_output = K.function([mymodel.layers[0].input],[mymodel.layers[0].output]) #set up function
x = np.expand_dims(X_train[0],0) #set up a 4D input of 1 image training set
layer_output = get_layer_output([x])[0] #get output using K.function
layer_output.shape #check output shape and use it in next cell, first dimension is number of filters
# --- Now output a mosaic
layeroutput3D = np.squeeze(layer_output)
ncol =4
nrow =np.ceil(numfilters/ncol)
plt.figure()
for i in range(layeroutput3D.shape[0]):
plt.subplot(nrow,ncol,i+1)
plt.imshow(layeroutput3D[i],'gray')
plt.axis('off')
#plt.savefig("test.png", bbox_inches='tight')
plt.show()
print('done plotting layer activation output mosaic')