@@ -46,7 +46,7 @@ func feedforward(inputs: Array[float]) -> Matrix:
4646 ## Feeding our inputs to the activation matrix
4747 var activation_matrix = Matrix .new (inputs .size (), 1 )
4848 for row in range (activation_matrix .no_of_rows ):
49- activation_matrix .set_index (row , 0 , inputs [row ])
49+ activation_matrix .set_index (row , 0 , clamp ( inputs [row ], - 1 , 1 ) )
5050 emit_signal ("activation_changed" , 0 , activation_matrix )
5151
5252 ## Calculate the next layer's activation array using to the weights and biases
@@ -65,10 +65,10 @@ func feedforward(inputs: Array[float]) -> Matrix:
6565
6666
6767## Train the neural network using mini-batch stochastic
68- ## gradient descent. The `` training_data`` is a list of tuples
69- ## ``(x, y)`` representing the training inputs and the desired
68+ ## gradient descent. The training_data is an Array of Arrays
69+ ## [data, expected output] representing the training inputs and the desired
7070## outputs. The other non-optional parameters are
71- ## self-explanatory. If `` test_data`` is provided then the
71+ ## self-explanatory. If test_data is provided then the
7272## network will be evaluated against the test data after each
7373## epoch, and partial progress printed out. This is useful for
7474## tracking progress, but slows things down substantially."""
@@ -79,73 +79,72 @@ func SGD(
7979 eta : float ,
8080 test_data : Array [Array ] = []
8181):
82- var n = len ( training_data )
82+ var n = training_data . size ( )
8383 for j in range (epochs ):
8484 training_data .shuffle ()
8585 for k in range (0 , n , mini_batch_size ):
8686 var mini_batch : Array [Array ] = training_data .slice (k , k + mini_batch_size )
8787 update_mini_batch (mini_batch , eta )
8888 if test_data :
89- print ("Epoch & s: & s / & s" % [str (j ), str (evaluate (test_data )), str (len ( test_data ))])
89+ print ("Epoch % s : % s / % s " % [str (j ), str (evaluate (test_data )), str (test_data . size ( ))])
9090 else :
9191 print ("Epoch %s complete" % str (j ))
9292
93+ if _visualizer :
94+ _visualizer .update_weights (self )
95+
9396
9497## Update the network's weights and biases by applying
9598## gradient descent using backpropagation to a single mini batch.
96- ## The `` mini_batch`` is a list of tuples ``(x, y)`` , and `` eta``
99+ ## The mini_batch is is an Array of Arrays [data, expected output] , and eta
97100## is the learning rate.
98101func update_mini_batch (mini_batch : Array [Array ], eta : float ) -> void :
99102 var total_nabla_b : Array [Matrix ]
100103 var total_nabla_w : Array [Matrix ]
101- for b : Matrix in biases :
102- total_nabla_b .append (Matrix .new (b .no_of_rows , b .no_of_columns ))
103- for w : Matrix in weights :
104- total_nabla_w .append (Matrix .new (w .no_of_rows , w .no_of_columns ))
104+ for i : int in biases .size ():
105+ total_nabla_b .append (Matrix .new (biases [i ].no_of_rows , biases [i ].no_of_columns ))
106+ total_nabla_w .append (Matrix .new (weights [i ].no_of_rows , weights [i ].no_of_columns ))
105107
106108 for activation_and_results : Array [Matrix ] in mini_batch :
107- ## error_array contains [nabla_b, nabla_w]
108109 var error_array = backprop (activation_and_results [0 ], activation_and_results [1 ])
109110 var delta_nabla_b : Array [Matrix ] = error_array [0 ]
110111 var delta_nabla_w : Array [Matrix ] = error_array [1 ]
111112
112113 for i : int in total_nabla_b .size ():
113- for dnb : Matrix in delta_nabla_b :
114- total_nabla_b [i ] = total_nabla_b [i ].add (dnb )
115- for i : int in total_nabla_w .size ():
116- for dnw : Matrix in delta_nabla_w :
117- total_nabla_w [i ] = total_nabla_w [i ].add (dnw )
114+ total_nabla_b [i ] = total_nabla_b [i ].add (delta_nabla_b [i ])
115+ total_nabla_w [i ] = total_nabla_w [i ].add (delta_nabla_w [i ])
118116
119117 # update weights and biases accordinly
120118 for i : int in weights .size ():
121- for nw : Matrix in total_nabla_w :
122- weights [i ] = nw .multiply_scalar (eta / len (mini_batch )).subtract_from (weights [i ])
123-
124- for i : int in biases .size ():
125- for nb : Matrix in total_nabla_b :
126- biases [i ] = nb .multiply_scalar (eta / len (mini_batch )).subtract_from (biases [i ])
119+ weights [i ] = total_nabla_w [i ].multiply_scalar (eta / mini_batch .size ()).subtract_from (weights [i ])
120+ biases [i ] = total_nabla_b [i ].multiply_scalar (eta / mini_batch .size ()).subtract_from (biases [i ])
127121
128122
129123## Return an Array [nabla_b, nabla_w] representing the gradient for the cost function C_x.
130124## nabla_b and nabla_w are layer-by-layer matrices, similar to biases and weights.
131125func backprop (x : Matrix , y : Matrix ):
132126 var nabla_b_array : Array [Matrix ]
133127 var nabla_w_array : Array [Matrix ]
134- for b : Matrix in biases :
135- nabla_b_array .append (Matrix .new (b .no_of_rows , b .no_of_columns ))
136- for w : Matrix in weights :
137- nabla_w_array .append (Matrix .new (w .no_of_rows , w .no_of_columns ))
128+ for i : int in biases .size ():
129+ nabla_b_array .append (Matrix .new (biases [i ].no_of_rows , biases [i ].no_of_columns ))
130+ nabla_w_array .append (Matrix .new (weights [i ].no_of_rows , weights [i ].no_of_columns ))
138131
139132 # feedforward
140- var activation : Matrix = x
133+ var activation_matrix : Matrix = x
141134 var activations : Array [Matrix ] = [x ] # list to store all the activations, layer by layer
142135 var zs : Array [Matrix ] = [] # list to store all the z vectors, layer by layer
143- for b : Matrix in biases :
144- for w : Matrix in weights :
145- var z := w .product_matrix (activation ).add (b )
146- zs .append (z )
147- activation = z .sigmoid ()
148- activations .append (activation )
136+ ## Calculate the next layer's activation array using to the weights and biases
137+ ## the next layer holds for the current layer. (and loop through this procedure till
138+ ## the final layer's activation array is achieved)
139+ for layer in num_layers - 1 :
140+ var bias = biases [layer ] # Next layer's bias for this layer.
141+ var weight = weights [layer ] # Next layer's weight for this layer.
142+ ## Find the activation matrix for the next layer
143+ ## N+1 = Sigmoid of {(Weight).(N) + bias}
144+ var z = weight .product_matrix (activation_matrix ).add (bias )
145+ zs .append (z )
146+ activation_matrix = z .sigmoid ()
147+ activations .append (activation_matrix )
149148
150149 # backward pass
151150 var delta := cost_derivative (activations [- 1 ], y ).multiply_corresponding (zs [- 1 ].sigmoid_prime ())
@@ -154,7 +153,7 @@ func backprop(x: Matrix, y: Matrix):
154153 for l in range (2 , num_layers ):
155154 var z := zs [- l ]
156155 var sp = z .sigmoid_prime ()
157- delta = weights [- l + 1 ].clone (true ).product_matrix (delta ).multiply_corresponding (sp )
156+ delta = weights [- l + 1 ].clone (true ).product_matrix (delta ).multiply_corresponding (sp )
158157 nabla_b_array [- l ] = delta
159158 nabla_w_array [- l ] = delta .product_matrix (activations [- l - 1 ].clone (true ))
160159 return [nabla_b_array , nabla_w_array ]
@@ -163,13 +162,14 @@ func backprop(x: Matrix, y: Matrix):
163162## Return the number of test inputs for which the neural network outputs the correct result.
164163## Note that the neural network's output is assumed to be the index of whichever neuron in the
165164## final layer has the highest activation.
166- func evaluate (test_data : Array [Array ]):
165+ func evaluate (test_data : Array [Array ]) -> int :
167166 var test_results : Array [Array ] = []
168- var sum = 0
169- for sample : Array in test_data :
170- test_results .append ([feedforward (sample [0 ]) .argmax (), sample [1 ]])
167+ var sum : int = 0
168+ for sample : Array [ Matrix ] in test_data :
169+ test_results .append ([feedforward (sample [0 ]. to_array ()) .argmax (), sample [1 ]. argmax () ])
171170 for result : Array [float ] in test_results :
172171 sum += int (result [0 ] == result [1 ])
172+ return sum
173173
174174
175175## Return the vector of partial derivatives
0 commit comments