rann 0.2.7 → 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b604698cf3630cf7056f4b10d5b1b301292074b4
4
- data.tar.gz: a341f41f53c78db0f026948b7bad72ff04574e54
3
+ metadata.gz: 2cd393e231a8a1da7a732eff0ea1e82008cc5dcc
4
+ data.tar.gz: 479d4669daab9e8f2fd60b06044d754e78479ad9
5
5
  SHA512:
6
- metadata.gz: 3e7167b3fb0fb79d0fcd3fc7a72b59d0ab4c9d29b69e6fbc230599b11752b3b9e001c06e9bef284325974649e7f64d4f34dd05864fe1fedb9fa7786ef9d40586
7
- data.tar.gz: 6816e982c0536c21a474e377c87ca6de213b62268dfda48317d2c360972e2fa2d0f32eb491c8a088cccae8ca3bb5ef367587d601db2a7eda3d45d695a6c5ea8a
6
+ metadata.gz: 55e2b084f9477543cdc8bbb3cd415e80bfd6c3f75517b61cd1969e9070aa2045c27a6003655394414414c11155cbf042aa597d8ef4798bdf4a2ffcfedd02782e
7
+ data.tar.gz: c2ca6ed22034d63d2a256d7a898b8c5c3c12fcf5674d133e34e405357740ca11ba2002ad26c5506e56b861349db42c8ede21bbc22ba57957bc447b515d4bdef1
data/CHANGES.md CHANGED
@@ -1,3 +1,46 @@
1
+ - More backprop fixes..
2
+
3
+ *Michael Campbell*
4
+
5
+ - Give LSTM input neurons linear activation.
6
+
7
+ *Michael Campbell*
8
+
9
+ - For context neurons connected to a product neuron, it's initial value should
10
+ be 1.
11
+
12
+ *Michael Campbell*
13
+
14
+ - So. Many. Bugs. Turns out the product neuron stuff was still broken and
15
+ network evaluation wasn't behaving correctly with context neurons (recurrent
16
+ connections). Also an error in timestep handling during backprop, and just
17
+ generally network traversal ...
18
+
19
+ *Michael Campbell*
20
+
21
+ - Don't lock the input connections into the LSTM layer, that acts as the fully
22
+ connected part of the network and that's where the majority of learning takes
23
+ place, derp.
24
+
25
+ *Michael Campbell*
26
+
27
+ - Don't change the weight of a LockedConnection during initialisation. (eugh)
28
+
29
+ *Michael Campbell*
30
+
31
+ - Fix bug in backprop over product neuron.
32
+
33
+ *Michael Campbell*
34
+
35
+ - Worked out how to use BigDecimal properly, lol. Refactored to use
36
+ `BigDecimal.limit`.
37
+
38
+ *Michael Campbell*
39
+
40
+ - Allow customisable precision, defaults to 10.
41
+
42
+ *Michael Campbell*
43
+
1
44
  ## 0.2.7 (December 2, 2017)
2
45
 
3
46
  - Allow different weights to the different gates in the LSTM. Previously it was
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rann (0.2.7)
4
+ rann (0.2.8)
5
5
  parallel (~> 1.12, >= 1.12.0)
6
6
  ruby-graphviz (~> 1.2, >= 1.2.3)
7
7
 
@@ -0,0 +1,57 @@
1
+ # A reproduction of the wonderful step by step backprop example at
2
+ # https://mattmazur.com/2015/03/17/a-step-by-step-backpropagation-example/
3
+
4
+ require "bundler/setup"
5
+ require "rann"
6
+
7
+ # inputs
8
+ inputs = Array.new(2){ |i| RANN::Neuron.new "input #{i}", 0, :input, :sig }
9
+
10
+ # hidden layer
11
+ hiddens = Array.new(2){ |i| RANN::Neuron.new "hidden #{i}", 3, :standard, :sig }
12
+ hidden_bias = RANN::Neuron.new "bias", 0, :bias
13
+
14
+ # output layer
15
+ outputs = Array.new(2){ |i| RANN::Neuron.new "output #{i}", 3, :output, :sig }
16
+ output_bias = RANN::Neuron.new "bias", 0, :bias
17
+
18
+ # connect it all w/initial weights
19
+ connections = []
20
+ connections << RANN::Connection.new(inputs[0], hiddens[0], 0.15.to_d)
21
+ connections << RANN::Connection.new(inputs[0], hiddens[1], 0.25.to_d)
22
+ connections << RANN::Connection.new(inputs[1], hiddens[0], 0.2.to_d)
23
+ connections << RANN::Connection.new(inputs[1], hiddens[1], 0.3.to_d)
24
+ connections << RANN::Connection.new(hidden_bias, hiddens[0], 0.35.to_d)
25
+ connections << RANN::Connection.new(hidden_bias, hiddens[1], 0.35.to_d)
26
+
27
+ connections << RANN::Connection.new(hiddens[0], outputs[0], 0.4.to_d)
28
+ connections << RANN::Connection.new(hiddens[0], outputs[1], 0.5.to_d)
29
+ connections << RANN::Connection.new(hiddens[1], outputs[0], 0.45.to_d)
30
+ connections << RANN::Connection.new(hiddens[1], outputs[1], 0.55.to_d)
31
+ connections << RANN::Connection.new(output_bias, outputs[0], 0.6.to_d)
32
+ connections << RANN::Connection.new(output_bias, outputs[1], 0.6.to_d)
33
+
34
+ network = RANN::Network.new connections
35
+ backprop = RANN::Backprop.new network
36
+
37
+ inputs = [0.05.to_d, 0.10.to_d]
38
+ targets = [0.1.to_d, 0.99.to_d]
39
+ outputs = network.evaluate [0.05.to_d, 0.10.to_d]
40
+
41
+ puts "forward prop outputs: #{outputs.map(&:to_f).inspect}"
42
+
43
+ network.reset!
44
+
45
+ gradients, error =
46
+ RANN::Backprop.run_single(
47
+ network,
48
+ [0.05.to_d, 0.10.to_d],
49
+ [0.01.to_d, 0.99.to_d]
50
+ )
51
+
52
+ puts "error: #{error.to_f}"
53
+ puts "backprop gradients & updates:"
54
+ gradients.each do |cid, g|
55
+ c = network.connections.find{ |c| c.id == cid }
56
+ puts "#{c.input_neuron.name} -> #{c.output_neuron.name}: g = #{g.to_f}, u = #{(c.weight - 0.5.to_d * g).to_f}"
57
+ end
@@ -7,3 +7,6 @@ require "rann/product_neuron"
7
7
  require "rann/connection"
8
8
  require "rann/locked_connection"
9
9
  require "rann/backprop"
10
+
11
+ BigDecimal.mode BigDecimal::EXCEPTION_ALL, true
12
+ BigDecimal.limit 10
@@ -12,9 +12,9 @@ module RANN
12
12
 
13
13
  ACTIVATION_DERIVATIVES = {
14
14
  relu: ->(x){ x > 0 ? 1.to_d : 0.to_d },
15
- sig: ->(x){ x.mult(1 - x, 10) },
15
+ sig: ->(x){ x * (1 - x) },
16
16
  linear: ->(_){ 1.to_d },
17
- tanh: ->(x){ 1 - x.power(2, 10) },
17
+ tanh: ->(x){ 1 - x ** 2 },
18
18
  step: ->(_){ 0.to_d },
19
19
  }
20
20
 
@@ -60,9 +60,9 @@ module RANN
60
60
  gradients, error = Backprop.run_single network, input, targets[i + j]
61
61
 
62
62
  gradients.each do |cid, g|
63
- group_avg_gradients[cid] += g.div batch_size, 10
63
+ group_avg_gradients[cid] += g / batch_size
64
64
  end
65
- group_avg_error += error.div batch_size, 10
65
+ group_avg_error += error / batch_size
66
66
  end
67
67
 
68
68
  group_avg_gradients.default_proc = nil
@@ -113,64 +113,80 @@ module RANN
113
113
  error = mse targets, outputs
114
114
 
115
115
  # backward pass with unravelling for recurrent networks
116
- node_deltas = Hash.new{ |h, k| h[k] = Hash.new 0.to_d }
117
- gradients = Hash.new 0.to_d
118
-
116
+ node_deltas = Hash.new{ |h, k| h[k] = {} }
119
117
  initial_timestep = inputs.size - 1
120
118
  neuron_stack = network.output_neurons.map{ |n| [n, initial_timestep] }
119
+ # initialize network end-point node_deltas in all timesteps with zero
120
+ network.neurons_with_no_outgoing_connections.each do |n|
121
+ (0...(inputs.size - 1)).each do |i|
122
+ node_deltas[i][n.id] = 0.to_d
123
+ neuron_stack << [n, i]
124
+ end
125
+ end
126
+ gradients = Hash.new 0.to_d
121
127
 
122
128
  while current = neuron_stack.shift
123
129
  neuron, timestep = current
124
130
  next if node_deltas[timestep].key? neuron.id
125
131
 
126
- from_here = bptt_connecting_to neuron, network, timestep
127
- neuron_stack.push *from_here
128
-
129
132
  # neuron delta is summation of neuron deltas deltas for the connections
130
133
  # from this neuron
131
- step_one =
132
- if neuron.output?
133
- output_index = network.output_neurons.index neuron
134
- mse_delta targets[output_index], outputs[output_index]
135
- else
134
+ if neuron.output?
135
+ output_index = network.output_neurons.index neuron
136
+ step_one = mse_delta targets[output_index], outputs[output_index]
137
+ else
138
+ sum =
136
139
  network.connections_from(neuron).reduce 0.to_d do |m, c|
137
140
  out_timestep = c.output_neuron.context? ? timestep + 1 : timestep
138
141
  output_node_delta = node_deltas[out_timestep][c.output_neuron.id]
139
142
 
140
- # connection delta is the output neuron delta multiplied by the
141
- # connection's weight
142
- connection_delta =
143
- if c.output_neuron.is_a? ProductNeuron
144
- intermediate = states[out_timestep][:intermediates][c.output_neuron.id]
145
- output_node_delta.mult intermediate.div(states[timestep][:values][c.input_neuron.id], 10), 10
146
- else
147
- output_node_delta.mult c.weight, 10
148
- end
149
-
150
- m + connection_delta
143
+ if out_timestep > initial_timestep
144
+ m
145
+ elsif !output_node_delta
146
+ break
147
+ else
148
+ # connection delta is the output neuron delta multiplied by the
149
+ # connection's weight
150
+ connection_delta =
151
+ if c.output_neuron.is_a? ProductNeuron
152
+ intermediate =
153
+ network.connections_to(c.output_neuron).reject{ |c2| c2 == c }.reduce 1.to_d do |m, c2|
154
+ m * states[timestep][:values][c2.input_neuron.id] * c2.weight
155
+ end
156
+ output_node_delta * intermediate * c.weight
157
+ else
158
+ output_node_delta * c.weight
159
+ end
160
+
161
+ m + connection_delta
162
+ end
151
163
  end
152
- end
164
+
165
+ step_one = sum || next
166
+ end
167
+
168
+ from_here = bptt_connecting_to neuron, network, timestep
169
+ neuron_stack |= from_here
153
170
 
154
171
  node_delta =
155
172
  ACTIVATION_DERIVATIVES[neuron.activation_function]
156
- .call(states[timestep][:values][neuron.id])
157
- .mult(step_one, 10)
173
+ .call(states[timestep][:values][neuron.id]) *
174
+ step_one
158
175
 
159
176
  node_deltas[timestep][neuron.id] = node_delta
160
177
 
178
+ in_timestep = neuron.context? ? timestep - 1 : timestep
161
179
  network.connections_to(neuron).each do |c|
162
- in_timestep = neuron.context? ? timestep - 1 : timestep
163
-
164
180
  # connection gradient is the output neuron delta multipled by the
165
181
  # connection's input neuron value.
166
182
  gradient =
167
183
  if c.output_neuron.is_a? ProductNeuron
168
184
  intermediate = states[timestep][:intermediates][c.output_neuron.id]
169
- node_delta.mult intermediate.div(c.weight, 10), 10
185
+ node_delta * intermediate / c.weight
170
186
  elsif c.input_neuron.context? && timestep == 0
171
187
  0.to_d
172
188
  else
173
- node_delta.mult states[in_timestep][:values][c.input_neuron.id], 10
189
+ node_delta * states[in_timestep][:values][c.input_neuron.id]
174
190
  end
175
191
 
176
192
  gradients[c.id] += gradient
@@ -192,7 +208,7 @@ module RANN
192
208
  end
193
209
  end
194
210
 
195
- def restore filepath
211
+ def restore filepath = nil
196
212
  unless filepath
197
213
  filepath = Dir['*'].select{ |f| f =~ /rann_savepoint_.*/ }.sort.last
198
214
 
@@ -217,7 +233,7 @@ module RANN
217
233
  total_squared_error = 0.to_d
218
234
 
219
235
  targets.size.times do |i|
220
- total_squared_error += (targets[i] - outputs[i]).power(2, 10).div(2, 10)
236
+ total_squared_error += (targets[i] - outputs[i]) ** 2 / 2
221
237
  end
222
238
 
223
239
  total_squared_error
@@ -231,11 +247,12 @@ module RANN
231
247
  # halt traversal if we're at a context and we're at the base timestep
232
248
  return [] if neuron.context? && timestep == 0
233
249
 
250
+ timestep -= 1 if neuron.context?
251
+
234
252
  network.connections_to(neuron).each.with_object [] do |c, a|
235
253
  # don't enqueue connections from inputs
236
254
  next if c.input_neuron.input?
237
255
 
238
- timestep -= timestep if neuron.context?
239
256
  a << [c.input_neuron, timestep]
240
257
  end
241
258
  end
@@ -25,7 +25,7 @@ module RANN
25
25
 
26
26
  def process
27
27
  if processable? && !processed?
28
- out_value = input_neuron.value.mult weight, 10
28
+ out_value = input_neuron.value * weight
29
29
  output_neuron.push_value! out_value
30
30
  @processed = true
31
31
  end
@@ -60,8 +60,9 @@ module RANN
60
60
  if output_neuron.context?
61
61
  1.to_d
62
62
  else
63
- rand.to_d 10
63
+ rand.to_d BigDecimal.limit
64
64
  end
65
65
  end
66
66
  end
67
67
  end
68
+
@@ -1,15 +1,17 @@
1
1
  module RANN
2
2
  class GradientChecker
3
- EPSILON = 10.to_d.power -4, 10
3
+ def self.epsilon
4
+ 10.to_d ** -4
5
+ end
4
6
 
5
7
  def self.check network, inputs, targets, dvec
6
8
  gradapprox = []
7
9
 
8
10
  network.params.size.times do |i|
9
11
  thetaplus = network.params.dup
10
- thetaplus[i] = thetaplus[i] + EPSILON
12
+ thetaplus[i] = thetaplus[i] + epsilon
11
13
  thetaminus = network.params.dup
12
- thetaminus[i] = thetaminus[i] - EPSILON
14
+ thetaminus[i] = thetaminus[i] - epsilon
13
15
 
14
16
  network.impose thetaplus
15
17
  outputs = network.evaluate inputs
@@ -21,7 +23,7 @@ module RANN
21
23
  error_thetaminus = error outputs, targets
22
24
  network.reset!
23
25
 
24
- gradapprox[i] = (error_thetaplus - error_thetaminus).div(EPSILON.mult(2, 10), 10)
26
+ gradapprox[i] = (error_thetaplus - error_thetaminus) / (epsilon * 2)
25
27
  end
26
28
 
27
29
  gradapprox.each.with_index.with_object [] do |(ga, i), res|
@@ -33,7 +35,7 @@ module RANN
33
35
  total_squared_error = 0.to_d
34
36
 
35
37
  targets.size.times do |i|
36
- total_squared_error += (targets[i] - outputs[i]).power(2, 10).div(2, 10)
38
+ total_squared_error += (targets[i] - outputs[i]) ** 2 / 2
37
39
  end
38
40
 
39
41
  total_squared_error
@@ -19,52 +19,46 @@ module RANN
19
19
 
20
20
  def init
21
21
  @size.times do |j|
22
- input = RANN::Neuron.new("LSTM #{name} Input #{j}", 0, :standard).tap{ |n| @network.add n }
22
+ input = RANN::Neuron.new("LSTM #{name} Input #{j}", 0, :standard, :linear).tap{ |n| @network.add n }
23
23
  @inputs << input
24
24
 
25
25
  f = RANN::Neuron.new("LSTM #{name} F #{j}", 3, :standard, :sig).tap{ |n| @network.add n }
26
26
  i = RANN::Neuron.new("LSTM #{name} I #{j}", 4, :standard, :sig).tap{ |n| @network.add n }
27
27
  g = RANN::Neuron.new("LSTM #{name} G #{j}", 3, :standard, :tanh).tap{ |n| @network.add n }
28
28
  o = RANN::Neuron.new("LSTM #{name} O #{j}", 3, :standard, :sig).tap{ |n| @network.add n }
29
- bias_f = RANN::Neuron.new("LSTM #{name} Bias F #{j}", 0, :bias).tap do |n|
30
- @network.add n
31
- end
32
- bias_i = RANN::Neuron.new("LSTM #{name} Bias I #{j}", 0, :bias).tap do |n|
33
- @network.add n
34
- end
35
- bias_g = RANN::Neuron.new("LSTM #{name} Bias G #{j}", 0, :bias).tap do |n|
36
- @network.add n
37
- end
38
- bias_o = RANN::Neuron.new("LSTM #{name} Bias O #{j}", 0, :bias).tap do |n|
39
- @network.add n
40
- end
29
+ bias_f = RANN::Neuron.new("LSTM #{name} Bias F #{j}", 0, :bias).tap{ |n| @network.add n }
30
+ bias_i = RANN::Neuron.new("LSTM #{name} Bias I #{j}", 0, :bias).tap{ |n| @network.add n }
31
+ bias_g = RANN::Neuron.new("LSTM #{name} Bias G #{j}", 0, :bias).tap{ |n| @network.add n }
32
+ bias_o = RANN::Neuron.new("LSTM #{name} Bias O #{j}", 0, :bias).tap{ |n| @network.add n }
41
33
  memory_product = RANN::ProductNeuron.new("LSTM #{name} Mem Product #{j}", 2, :standard, :linear).tap{ |n| @network.add n }
42
34
  i_g_product = RANN::ProductNeuron.new("LSTM #{name} Hidden 2/3 Product #{j}", 2, :standard, :linear).tap{ |n| @network.add n }
43
35
  memory_standard = RANN::Neuron.new("LSTM #{name} Mem Standard #{j}", 2, :standard, :linear).tap{ |n| @network.add n }
44
36
  memory_tanh = RANN::Neuron.new("LSTM #{name} Mem Tanh #{j}", 1, :standard, :tanh).tap{ |n| @network.add n }
45
37
  memory_o_product = RANN::ProductNeuron.new("LSTM #{name} Mem/Hidden 4 Product #{j}", 2, :standard, :linear).tap{ |n| @network.add n }
46
- output = RANN::Neuron.new("LSTM #{name} Output #{j}", 1, :standard, :linear).tap{ |n| @network.add n }
47
- @outputs << output
48
- memory_context = RANN::Neuron.new("LSTM #{name} Mem Context #{j}", 1, :context).tap{ |n| @network.add n }
38
+ @outputs << memory_o_product
39
+ memory_context =
40
+ RANN::Neuron.new("LSTM #{name} Mem Context #{j}", 1, :context).tap do |n|
41
+ @network.add n
42
+ n.value = 1.to_d # connecting to a product neuron
43
+ end
49
44
  output_context = RANN::Neuron.new("LSTM #{name} Output Context #{j}", 1, :context).tap{ |n| @network.add n }
50
45
 
51
46
  @network.add RANN::Connection.new input, f
52
47
  @network.add RANN::Connection.new input, i
53
48
  @network.add RANN::Connection.new input, g
54
49
  @network.add RANN::Connection.new input, o
55
- @network.add RANN::LockedConnection.new f, memory_product, 1
56
- @network.add RANN::LockedConnection.new i, i_g_product, 1
57
- @network.add RANN::LockedConnection.new g, i_g_product, 1
58
- @network.add RANN::LockedConnection.new i_g_product, memory_standard, 1
59
- @network.add RANN::LockedConnection.new memory_product, memory_standard, 1
60
- @network.add RANN::LockedConnection.new memory_standard, memory_tanh, 1
61
- @network.add RANN::LockedConnection.new o, memory_o_product, 1
62
- @network.add RANN::LockedConnection.new memory_tanh, memory_o_product, 1
63
- @network.add RANN::LockedConnection.new memory_o_product, output, 1
64
- @network.add RANN::LockedConnection.new memory_standard, memory_context, 1
65
- @network.add RANN::LockedConnection.new memory_context, memory_product, 1
66
- @network.add RANN::LockedConnection.new memory_context, i, 1
67
- @network.add RANN::LockedConnection.new memory_o_product, output_context, 1
50
+ @network.add RANN::LockedConnection.new f, memory_product, 1.to_d
51
+ @network.add RANN::LockedConnection.new i, i_g_product, 1.to_d
52
+ @network.add RANN::LockedConnection.new g, i_g_product, 1.to_d
53
+ @network.add RANN::LockedConnection.new i_g_product, memory_standard, 1.to_d
54
+ @network.add RANN::LockedConnection.new memory_product, memory_standard, 1.to_d
55
+ @network.add RANN::LockedConnection.new memory_standard, memory_tanh, 1.to_d
56
+ @network.add RANN::LockedConnection.new o, memory_o_product, 1.to_d
57
+ @network.add RANN::LockedConnection.new memory_tanh, memory_o_product, 1.to_d
58
+ @network.add RANN::LockedConnection.new memory_standard, memory_context, 1.to_d
59
+ @network.add RANN::LockedConnection.new memory_context, memory_product, 1.to_d
60
+ @network.add RANN::LockedConnection.new memory_context, i, 1.to_d
61
+ @network.add RANN::LockedConnection.new memory_o_product, output_context, 1.to_d
68
62
  @network.add RANN::Connection.new output_context, f
69
63
  @network.add RANN::Connection.new output_context, i
70
64
  @network.add RANN::Connection.new output_context, g
@@ -78,7 +72,7 @@ module RANN
78
72
 
79
73
  def add_input neuron
80
74
  @inputs.each do |input|
81
- @network.add RANN::LockedConnection.new neuron, input, 1
75
+ @network.add RANN::Connection.new neuron, input
82
76
  end
83
77
  end
84
78
  end
@@ -41,7 +41,7 @@ module RANN
41
41
  # would probably be easier to detect circular dependency this way too?
42
42
  begin
43
43
  i = 0
44
- until output_neurons.all?{ |neuron| neuron.value }
44
+ until connections.select(&:enabled?).all? &:processed?
45
45
  i += 1
46
46
  connections.each do |connection|
47
47
  next if !connection.enabled?
@@ -167,11 +167,15 @@ module RANN
167
167
 
168
168
  def init_normalised!
169
169
  connections.each do |c|
170
+ next if c.locked?
171
+
170
172
  out_cons = c.output_neuron.connection_count.to_d
171
- from = -1.to_d.div out_cons.sqrt(10), 10
172
- to = 1.to_d.div out_cons.sqrt(10), 10
173
- c.weight = (to - from).mult(rand.to_d, 10) + from
173
+ from = -1.to_d / out_cons.sqrt(0)
174
+ to = 1.to_d / out_cons.sqrt(0)
175
+ c.weight = (to - from) * rand.to_d + from
174
176
  end
177
+
178
+ true
175
179
  end
176
180
  alias init_normalized! init_normalised!
177
181
 
@@ -179,6 +183,16 @@ module RANN
179
183
  neurons.each do |neuron|
180
184
  neuron.connection_count = connections.count{ |c| c.output_neuron == neuron }
181
185
  end
186
+
187
+ true
188
+ end
189
+
190
+ def neurons_with_no_outgoing_connections
191
+ return @no_outgoing if defined? @no_outgoing
192
+
193
+ neurons.select do |n|
194
+ connections_from(n).none?
195
+ end
182
196
  end
183
197
  end
184
198
  end
@@ -1,12 +1,13 @@
1
1
  require "securerandom"
2
2
  require "bigdecimal"
3
+ require "bigdecimal/math"
3
4
  require "bigdecimal/util"
4
5
 
5
6
  module RANN
6
7
  class Neuron
7
8
  ACTIVATION_FUNCTIONS = {
8
- sig: ->(v){ 1.to_d.div(1 + Math::E.to_d.power(-v, 10), 10) },
9
- tanh: ->(v){ Math.tanh(v).to_d(10) },
9
+ sig: ->(v){ 1.to_d / (1 + BigMath.E(BigDecimal.limit) ** -v) },
10
+ tanh: ->(v){ Math.tanh(v).to_d(BigDecimal.limit) },
10
11
  relu: ->(v){ [0.to_d, v].max },
11
12
  linear: ->(v){ v },
12
13
  step: ->(v){ v > 0.5 ? 1.to_d : 0.to_d },
@@ -73,7 +74,7 @@ module RANN
73
74
  end
74
75
 
75
76
  def initial_activation_function
76
- if standard? || context?
77
+ if standard?
77
78
  :relu
78
79
  else
79
80
  :linear
@@ -12,9 +12,9 @@ module RANN
12
12
  end
13
13
 
14
14
  def update grad, cid
15
- @historical_gradient[cid] = @historical_gradient[cid] + grad.power(2, 10)
15
+ @historical_gradient[cid] = @historical_gradient[cid] + grad ** 2
16
16
 
17
- grad.mult(- @learning_rate.div(@fudge_factor + @historical_gradient[cid].sqrt(10), 10), 10)
17
+ grad * - @learning_rate / (@fudge_factor + @historical_gradient[cid].sqrt(0))
18
18
  end
19
19
 
20
20
  # anything that gets modified over the course of training
@@ -13,9 +13,9 @@ module RANN
13
13
  end
14
14
 
15
15
  def update grad, cid
16
- @historical_gradient[cid] = @decay.mult(@historical_gradient[cid], 10) + (1 - @decay).mult(grad.power(2, 10), 10)
16
+ @historical_gradient[cid] = @decay * @historical_gradient[cid] + (1 - @decay) * grad ** 2
17
17
 
18
- grad.mult(- @learning_rate.div(@fudge_factor + @historical_gradient[cid].sqrt(10), 10), 10)
18
+ grad * - @learning_rate / (@fudge_factor + @historical_gradient[cid].sqrt(0))
19
19
  end
20
20
 
21
21
  # anything that gets modified over the course of training
@@ -5,7 +5,7 @@ module RANN
5
5
  attr_accessor :intermediate
6
6
 
7
7
  def set_value!
8
- @intermediate = incoming.reduce{ |i, m| m.mult(i, 10) }
8
+ @intermediate = incoming.reduce :*
9
9
  self.value = ACTIVATION_FUNCTIONS[activation_function].call @intermediate
10
10
  end
11
11
  end
@@ -1,3 +1,3 @@
1
1
  module RANN
2
- VERSION = "0.2.7"
2
+ VERSION = "0.2.8"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rann
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.7
4
+ version: 0.2.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Campbell
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-12-02 00:00:00.000000000 Z
11
+ date: 2017-12-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parallel
@@ -110,6 +110,7 @@ files:
110
110
  - bench/xor_benchmark.rb
111
111
  - bin/console
112
112
  - bin/setup
113
+ - examples/step_by_step.rb
113
114
  - examples/xor.rb
114
115
  - lib/rann.rb
115
116
  - lib/rann/backprop.rb