33 KiB
33 KiB
In [2]:
# %load partSix.py
# Neural Networks Demystified
# Part 6: Training
#
# Supporting code for short YouTube series on artificial neural networks.
#
# Stephen Welch
# @stephencwelch
## ----------------------- Part 1 ---------------------------- ##
import numpy as np
# X = (hours sleeping, hours studying), y = Score on test
X = np.array(([3,5], [5,1], [10,2]), dtype=float)
y = np.array(([75], [82], [93]), dtype=float)
# Normalize
X = X/np.amax(X, axis=0)
y = y/100 #Max test score is 100
## ----------------------- Part 5 ---------------------------- ##
class Neural_Network(object):
def __init__(self):
#Define Hyperparameters
self.inputLayerSize = 2
self.outputLayerSize = 1
self.hiddenLayerSize = 3
#Weights (parameters)
self.W1 = np.random.randn(self.inputLayerSize,self.hiddenLayerSize)
self.W2 = np.random.randn(self.hiddenLayerSize,self.outputLayerSize)
def forward(self, X):
#Propogate inputs though network
self.z2 = np.dot(X, self.W1)
self.a2 = self.sigmoid(self.z2)
self.z3 = np.dot(self.a2, self.W2)
yHat = self.sigmoid(self.z3)
return yHat
def sigmoid(self, z):
#Apply sigmoid activation function to scalar, vector, or matrix
return 1/(1+np.exp(-z))
def sigmoidPrime(self,z):
#Gradient of sigmoid
return np.exp(-z)/((1+np.exp(-z))**2)
def costFunction(self, X, y):
#Compute cost for given X,y, use weights already stored in class.
self.yHat = self.forward(X)
J = 0.5*sum((y-self.yHat)**2)
return J
def costFunctionPrime(self, X, y):
#Compute derivative with respect to W and W2 for a given X and y:
self.yHat = self.forward(X)
delta3 = np.multiply(-(y-self.yHat), self.sigmoidPrime(self.z3))
dJdW2 = np.dot(self.a2.T, delta3)
delta2 = np.dot(delta3, self.W2.T)*self.sigmoidPrime(self.z2)
dJdW1 = np.dot(X.T, delta2)
return dJdW1, dJdW2
#Helper Functions for interacting with other classes:
def getParams(self):
#Get W1 and W2 unrolled into vector:
params = np.concatenate((self.W1.ravel(), self.W2.ravel()))
return params
def setParams(self, params):
#Set W1 and W2 using single paramater vector.
W1_start = 0
W1_end = self.hiddenLayerSize * self.inputLayerSize
self.W1 = np.reshape(params[W1_start:W1_end], (self.inputLayerSize , self.hiddenLayerSize))
W2_end = W1_end + self.hiddenLayerSize*self.outputLayerSize
self.W2 = np.reshape(params[W1_end:W2_end], (self.hiddenLayerSize, self.outputLayerSize))
def computeGradients(self, X, y):
dJdW1, dJdW2 = self.costFunctionPrime(X, y)
return np.concatenate((dJdW1.ravel(), dJdW2.ravel()))
def computeNumericalGradient(N, X, y):
paramsInitial = N.getParams()
numgrad = np.zeros(paramsInitial.shape)
perturb = np.zeros(paramsInitial.shape)
e = 1e-4
for p in range(len(paramsInitial)):
#Set perturbation vector
perturb[p] = e
N.setParams(paramsInitial + perturb)
loss2 = N.costFunction(X, y)
N.setParams(paramsInitial - perturb)
loss1 = N.costFunction(X, y)
#Compute Numerical Gradient
numgrad[p] = (loss2 - loss1) / (2*e)
#Return the value we changed to zero:
perturb[p] = 0
#Return Params to original value:
N.setParams(paramsInitial)
return numgrad
## ----------------------- Part 6 ---------------------------- ##
from scipy import optimize
class trainer(object):
def __init__(self, N):
#Make Local reference to network:
self.N = N
def callbackF(self, params):
self.N.setParams(params)
self.J.append(self.N.costFunction(self.X, self.y))
def costFunctionWrapper(self, params, X, y):
self.N.setParams(params)
cost = self.N.costFunction(X, y)
grad = self.N.computeGradients(X,y)
return cost, grad
def train(self, X, y):
#Make an internal variable for the callback function:
self.X = X
self.y = y
#Make empty list to store costs:
self.J = []
params0 = self.N.getParams()
options = {'maxiter': 200, 'disp' : True}
_res = optimize.minimize(self.costFunctionWrapper, params0, jac=True, method='BFGS', \
args=(X, y), options=options, callback=self.callbackF)
self.N.setParams(_res.x)
self.optimizationResults = _res
In [3]:
print("Input Data", X)
print("Output Data", y)Input Data [[0.3 1. ] [0.5 0.2] [1. 0.4]] Output Data [[0.75] [0.82] [0.93]]
In [4]:
#Untrained Random Network
NN = Neural_Network()
y1 = NN.forward(X)
print("Untrained Output", y1)Untrained Output [[0.40080444] [0.43447789] [0.42423465]]
In [5]:
#Training step
T = trainer(NN)
T.train(X,y)Optimization terminated successfully.
Current function value: 0.000000
Iterations: 51
Function evaluations: 56
Gradient evaluations: 56
In [6]:
#Trained Network
y2 = NN.forward(X)
print("Trained Output",y2)
Trained Output [[0.75003127] [0.81998936] [0.92991079]]
In [8]:
#Put your code here
def MSE(y, yhat):
return (1/len(y1))*sum((y-yhat)**2)
print(MSE(y, y1))
print(MSE(y, y2))[0.17545447] [3.01663395e-09]
In [9]:
class Neural_Network(Neural_Network):
def __init__(self,insize, outsize, hiddensize):
#Define Hyperparameters
self.inputLayerSize = insize
self.outputLayerSize = outsize
self.hiddenLayerSize = hiddensize
#Weights (parameters)
self.W1 = np.random.randn(self.inputLayerSize,self.hiddenLayerSize)
self.W2 = np.random.randn(self.hiddenLayerSize,self.outputLayerSize)In [39]:
#Untrained Random Network
NN = Neural_Network(2,1,5)
y1 = NN.forward(X)
print("Untrained Output", y1)Untrained Output [[0.40867166] [0.36286813] [0.35807708]]
In [40]:
T = trainer(NN)
T.train(X,y)Optimization terminated successfully.
Current function value: 0.000000
Iterations: 51
Function evaluations: 53
Gradient evaluations: 53
In [41]:
#Trained Network
y2 = NN.forward(X)
print("Trained Output",y2)
Trained Output [[0.75000449] [0.81997275] [0.92997594]]
In [42]:
print(MSE(y, y1))
print(MSE(y, y2))[0.21752347] [4.47242084e-10]
In [100]:
%matplotlib inline
import matplotlib.pylab as plt
import numpy as np
from sklearn.datasets import fetch_lfw_people, load_digits
from sklearn.cross_validation import train_test_split
sk_data = load_digits();
#Cool slider to browse all of the images.
from ipywidgets import interact
def browse_images(images, labels, categories):
n = len(images)
def view_image(i):
plt.imshow(images[i], cmap=plt.cm.gray_r, interpolation='nearest')
plt.title('%s' % categories[labels[i]])
plt.axis('off')
plt.show()
interact(view_image, i=(0,n-1))
browse_images(sk_data.images, sk_data.target, sk_data.target_names)
feature_vectors = sk_data.data
class_labels = sk_data.target
categories = sk_data.target_names
N, h, w = sk_data.images.shape
train_vectors, test_vectors, train_labels, test_labels = train_test_split(feature_vectors, class_labels, test_size=0.25, random_state=1)In [114]:
train_vectors = train_vectors/train_vectors.max()
train_vectors = train_vectors
train_labels = train_labels.reshape(1347,1)
train_labels = train_labels/train_labels.max()
print(train_vectors.shape)
print(train_labels.shape)
print(train_labels)(1347, 64) (1347, 1) [[0.22222222] [0.66666667] [0.66666667] ... [1. ] [0.11111111] [0.55555556]]
In [138]:
#Run the training.
# X = np.array(([3,5], [5,1], [10,2]), dtype=float) 2,1,3
# y = np.array(([75], [82], [93]), dtype=float)
NN = Neural_Network(64,1,10) #len(train_vectors)
NN.forward(train_vectors)
Out [138]:
array([[1.14594026e-02],
[1.83245292e-03],
[2.81387785e-03],
...,
[1.97903197e-02],
[2.87355695e-02],
[8.32694764e-06]])In [139]:
T = trainer(NN)
T.train(train_vectors, train_labels)[0;31m---------------------------------------------------------------------------[0m
[0;31mKeyboardInterrupt[0m Traceback (most recent call last)
[0;32m<ipython-input-139-4310d4908f49>[0m in [0;36m<module>[0;34m()[0m
[1;32m 1[0m [0mT[0m [1;33m=[0m [0mtrainer[0m[1;33m([0m[0mNN[0m[1;33m)[0m[1;33m[0m[0m
[0;32m----> 2[0;31m [0mT[0m[1;33m.[0m[0mtrain[0m[1;33m([0m[0mtrain_vectors[0m[1;33m,[0m [0mtrain_labels[0m[1;33m)[0m[1;33m[0m[0m
[0m
[0;32m<ipython-input-2-71cf4520db29>[0m in [0;36mtrain[0;34m(self, X, y)[0m
[1;32m 141[0m [1;33m[0m[0m
[1;32m 142[0m [0moptions[0m [1;33m=[0m [1;33m{[0m[1;34m'maxiter'[0m[1;33m:[0m [1;36m200[0m[1;33m,[0m [1;34m'disp'[0m [1;33m:[0m [1;32mTrue[0m[1;33m}[0m[1;33m[0m[0m
[0;32m--> 143[0;31m [0m_res[0m [1;33m=[0m [0moptimize[0m[1;33m.[0m[0mminimize[0m[1;33m([0m[0mself[0m[1;33m.[0m[0mcostFunctionWrapper[0m[1;33m,[0m [0mparams0[0m[1;33m,[0m [0mjac[0m[1;33m=[0m[1;32mTrue[0m[1;33m,[0m [0mmethod[0m[1;33m=[0m[1;34m'BFGS'[0m[1;33m,[0m [0margs[0m[1;33m=[0m[1;33m([0m[0mX[0m[1;33m,[0m [0my[0m[1;33m)[0m[1;33m,[0m [0moptions[0m[1;33m=[0m[0moptions[0m[1;33m,[0m [0mcallback[0m[1;33m=[0m[0mself[0m[1;33m.[0m[0mcallbackF[0m[1;33m)[0m[1;33m[0m[0m
[0m[1;32m 144[0m [1;33m[0m[0m
[1;32m 145[0m [0mself[0m[1;33m.[0m[0mN[0m[1;33m.[0m[0msetParams[0m[1;33m([0m[0m_res[0m[1;33m.[0m[0mx[0m[1;33m)[0m[1;33m[0m[0m
[0;32mC:\Users\Maxwell\AppData\Roaming\Python\Python36\site-packages\scipy\optimize\_minimize.py[0m in [0;36mminimize[0;34m(fun, x0, args, method, jac, hess, hessp, bounds, constraints, tol, callback, options)[0m
[1;32m 479[0m [1;32mreturn[0m [0m_minimize_cg[0m[1;33m([0m[0mfun[0m[1;33m,[0m [0mx0[0m[1;33m,[0m [0margs[0m[1;33m,[0m [0mjac[0m[1;33m,[0m [0mcallback[0m[1;33m,[0m [1;33m**[0m[0moptions[0m[1;33m)[0m[1;33m[0m[0m
[1;32m 480[0m [1;32melif[0m [0mmeth[0m [1;33m==[0m [1;34m'bfgs'[0m[1;33m:[0m[1;33m[0m[0m
[0;32m--> 481[0;31m [1;32mreturn[0m [0m_minimize_bfgs[0m[1;33m([0m[0mfun[0m[1;33m,[0m [0mx0[0m[1;33m,[0m [0margs[0m[1;33m,[0m [0mjac[0m[1;33m,[0m [0mcallback[0m[1;33m,[0m [1;33m**[0m[0moptions[0m[1;33m)[0m[1;33m[0m[0m
[0m[1;32m 482[0m [1;32melif[0m [0mmeth[0m [1;33m==[0m [1;34m'newton-cg'[0m[1;33m:[0m[1;33m[0m[0m
[1;32m 483[0m return _minimize_newtoncg(fun, x0, args, jac, hess, hessp, callback,
[0;32mC:\Users\Maxwell\AppData\Roaming\Python\Python36\site-packages\scipy\optimize\optimize.py[0m in [0;36m_minimize_bfgs[0;34m(fun, x0, args, jac, callback, gtol, norm, eps, maxiter, disp, return_all, **unknown_options)[0m
[1;32m 1003[0m [0mA1[0m [1;33m=[0m [0mI[0m [1;33m-[0m [0msk[0m[1;33m[[0m[1;33m:[0m[1;33m,[0m [0mnumpy[0m[1;33m.[0m[0mnewaxis[0m[1;33m][0m [1;33m*[0m [0myk[0m[1;33m[[0m[0mnumpy[0m[1;33m.[0m[0mnewaxis[0m[1;33m,[0m [1;33m:[0m[1;33m][0m [1;33m*[0m [0mrhok[0m[1;33m[0m[0m
[1;32m 1004[0m [0mA2[0m [1;33m=[0m [0mI[0m [1;33m-[0m [0myk[0m[1;33m[[0m[1;33m:[0m[1;33m,[0m [0mnumpy[0m[1;33m.[0m[0mnewaxis[0m[1;33m][0m [1;33m*[0m [0msk[0m[1;33m[[0m[0mnumpy[0m[1;33m.[0m[0mnewaxis[0m[1;33m,[0m [1;33m:[0m[1;33m][0m [1;33m*[0m [0mrhok[0m[1;33m[0m[0m
[0;32m-> 1005[0;31m Hk = numpy.dot(A1, numpy.dot(Hk, A2)) + (rhok * sk[:, numpy.newaxis] *
[0m[1;32m 1006[0m sk[numpy.newaxis, :])
[1;32m 1007[0m [1;33m[0m[0m
[0;31mKeyboardInterrupt[0m: In [ ]:
pred_labels = NN.forward(train_vectors)
print("Training Data error", np.sum(np.sqrt((train_labels - pred_labels)*(train_labels-pred_labels)))/len(train_vectors))
In [ ]:
pred_labels = NN.forward(test_vectors)
print("Testing Data error", np.sum(np.sqrt((test_labels - pred_labels)*(test_labels-pred_labels)))/len(test_vectors))
In [ ]:
# Pay attention to how the plotting code rescales the data labels,
# if you scaled them differently, you may need to change this code.
def plot_gallery(images, true_titles, pred_titles, h, w, n_row=5, n_col=5):
"""Helper function to plot a gallery of portraits"""
plt.figure(figsize=(1.8 * n_col, 2.4 * n_row))
plt.subplots_adjust(bottom=0, left=.01, right=.99, top=.90, hspace=.35)
for i in range(n_row * n_col):
plt.subplot(n_row, n_col, i + 1)
plt.imshow(images[i].reshape((h, w)), cmap=plt.cm.gray_r)
plt.title(np.round(pred_titles[i]*10, 2))
plt.xlabel('Actual='+str(true_titles[i]), size=9)
plt.xticks(())
plt.yticks(())
plot_gallery(test_vectors, test_labels, pred_labels, h,w)In [ ]:
# Put your installation code here
In [ ]:
# Put your example code here
In [ ]:
# Put your Grade example code here
In [ ]:
# Put your Digits example code here
In [ ]:
from IPython.display import HTML
HTML(
"""
<iframe
src="https://goo.gl/forms/nRQj6A0xZHgrS4WK2"
width="80%"
height="500px"
frameborder="0"
marginheight="0"
marginwidth="0">
Loading...
</iframe>
"""
)