// Basic backpropagating neural network in Python
1
2 import random
3
4 class NN:
5 def __init__(self, numInputs, numOutputs, numLayers, numNodesPerLayer, learnRate=0.25, threshold=1, sigCoef=0.5):
6 self.weights = []
7 self.nodes = []
8 self.lambd = learnRate
9 self.a = sigCoef
10
11 self.nodes.append([])
12 for x in range(numInputs):
13 self.nodes[0].append([0,0,threshold])
14 for x in range(numLayers):
15 self.nodes.append([])
16 for y in range(numNodesPerLayer):
17 self.nodes[x+1].append([0,0,threshold])
18 self.nodes.append([])
19 for x in range(numOutputs):
20 self.nodes[-1].append([0,0,threshold])
21
22 for x in range(numLayers+3):
23 self.weights.append([])
24 for x in range(numInputs):
25 self.weights[0].append(1)
26 for x in range(numLayers+1):
27 for y in range(len(self.nodes[x])*len(self.nodes[x+1])):
28 self.weights[x+1].append(self.rand())
29 for x in range(numOutputs):
30 self.weights[-1].append(1)
31
32 def rand(self):
33 return random.uniform(0,1)
34
35 def sigmoid(self, inpt):
36 output = 1/(1+(2.71828183**((-self.a)*inpt)))
37 return output
38
39 def sigMyZ(self, nodeLoc):
40 d = self.nodes[nodeLoc[0]][nodeLoc[1]][0]
41 theta = self.nodes[nodeLoc[0]][nodeLoc[1]][2]
42 z = self.sigmoid(d + theta)
43 self.nodes[nodeLoc[0]][nodeLoc[1]][0] = z
44
45 def passX(self, nodeLoc):
46 if nodeLoc[0]>0:
47 self.sigMyZ(nodeLoc)
48
49 z = self.nodes[nodeLoc[0]][nodeLoc[1]][0]
50 lenOfNextLayer = len(self.nodes[nodeLoc[0]+1])
51 for nextNode in range(lenOfNextLayer):
52 self.nodes[nodeLoc[0]+1][nextNode][0] += (self.weights[nodeLoc[0]+1][(nodeLoc[1]*lenOfNextLayer)+nextNode]*z)
53
54 def runOnce(self, inpt, returns):
55 output = []
56
57 for x in range(len(self.nodes[0])):
58 self.nodes[0][x][0] = inpt[x]
59
60 for x in range(len(self.nodes)-1):
61 for y in range(len(self.nodes[x])):
62 self.passX([x,y])
63
64 for x in range(len(self.nodes[-1])):
65 self.sigMyZ([-1,x])
66 output.append(self.nodes[-1][x][0])
67
68 if returns == 1:
69 return output
70
71 def backProp(self, y):
72
73 for x in range(len(self.nodes[-1])):
74 z = self.nodes[-1][x][0]
75 self.nodes[-1][x][0] = 0
76 self.nodes[-1][x][1] = (z*(1-z)*(y[x]-z))
77 dTheta = self.nodes[-1][x][1]*self.lambd
78 self.nodes[-1][x][2] += dTheta
79 count = 0
80 for weight in range(x,len(self.weights[-2]),len(self.nodes[-1])):
81 self.weights[-2][weight] += (dTheta*self.nodes[-2][count][0])
82 count += 1
83
84
85 for layer in range(2,len(self.nodes)):
86 lenOfThisLayer = len(self.nodes[(-layer)])
87 lenOfNextLayer = len(self.nodes[(-layer)+1])
88 for currentNode in range(lenOfThisLayer):
89 z = self.nodes[-layer][currentNode][0]
90 self.nodes[-layer][currentNode][0] = 0
91 g = 0
92 for nextNode in range(lenOfNextLayer):
93 g += (self.nodes[(-layer)+1][nextNode][1]*self.weights[-layer][(currentNode*lenOfNextLayer)+nextNode])
94 self.nodes[-layer][currentNode][1] = (z*(1-z)*g)
95 dTheta = self.nodes[-layer][currentNode][1]*(self.lambd)
96 self.nodes[-layer][currentNode][2] += dTheta
97 count = 0
98 for weight in range(currentNode,len(self.weights[(-layer)-1]),lenOfThisLayer):
99 self.weights[(-layer)-1][weight] += (dTheta*self.nodes[(-layer)-1][count][0])
100 count += 1
101
102 def getLayers(self):
103 return self.nodes
104
105 def getWeights(self):
106 return self.weights
107
108