Created
April 26, 2012 17:55
-
-
Save yusugomori/2501438 to your computer and use it in GitHub Desktop.
bpnn.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
# Originally from http://arctrix.com/nas/python/bpnn.py | |
import time, math, random | |
random.seed(0) | |
class BPNN: | |
def __init__(self, ni, nh, no): | |
self.ni = ni + 1 | |
self.nh = nh | |
self.no = no | |
self.ai = [1.0]*self.ni | |
self.ah = [1.0]*self.nh | |
self.ao = [1.0]*self.no | |
self.wi = self.makeMatrix(self.ni, self.nh) | |
self.wo = self.makeMatrix(self.nh, self.no) | |
for i in xrange(self.ni): | |
for j in xrange(self.nh): | |
self.wi[i][j] = self.rand(-0.2, 0.2) | |
for j in xrange(self.nh): | |
for k in xrange(self.no): | |
self.wo[j][k] = self.rand(-2.0, 2.0) | |
self.ci = self.makeMatrix(self.ni, self.nh) | |
self.co = self.makeMatrix(self.nh, self.no) | |
def update(self, inputs): | |
if len(inputs) != self.ni-1: | |
raise ValueError('wrong number of inputs') | |
for i in xrange(self.ni-1): | |
self.ai[i] = inputs[i] | |
for j in xrange(self.nh): | |
sum = 0.0 | |
for i in xrange(self.ni): | |
sum = sum + self.ai[i] * self.wi[i][j] | |
self.ah[j] = self.sigmoid(sum) | |
for k in xrange(self.no): | |
sum = 0.0 | |
for j in xrange(self.nh): | |
sum = sum + self.ah[j] * self.wo[j][k] | |
self.ao[k] = self.sigmoid(sum) | |
return self.ao | |
def backPropagate(self, targets, N, M): | |
if len(targets) != self.no: | |
raise ValueError('wrong number of target values') | |
output_deltas = [0.0] * self.no | |
for k in xrange(self.no): | |
error = targets[k]-self.ao[k] | |
output_deltas[k] = self.dsigmoid(self.ao[k]) * error | |
hidden_deltas = [0.0] * self.nh | |
for j in xrange(self.nh): | |
error = 0.0 | |
for k in xrange(self.no): | |
error = error + output_deltas[k]*self.wo[j][k] | |
hidden_deltas[j] = self.dsigmoid(self.ah[j]) * error | |
for j in xrange(self.nh): | |
for k in xrange(self.no): | |
change = output_deltas[k]*self.ah[j] | |
self.wo[j][k] = self.wo[j][k] + N*change + M*self.co[j][k] | |
self.co[j][k] = change | |
for i in xrange(self.ni): | |
for j in xrange(self.nh): | |
change = hidden_deltas[j]*self.ai[i] | |
self.wi[i][j] = self.wi[i][j] + N*change + M*self.ci[i][j] | |
self.ci[i][j] = change | |
error = 0.0 | |
for k in xrange(len(targets)): | |
error = error + 0.5*(targets[k]-self.ao[k])**2 | |
return error | |
def test(self, patterns): | |
for p in patterns: | |
print p[0], '->', self.update(p[0]) | |
def train(self, patterns, iter=100, N=0.5, M=0.1): | |
for i in xrange(iter): | |
error = 0.0 | |
for p in patterns: | |
inputs = p[0] | |
targets = p[1] | |
self.update(inputs) | |
error = error + self.backPropagate(targets, N, M) | |
def rand(self, a, b): | |
return (b-a)*random.random() + a | |
def makeMatrix(self, I, J, fill=0.0): | |
m = [] | |
for i in range(I): | |
m.append([fill]*J) | |
return m | |
def sigmoid(self, x): | |
return math.tanh(x) | |
def dsigmoid(self, y): | |
return 1.0 - y**2 | |
def benchmark(): | |
# XOR | |
patterns = [ | |
[[-1,-1], [-1]], | |
[[-1,1], [1]], | |
[[1,-1], [1]], | |
[[1,1], [-1]], | |
] | |
bp = BPNN(2, 3, 1) | |
bp.train(patterns, 10000) | |
bp.test(patterns) | |
if __name__ == '__main__': | |
start = time.clock() | |
benchmark() | |
end = time.clock() | |
print end - start |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment