Advertisement
Guest User

Untitled

a guest
May 24th, 2016
50
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.85 KB | None | 0 0
  1. #!/usr/bin/env python
  2. # From http://arctrix.com/nas/python/bpnn.py
  3.  
  4. import time, math, random
  5. random.seed(0)
  6.  
  7. def sigmoid(x):
  8.     return math.tanh(x)
  9.  
  10. def dsigmoid(y):
  11.     return 1.0 - y**2
  12.  
  13. def rand(a, b):
  14.     return (b-a)*random.random() + a
  15.  
  16. def makeMatrix(I, J, fill=0.0):
  17.     m = []
  18.     for i in range(I):
  19.         m.append([fill]*J)
  20.     return m
  21.  
  22. class NN:
  23.     def __init__(self, ni, nh, no):
  24.         # number of input, hidden, and output nodes
  25.         self.ni = ni + 1 # +1 for bias node
  26.         self.nh = nh
  27.         self.no = no
  28.  
  29.         # activations for nodes
  30.         self.ai = [1.0]*self.ni
  31.         self.ah = [1.0]*self.nh
  32.         self.ao = [1.0]*self.no
  33.        
  34.         # create weights
  35.         self.wi = makeMatrix(self.ni, self.nh)
  36.         self.wo = makeMatrix(self.nh, self.no)
  37.         # set them to random vaules
  38.         for i in range(self.ni):
  39.             for j in range(self.nh):
  40.                 self.wi[i][j] = rand(-0.2, 0.2)
  41.         for j in range(self.nh):
  42.             for k in range(self.no):
  43.                 self.wo[j][k] = rand(-2.0, 2.0)
  44.  
  45.         # last change in weights for momentum  
  46.         self.ci = makeMatrix(self.ni, self.nh)
  47.         self.co = makeMatrix(self.nh, self.no)
  48.  
  49.     def update(self, inputs):
  50.         if len(inputs) != self.ni-1:
  51.             raise ValueError('wrong number of inputs')
  52.  
  53.         # input activations
  54.         for i in range(self.ni-1):
  55.             #self.ai[i] = sigmoid(inputs[i])
  56.             self.ai[i] = inputs[i]
  57.  
  58.         # hidden activations
  59.         for j in range(self.nh):
  60.             sum = 0.0
  61.             for i in range(self.ni):
  62.                 sum = sum + self.ai[i] * self.wi[i][j]
  63.             self.ah[j] = sigmoid(sum)
  64.  
  65.         # output activations
  66.         for k in range(self.no):
  67.             sum = 0.0
  68.             for j in range(self.nh):
  69.                 sum = sum + self.ah[j] * self.wo[j][k]
  70.             self.ao[k] = sigmoid(sum)
  71.  
  72.         return self.ao[:]
  73.  
  74.  
  75.     def backPropagate(self, targets, N, M):
  76.         if len(targets) != self.no:
  77.             raise ValueError('wrong number of target values')
  78.  
  79.         # calculate error terms for output
  80.         output_deltas = [0.0] * self.no
  81.         for k in range(self.no):
  82.             error = targets[k]-self.ao[k]
  83.             output_deltas[k] = dsigmoid(self.ao[k]) * error
  84.  
  85.         # calculate error terms for hidden
  86.         hidden_deltas = [0.0] * self.nh
  87.         for j in range(self.nh):
  88.             error = 0.0
  89.             for k in range(self.no):
  90.                 error = error + output_deltas[k]*self.wo[j][k]
  91.             hidden_deltas[j] = dsigmoid(self.ah[j]) * error
  92.  
  93.         # update output weights
  94.         for j in range(self.nh):
  95.             for k in range(self.no):
  96.                 change = output_deltas[k]*self.ah[j]
  97.                 self.wo[j][k] = self.wo[j][k] + N*change + M*self.co[j][k]
  98.                 self.co[j][k] = change
  99.                 #print N*change, M*self.co[j][k]
  100.  
  101.         # update input weights
  102.         for i in range(self.ni):
  103.             for j in range(self.nh):
  104.                 change = hidden_deltas[j]*self.ai[i]
  105.                 self.wi[i][j] = self.wi[i][j] + N*change + M*self.ci[i][j]
  106.                 self.ci[i][j] = change
  107.  
  108.         # calculate error
  109.         error = 0.0
  110.         for k in range(len(targets)):
  111.             error = error + 0.5*(targets[k]-self.ao[k])**2
  112.         return error
  113.  
  114.  
  115.     def test(self, patterns, threshold=0.5):
  116.         for p in patterns:
  117.             res = self.update(p[0])
  118.             res = list(map(lambda x:-1 if x < -threshold else 1 if x > threshold else 0,res))
  119.             print(p[0], '->', "+" if res == p[1] else "-", "Got: ", res, "Expected: ", p[1])
  120.  
  121.     def weights(self):
  122.         print('Input weights:')
  123.         for i in range(self.ni):
  124.             print(self.wi[i])
  125.         print()
  126.         print('Output weights:')
  127.         for j in range(self.nh):
  128.             print(self.wo[j])
  129.  
  130.     def train(self, patterns, iterations=1000, N=0.5, M=0.1):
  131.         # N: learning rate
  132.         # M: momentum factor
  133.         for i in range(iterations):
  134.             error = 0.0
  135.             for p in patterns:
  136.                 inputs = p[0]
  137.                 targets = p[1]
  138.                 self.update(inputs)
  139.                 error = error + self.backPropagate(targets, N, M)
  140.             if i % 100 == 0:
  141.                 print('error %-.5f' % error)
  142.  
  143. def fizzbuzz():
  144.     CONSTANTS=[1] # bias node
  145.     def int2bits(n, digits):
  146.         res = [0]*digits
  147.         i = 0
  148.         while n > 0:
  149.             res[i] = int(n) & 1
  150.             i = i + 1
  151.             n = n // 2
  152.         return res
  153.  
  154.     def int2quadbits(n, quadbits):
  155.         res = [0,0,0,0,] * quadbits
  156.         i = 0
  157.         while n > 0:
  158.             res[i:i+4]=int2bits(n%15,4)
  159.             i += 4
  160.             n=n//15
  161.         return CONSTANTS + res
  162.     def fizzbuzz(j):
  163.         F=0
  164.         if j % 15 == 0: return [1,1,F]
  165.         if j % 3 == 0: return [1,F,F]
  166.         if j % 5 == 0: return [F,1,F]
  167.         return [F,F,1]
  168.  
  169.     assert int2bits(11, 4) == [1, 1, 0, 1]
  170.     assert int2quadbits(11, 1) == CONSTANTS+[1, 1, 0, 1]
  171.     assert int2quadbits(37, 1) == CONSTANTS+[1, 1, 1, 0,  0,1,0,0]
  172.  
  173.     pat100 = [[int2quadbits(j,2), fizzbuzz(j)] for j in range(1,101)]
  174.     pat200 = [[int2quadbits(j,2), fizzbuzz(j)] for j in range(101,201)]
  175.  
  176.     inputs  = len(pat200[0][0])
  177.     outputs = len(pat200[0][1])
  178.  
  179.     bp = NN(inputs, inputs+outputs, outputs)
  180.     bp.train(pat200, N=0.05,M=0.2)
  181.     bp.test(pat100)
  182.  
  183.  
  184. def benchmark():
  185.     # XOR
  186.     patterns = [
  187.         [[-1,-1], [-1]],
  188.         [[-1,1], [1]],
  189.         [[1,-1], [1]],
  190.         [[1,1], [-1]],
  191.     ]
  192.  
  193.     bp = NN(2, 3, 1)
  194.     bp.train(patterns, 10000)
  195.     bp.test(patterns)
  196.  
  197. if __name__ == '__main__':
  198.     start = time.clock()
  199.     #benchmark()
  200.     fizzbuzz()
  201.     end = time.clock()
  202.     print
  203.     print (end - start)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement