Skip to content

Instantly share code, notes, and snippets.

@stober
Created June 15, 2012 21:12
Show Gist options
  • Save stober/2938728 to your computer and use it in GitHub Desktop.
Save stober/2938728 to your computer and use it in GitHub Desktop.
A simple multilayer backprop network.
#!/usr/bin/python
"""
Author: Jeremy M. Stober
Program: MULTILAYER.PY
Date: Monday, April 14 2008
Description: A simple implementation of a feed-forward multilayer network with back-propagation.
"""
import os, sys, getopt, pdb
from numpy import *
from numpy.random import *
import random as prandom
def logistic(vector):
return 1 / (1 + exp(-vector))
def dlogistic(vector):
return vector * (1 - vector)
def sigmoid(vector):
return tanh(vector)
def dsigmoid(vector):
return 1 - vector**2
class Multilayer(object):
def __init__(self, alpha, eta, ninput, nhidden, noutput):
# Create the weight sets.
self.input = standard_normal((ninput, nhidden))
self.output = standard_normal((nhidden, noutput))
self.storage = {} # Stored activations.
self.alpha = alpha # Momentum!
self.eta = eta #Learning rate!
self.momentum = {'input' : zeros((ninput, nhidden)),
'output' : zeros((nhidden, noutput)) }
def eval(self, input):
# Use array masks if network is not fully connected.
# Sum and squash the weights of the input activations.
hidden = sigmoid(dot(input, self.input))
# Sum and squash the weights of the hidden activations.
output = sigmoid(dot(hidden, self.output))
self.storage = {'input' : input, 'hidden' : hidden, 'output' : output}
# Output elements are in the range (0,1).
return output
def supervise(self, input, response):
# Will store the activations in self.storage.
error = response - self.eval(input)
# Backpropagate the error.
# Note: * is elementwise multiplication.
doutput = error * dsigmoid(self.storage['output'])
dhidden = dot(self.output,doutput) * dsigmoid(self.storage['hidden'])
# We need to store the last change for momentum.
deltas = { 'output' : self.eta * outer(self.storage['hidden'],doutput) + self.alpha * self.momentum['output'],
'input' : self.eta * outer(self.storage['input'], dhidden) + self.alpha * self.momentum['input'] }
self.output = self.output + deltas['output']
self.input = self.input + deltas['input']
self.momentum = deltas
return sum(error ** 2) # Return sum squared error.
def test():
patterns = [(array([0,1]), array([1])),
(array([1,0]), array([1])),
(array([1,1]), array([0])),
(array([0,0]), array([0]))]
multi = Multilayer(0.1, 0.5, 2, 2, 1)
for i in range(10000):
(input,response) = prandom.choice(patterns)
multi.supervise(input, response)
for i in range(10):
(input,response) = prandom.choice(patterns)
print input, multi.eval(input), response
def main():
def usage():
print sys.argv[0] + "[-h] [-d]"
try:
(options, args) = getopt.getopt(sys.argv[1:], 'dh', ['help','debug'])
except getopt.GetoptError:
# print help information and exit:
usage()
sys.exit(2)
for o, a in options:
if o in ('-h', '--help'):
usage()
sys.exit()
elif o in ('-d', '--debug'):
pdb.set_trace()
test()
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment