from math import *
import random
from random import random as r
class NN:
def __init__(self):
# initialize node-activations
self.ai = [1.0]*ni
self.ah = [1.0]*nh
self.ao = [1.0]*no
self.Aah = [0.0]*nh
self.Aao = [0.0]*no
self.Ach, self.Aco = [0]*nh, [0]*no
self.wi = [ [r() for j in range(nh)] for i in range(ni) ]
self.wo = [ [r() for k in range(no)] for j in range(nh) ]
self.ci = [[0.0]*nh]*ni
self.co = [[0.0]*no]*nh
def runNN (self, inputs):
self.ai = inputs
self.ah = [ sig(sum([ self.ai[i]*self.wi[i][j] for i in range(ni) ])) for j in range(nh)]
self.ao = [ sig(sum([ self.ah[j]*self.wo[j][k] for j in range(nh) ])) for k in range(no)]
return self.ao
def backPropagate (self, targets, N, M):
output_deltas = [0.0] * no
for k in range(no):
error = targets[k] - self.ao[k]
output_deltas[k] = error * dsig(self.ao[k])
for j in range(nh):
for k in range(no):
change = output_deltas[k] * self.ah[j]
self.wo[j][k] += N*change + M*self.co[j][k]
self.co[j][k] = change
# calc hidden deltas
hidden_deltas = [0.0] * nh
for j in range(nh):
error = 0.0
for k in range(no):
error += output_deltas[k] * self.wo[j][k]
hidden_deltas[j] = error * dsig(self.ah[j])
#update input weights
for i in range (ni):
for j in range (nh):
change = hidden_deltas[j] * self.ai[i]
self.wi[i][j] += N*change + M*self.ci[i][j]
self.ci[i][j] = change
# calc combined error
# 1/2 for differential convenience & **2 for modulus
error = 0.0
for k in range(len(targets)):
error = 0.5 * (targets[k]-self.ao[k])**2
return error
def test(self, patterns):
for p in patterns:
inputs = p[0]
print 'Inputs:', p[0], '-->', self.runNN(inputs), '\tTarget', p[1]
def BP(self, patterns, N, M,i):
for p in patterns:
inputs = p[0]
targets = p[1]
self.runNN(inputs)
error = self.backPropagate(targets, N, M)
if i % 50 == 0:
print str(i).zfill(len(str(max_iterations-1))),'Combined error', error
def NGA(self, pat,i ):
for p in pat:
inputs = p[0]
targets = p[1]
self.astrocyteactions(inputs)
def astrocyteactions (self, inputs):
for m in range(M_iters):
self.ai = inputs
for j in range(nh):
self.ah[j] = sig(sum([ self.ai[i]*self.wi[i][j] for i in range(ni) ]))
if self.ah[j] > 0: self.Aah[j] +=1
else: self.Aah[j] -=1
if self.Aah[j] == Athresh:
self.Ach[j] = Adur
elif self.Aah[j] == -Athresh:
self.Ach[j] = -Adur
if self.Ach[j] > 0:
for i in range(ni):
self.wi[i][j] += self.wi[i][j]*0.25
self.Ach[j] -=1
elif self.Ach[j] < 0:
for i in range(ni):
self.wi[i][j] += self.wi[i][j]*-0.5
self.Ach[j] +=1
for k in range(no):
self.ao[k] = sig(sum([ self.ah[j]*self.wo[j][k] for j in range(nh) ]))
if self.ao[k] > 0: self.Aao[k] +=1
else: self.Aao[k] -=1
if self.Aao[k] == Athresh:
self.Aco[k] = Adur
elif self.Aao[k] == -Athresh:
self.Aco[k] = -Adur
if self.Aco[k] > 0:
for j in range(nh):
self.wo[j][k] += self.wo[j][k]*0.25
self.Aco[k] -=1
elif self.Aco[k] < 0:
for j in range(nh):
self.wo[j][k] += self.wo[j][k]*-0.5
self.Aco[k] +=1
return self.ao
def weights(self):
print 'Input weights:'
for i in range(ni):
print map(lambda x: round(x,2),self.wi[i])
print
print 'Output weights:'
for j in range(nh):
print map(lambda x: round(x,2),self.wo[j])
print ''
def train (self, patterns):
for i in range(max_iterations):
self.BP(patterns, N, M,i)
self.NGA(patterns,i)
self.test(patterns)
self.weights()
def sig (x):
return tanh(x)
def dsig (y):
return 1 - y**2
max_iterations = 10000
N=0.2
M=0.1
M_iters = 8
Athresh, Adur = 2, 3
ni, nh, no = 2,2,1
pat = [
[[0,0], [0]],
[[0,1], [1]],
[[1,0], [1]],
[[1,1], [0]]
]
def main ():
myNN = NN()
myNN.train(pat)
if __name__ == "__main__":
main()
Diff to Previous Revision
--- revision 2 2012-10-03 09:07:06
+++ revision 3 2012-10-03 20:59:44
@@ -3,12 +3,7 @@
from random import random as r
class NN:
- def __init__(self, NI, NH, NO):
- # number of nodes in layers
- self.ni = NI
- self.nh = NH
- self.no = NO
-
+ def __init__(self):
# initialize node-activations
self.ai = [1.0]*ni
self.ah = [1.0]*nh
@@ -29,28 +24,28 @@
def backPropagate (self, targets, N, M):
- output_deltas = [0.0] * self.no
- for k in range(self.no):
+ output_deltas = [0.0] * no
+ for k in range(no):
error = targets[k] - self.ao[k]
output_deltas[k] = error * dsig(self.ao[k])
- for j in range(self.nh):
- for k in range(self.no):
+ for j in range(nh):
+ for k in range(no):
change = output_deltas[k] * self.ah[j]
self.wo[j][k] += N*change + M*self.co[j][k]
self.co[j][k] = change
# calc hidden deltas
- hidden_deltas = [0.0] * self.nh
- for j in range(self.nh):
+ hidden_deltas = [0.0] * nh
+ for j in range(nh):
error = 0.0
- for k in range(self.no):
+ for k in range(no):
error += output_deltas[k] * self.wo[j][k]
hidden_deltas[j] = error * dsig(self.ah[j])
#update input weights
- for i in range (self.ni):
- for j in range (self.nh):
+ for i in range (ni):
+ for j in range (nh):
change = hidden_deltas[j] * self.ai[i]
self.wi[i][j] += N*change + M*self.ci[i][j]
self.ci[i][j] = change
@@ -74,7 +69,7 @@
self.runNN(inputs)
error = self.backPropagate(targets, N, M)
if i % 50 == 0:
- print 'Combined error', error
+ print str(i).zfill(len(str(max_iterations-1))),'Combined error', error
def NGA(self, pat,i ):
for p in pat:
@@ -122,11 +117,11 @@
def weights(self):
print 'Input weights:'
- for i in range(self.ni):
+ for i in range(ni):
print map(lambda x: round(x,2),self.wi[i])
print
print 'Output weights:'
- for j in range(self.nh):
+ for j in range(nh):
print map(lambda x: round(x,2),self.wo[j])
print ''
@@ -151,14 +146,14 @@
M_iters = 8
Athresh, Adur = 2, 3
ni, nh, no = 2,2,1
+ pat = [
+ [[0,0], [0]],
+ [[0,1], [1]],
+ [[1,0], [1]],
+ [[1,1], [0]]
+ ]
def main ():
- pat = [
- [[0,0], [0]],
- [[0,1], [1]],
- [[1,0], [1]],
- [[1,1], [0]]
- ]
- myNN = NN(ni, nh, no)
+ myNN = NN()
myNN.train(pat)