Class: CooCoo::Network
Instance Attribute Summary collapse
-
#activation_function ⇒ Object
readonly
Returns the value of attribute activation_function.
-
#age ⇒ Object
readonly
Returns the value of attribute age.
-
#command ⇒ Object
Returns the value of attribute command.
-
#comments ⇒ Object
Returns the value of attribute comments.
Class Method Summary collapse
Instance Method Summary collapse
- #adjust_weights!(deltas) ⇒ Object
- #backprop(inputs, outputs, errors, hidden_state = nil) ⇒ Object
- #final_output(outputs) ⇒ Object
- #forward(input, hidden_state = nil, flattened = false, processed = false) ⇒ Object
-
#initialize {|_self| ... } ⇒ Network
constructor
A new instance of Network.
- #layer(new_layer) ⇒ Object
- #layer_index(layer) ⇒ Object
- #layers ⇒ Object
- #learn(input, expecting, rate, cost_function = CostFunctions::MeanSquare, hidden_state = nil) ⇒ Object
- #load!(path) ⇒ Object
- #num_inputs ⇒ Object
- #num_layers ⇒ Object
- #num_outputs ⇒ Object
- #output_activation_function ⇒ Object
- #predict(input, hidden_state = nil, flattened = false, processed = false) ⇒ Object
- #prep_input(input) ⇒ Object
- #prep_output_target(target) ⇒ Object
- #save(path) ⇒ Object
- #to_hash ⇒ Object
- #transfer_errors(deltas) ⇒ Object
- #update_from_hash!(h) ⇒ Object
- #update_weights!(input, outputs, deltas) ⇒ Object
- #weight_deltas(input, outputs, deltas) ⇒ Object
Constructor Details
Instance Attribute Details
#activation_function ⇒ Object (readonly)
Returns the value of attribute activation_function.
12 13 14 |
# File 'lib/coo-coo/network.rb', line 12 def activation_function @activation_function end |
#age ⇒ Object (readonly)
Returns the value of attribute age.
12 13 14 |
# File 'lib/coo-coo/network.rb', line 12 def age @age end |
#command ⇒ Object
Returns the value of attribute command.
13 14 15 |
# File 'lib/coo-coo/network.rb', line 13 def command @command end |
#comments ⇒ Object
Returns the value of attribute comments.
13 14 15 |
# File 'lib/coo-coo/network.rb', line 13 def comments @comments end |
Class Method Details
.from_a(layers) ⇒ Object
212 213 214 |
# File 'lib/coo-coo/network.rb', line 212 def from_a(layers) self.new().update_from_a!(layers) end |
.from_hash(h) ⇒ Object
216 217 218 |
# File 'lib/coo-coo/network.rb', line 216 def from_hash(h) self.new.update_from_hash!(h) end |
.load(path) ⇒ Object
220 221 222 |
# File 'lib/coo-coo/network.rb', line 220 def load(path) self.new().load!(path) end |
Instance Method Details
#adjust_weights!(deltas) ⇒ Object
140 141 142 143 144 145 146 147 |
# File 'lib/coo-coo/network.rb', line 140 def adjust_weights!(deltas) @layers.each_with_index do |layer, i| layer.adjust_weights!(deltas[i]) end @age += 1 self end |
#backprop(inputs, outputs, errors, hidden_state = nil) ⇒ Object
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/coo-coo/network.rb', line 109 def backprop(inputs, outputs, errors, hidden_state = nil) hidden_state ||= Hash.new d = @layers.reverse_each.each_with_index.inject([]) do |acc, (layer, i)| input = if i < (@layers.size - 1) outputs[@layers.size - i - 2] else prep_input(inputs) # TODO condition prep_input end #CooCoo.debug("#{self.class.name}.#{__method__}\t#{i} #{@layers.size - i - 1}\t#{input.size}\t#{outputs.size}") deltas, hidden_state = layer.backprop(input, outputs[@layers.size - i - 1], errors, hidden_state) errors = layer.transfer_error(deltas) acc.unshift(deltas) end return Sequence[d], hidden_state end |
#final_output(outputs) ⇒ Object
73 74 75 |
# File 'lib/coo-coo/network.rb', line 73 def final_output(outputs) outputs.last end |
#forward(input, hidden_state = nil, flattened = false, processed = false) ⇒ Object
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/coo-coo/network.rb', line 77 def forward(input, hidden_state = nil, flattened = false, processed = false) unless flattened || input.kind_of?(CooCoo::Vector) input = CooCoo::Vector[input.to_a.flatten, num_inputs] end hidden_state ||= Hash.new output = if processed input else prep_input(input) end outputs = @layers.each_with_index.inject([]) do |acc, (layer, i)| #debug("Layer: #{i} #{layer.num_inputs} #{layer.size}") #debug("Input: #{input}") #debug("Weights: #{layer.neurons[0].weights}") output, hidden_state = layer.forward(output, hidden_state) acc << output #debug("Output: #{input}") end return outputs, hidden_state end |
#layer(new_layer) ⇒ Object
42 43 44 45 |
# File 'lib/coo-coo/network.rb', line 42 def layer(new_layer) @layers << new_layer self end |
#layer_index(layer) ⇒ Object
38 39 40 |
# File 'lib/coo-coo/network.rb', line 38 def layer_index(layer) @layers.find_index { |l| l.eql?(layer) } end |
#layers ⇒ Object
34 35 36 |
# File 'lib/coo-coo/network.rb', line 34 def layers @layers end |
#learn(input, expecting, rate, cost_function = CostFunctions::MeanSquare, hidden_state = nil) ⇒ Object
162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/coo-coo/network.rb', line 162 def learn(input, expecting, rate, cost_function = CostFunctions::MeanSquare, hidden_state = nil) hidden_state ||= Hash.new output, hidden_state = forward(input, hidden_state) cost = cost_function.derivative(prep_input(expecting), output.last) deltas, hidden_state = backprop(input, output, cost, hidden_state) update_weights!(input, output, deltas * rate) return self, hidden_state rescue CooCoo.debug("Network#learn caught #{$!}", input, expecting) raise end |
#load!(path) ⇒ Object
180 181 182 183 184 185 186 187 |
# File 'lib/coo-coo/network.rb', line 180 def load!(path) yaml = YAML.load(File.read(path)) raise RuntimeError.new("Invalid YAML definition in #{path}") if yaml.nil? update_from_hash!(yaml) self end |
#num_inputs ⇒ Object
22 23 24 |
# File 'lib/coo-coo/network.rb', line 22 def num_inputs @layers.first.num_inputs end |
#num_layers ⇒ Object
30 31 32 |
# File 'lib/coo-coo/network.rb', line 30 def num_layers @layers.size end |
#num_outputs ⇒ Object
26 27 28 |
# File 'lib/coo-coo/network.rb', line 26 def num_outputs @layers.last.size end |
#output_activation_function ⇒ Object
56 57 58 59 60 61 62 63 |
# File 'lib/coo-coo/network.rb', line 56 def output_activation_function unless @output_activation_function layer = @layers.reverse.find { |l| l.activation_function } @output_activation_function = layer.activation_function end @output_activation_function end |
#predict(input, hidden_state = nil, flattened = false, processed = false) ⇒ Object
102 103 104 105 106 107 |
# File 'lib/coo-coo/network.rb', line 102 def predict(input, hidden_state = nil, flattened = false, processed = false) hidden_state ||= Hash.new outputs, hidden_state = forward(input, hidden_state, flattened, processed) out = final_output(outputs) return out, hidden_state end |
#prep_input(input) ⇒ Object
65 66 67 |
# File 'lib/coo-coo/network.rb', line 65 def prep_input(input) activation_function.prep_input(input) end |
#prep_output_target(target) ⇒ Object
69 70 71 |
# File 'lib/coo-coo/network.rb', line 69 def prep_output_target(target) output_activation_function.prep_output_target(target) end |
#save(path) ⇒ Object
174 175 176 177 178 |
# File 'lib/coo-coo/network.rb', line 174 def save(path) File.write_to(path) do |f| f.write(to_hash.to_yaml) end end |
#to_hash ⇒ Object
203 204 205 206 207 208 209 |
# File 'lib/coo-coo/network.rb', line 203 def to_hash { age: @age, command: @command, comments: @comments, layers: @layers.collect { |l| l.to_hash(self) } } end |
#transfer_errors(deltas) ⇒ Object
129 130 131 132 133 |
# File 'lib/coo-coo/network.rb', line 129 def transfer_errors(deltas) @layers.zip(deltas).collect do |layer, delta| layer.transfer_error(delta) end end |
#update_from_hash!(h) ⇒ Object
189 190 191 192 193 194 195 196 197 198 199 200 201 |
# File 'lib/coo-coo/network.rb', line 189 def update_from_hash!(h) @layers = Array.new h[:layers].each do |layer_hash| @layers << CooCoo::LayerFactory.from_hash(layer_hash, self) end @age = h.fetch(:age, 0) @command = h.fetch(:command, nil) @comments = h.fetch(:comments) { Array.new } self end |
#update_weights!(input, outputs, deltas) ⇒ Object
135 136 137 138 |
# File 'lib/coo-coo/network.rb', line 135 def update_weights!(input, outputs, deltas) adjust_weights!(weight_deltas(input, outputs, deltas)) self end |
#weight_deltas(input, outputs, deltas) ⇒ Object
149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/coo-coo/network.rb', line 149 def weight_deltas(input, outputs, deltas) d = @layers.each_with_index.collect do |layer, i| inputs = if i != 0 outputs[i - 1] else prep_input(input) end layer.weight_deltas(inputs, deltas[i]) end d end |