-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathn_network.py
194 lines (151 loc) · 5.37 KB
/
n_network.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
#! /usr/local/bin/python2.7
from math import exp
import random
class Node(object):
def __init__(self,_id):
self._id = _id
self.con = []
self.con_weights = {}
def get_id(self):
return self._id
def connect(self,node,weight):
"""symetrically connects any two Node objects"""
if not self.is_connected(node):
self.con.append(node)
node.connect(self,weight)
self.set_weight(node,weight)
def set_weight(self,node,weight):
if self.is_connected(node):
self.con_weights[node.get_id()] = float(weight)
def is_connected(self,node):
if node in self.con:
return True
else: return False
def get_connections(self):
""" returns [(node, weight),..] """
connections = []
for node in self.con:
connections.append((node,self.con_weights[node.get_id()]))
return connections
def print_weights(self):
for key, value in self.con_weights.iteritems():
print "node:",self.get_id(),"to",key,"weight",value
def __repr__(self):
return str(self.get_id())
class InputNode(Node):
def set_input(self,val):
self.in_val = val
def get_input(self):
return self.in_val
def update_weight(self, i):
for h_node in self.con:
if type(h_node) == HiddenNode:
new_weight = self.con_weights[h_node.get_id()] \
+ (i * h_node.get_error() * self.in_val)
self.set_weight(h_node,new_weight)
h_node.set_weight(self,new_weight)
class HiddenNode(Node):
def sigmoid(self):
in_values = 0
for in_node in self.con:
if type(in_node) == InputNode:
in_values += in_node.get_input() * self.con_weights[in_node.get_id()]
self.sig = 1 / ( 1 + exp(-in_values) )
def get_sigmoid(self):
return self.sig
def set_error(self):
for out_node in self.con:
if type(out_node) == OutputNode:
self.error = (self.sig*(1-self.sig))* \
(self.con_weights[out_node.get_id()] * out_node.get_error())
def get_error(self):
return self.error
def update_weight(self, i):
for out_node in self.con:
if type(out_node) == OutputNode:
new_weight = self.con_weights[out_node.get_id()] \
+ (i * out_node.get_error() * self.sig)
self.set_weight(out_node,new_weight)
out_node.set_weight(self,new_weight)
class OutputNode(Node):
def set_output(self):
in_values = 0
for in_node in self.con:
if type(in_node) == HiddenNode:
in_values += in_node.get_sigmoid() * self.con_weights[in_node.get_id()]
self.output = 1 / ( 1 + exp(-in_values) )
def error_output(self,expected):
self.error = self.output * ((1 - self.output)*(expected - self.output))
def get_error(self):
return self.error
class NeuralNetwork(object):
"""
Initialize NeuralNetwork by specifying the number of input nodes,
hidden nodes, and output nodes. Call connect_nodes to connect the
nodes and then use forward_prop and back_prop to step through
the propagation steps"""
def __init__(self, in_nodes,h_nodes,o_nodes):
i = 1
self.input_nodes = []
self.hidden_nodes = []
self.output_nodes = []
while i <= in_nodes:
self.input_nodes.append(InputNode(i))
i += 1
while i <= in_nodes + h_nodes:
self.hidden_nodes.append(HiddenNode(i))
i += 1
while i <= in_nodes + h_nodes + o_nodes:
self.output_nodes.append(OutputNode(i))
i += 1
def connect_nodes(self,rand_weight=True):
"""call connect_notes with False to input
initial node weights manually"""
self.connect_input_hidden(rand_weight)
self.connect_hidden_output(rand_weight)
def connect_input_hidden(self,rand_weight):
for node in self.input_nodes:
for h_node in self.hidden_nodes:
if rand_weight:
weight = random.random() * random.choice([-1,1])
else:
weight = raw_input("enter weight between "+\
str(node.get_id())+" and "+str(h_node.get_id())+": ")
node.connect(h_node,float(weight))
def connect_hidden_output(self,rand_weight):
for o_node in self.output_nodes:
for h_node in self.hidden_nodes:
if rand_weight:
weight = random.random() * random.choice([-1,1])
else:
weight = raw_input("enter weight between "+\
str(h_node.get_id())+" and "+str(o_node.get_id())+": ")
o_node.connect(h_node,float(weight))
def forward_prop(self,inputs):
"""call forward_prop with a list of inputs,
input list must be equal to the number of input
nodes"""
assert(len(inputs) == len(self.input_nodes))
for n,in_node in enumerate(self.input_nodes):
in_node.set_input(float(inputs[n]))
for h_node in self.hidden_nodes:
h_node.sigmoid()
for o_node in self.output_nodes:
o_node.set_output()
return [o_node.output for o_node in self.output_nodes]
def back_prop(self,expected,i):
"""call back_prop with expected output of the output
node and i"""
assert(len(expected) == len(self.output_nodes))
for n,o_node in enumerate(self.output_nodes):
o_node.error_output(float(expected[n]))
for h_node in self.hidden_nodes:
h_node.set_error()
for h_node in self.hidden_nodes:
h_node.update_weight(i)
for in_node in self.input_nodes:
in_node.update_weight(i)
return [o_node.error for o_node in self.output_nodes]
def print_net(self):
for node in self.hidden_nodes:
node.print_weights()