In [2]:
%matplotlib inline
import matplotlib.pyplot as plt
from matplotlib.pylab import *
from IPython.html.widgets import interact
from scipy.interpolate import griddata
import numpy as np


:0: FutureWarning: IPython widgets are experimental and may change in the future.

In [3]:
from sklearn.datasets import load_digits
digits = load_digits()
print(digits.data.shape)


(1797, 64)

In [4]:
"""Initialize
Creates the random weights that connect the input to the output.  
Currently it uses an input layer, a hidden layer, and an output layer."""

#ni = number of inputs
#nh = hidden nodes
#no = output nodes

ni = 64
nh = 64
no = 10

w = [np.random.rand(ni,nh),np.random.rand(nh,no)]

In [5]:
"""Using matrix multiplication, the input is turned into the output"""
def feed_forward(n,w):
    out = [0,0]
    out[0] = np.dot(n,w[0])
    out[1] = np.dot(out[0],w[1])
    return out

In [6]:
m = [[[1,0],[0,1]],[[1,0],[0,1]]]
n = [1,3]
assert (feed_forward(n,m)[1][0] == 1)
assert (feed_forward(n,m)[1][1] == 3)

In [7]:
"""Here the learning data is fed to the program and the error is computed.
After the batch is done, the sum of the changes that need to be made are computed and executed."""
def update_batch(n,w,batch,c):
    
    c = c + 1
    error = 0
    
    x = np.matrix(digits.images[n]) #These few lines turn the input data into the type of array the network understands
    x = np.reshape(x,(1,64))
    x = x/(np.sum(x)*5)
    
    p = digits.target[n]  #This determines the perfect result for a given input.  Namely, a 1 for the output of
    ideal = np.zeros((1,10)) #the correct number and 0 elsewhere
    ideal[0,p] = 1 
    
    out = feed_forward(x,w)   #The full output of the network for the hidden and output layers
    err1 = (ideal - out[1])   #The error at the output layer is computed
    modw1 = np.dot(np.reshape(out[0],(nh,1)),np.reshape(err1,(1,no)))  #The gradient of the error is computed
    err0 = np.dot(err1,np.transpose(w[1]))  #The error at the hidden layer is computed
    modw0 = np.dot(np.reshape(np.transpose(x),(ni,1)),np.reshape(err0,(1,nh)))  #The gradient of that error is computed
    
    if batch == 0:     #These four lines start or update the current batch
        batch = [err0,modw0,err1,modw1]
    else:
        batch = batch + [err0,modw0,err1,modw1]

    if c > 10:   #After the batch size is reached, the weights are updated and the batch is reset
        w = backprop(w,batch)
        batch = 0
        c = 0
        
    if p != np.argmax(out[1]):  #If the network guessed the wrong number, output an error of 1
        error =  1
        
    return [w,error,batch,c]

In [8]:
def backprop(w,batch):  #This updates the weights of the network accordin to the batch
    LC = .01   #The learning constant determines how large a change to the network will be
    err0 = batch[0]
    modw0 = batch[1]
    err1 = batch[2]
    modw1 = batch[3]
    w[1] = w[1] + LC*modw1
    w[0] = w[0] + LC*modw0
    return w

In [9]:
x = np.random.permutation(1700)
x1 = x[0:1000]
x2 = x[1000:1700]

In [47]:
#The network gets a sample of 1000 digits and practices with them
h = 0
error = 0
c = 0
batch = 0

while h < 10:
    error = 0
    for n in x1:
        bat = update_batch(n,w,batch,c)
        w = bat[0]
        error = error + bat[1]
        batch = bat[2]
        c = bat[3]
        
    h = h + 1
print (error)


73

In [62]:
# np.save('weights0', w[0])
# np.save('weights1', w[1])

In [65]:
w[0] = np.load('weights0.npy')
w[1] = np.load('weights1.npy')

In [66]:
#The network is tested with an additional 700 digits.  It is still learning, but knowing the answer does not assist its error result.
error = 0
n = 1000
for n in x2:

    bat = update_batch(n,w,batch,c)
    #w = bat[0]
    error = error + bat[1]
    batch = bat[2]
    c = bat[3]
    n = n + 1
print (error)


61

In [16]:
#The network in its final form, a digit guesser.
def guess(n,w):
    x = np.matrix(digits.images[n])
    x = np.reshape(x,(1,64))
    x = x/(np.sum(x)*5)
    print("Guess: ",np.argmax(feed_forward(x,w)[1]), "Actual: ", digits.target[n])

In [17]:
b = 1700

In [30]:
guess(b,w)
b = b + 1


Guess:  7 Actual:  3

In [ ]: