Class: CooCoo::Convolution::BoxLayer
- Defined in:
- lib/coo-coo/convolution.rb
Instance Attribute Summary collapse
-
#delta_accumulator ⇒ Object
readonly
Returns the value of attribute delta_accumulator.
-
#height ⇒ Object
readonly
Returns the value of attribute height.
-
#horizontal_step ⇒ Object
readonly
Returns the value of attribute horizontal_step.
-
#input_height ⇒ Object
readonly
Returns the value of attribute input_height.
-
#input_width ⇒ Object
readonly
Returns the value of attribute input_width.
-
#int_output_height ⇒ Object
readonly
Returns the value of attribute int_output_height.
-
#int_output_width ⇒ Object
readonly
Returns the value of attribute int_output_width.
-
#internal_layer ⇒ Object
readonly
Returns the value of attribute internal_layer.
-
#vertical_step ⇒ Object
readonly
Returns the value of attribute vertical_step.
-
#width ⇒ Object
readonly
Returns the value of attribute width.
Class Method Summary collapse
Instance Method Summary collapse
- #==(other) ⇒ Object
- #activation_function ⇒ Object
- #adjust_weights!(deltas) ⇒ Object
- #backprop(input, output, errors, hidden_state) ⇒ Object
-
#each_area ⇒ Object
private.
- #flatten_areas(outputs, w, h, inner_width) ⇒ Object
- #forward(input, hidden_state) ⇒ Object
- #horizontal_span ⇒ Object
-
#initialize(width, height, horizontal_step, vertical_step, internal_layer, input_width, input_height, int_output_width, int_output_height, update_weights_with = :average) ⇒ BoxLayer
constructor
A new instance of BoxLayer.
- #neurons ⇒ Object
- #num_inputs ⇒ Object
- #output_height ⇒ Object
- #output_width ⇒ Object
- #size ⇒ Object
- #slice_input(input, grid_x, grid_y) ⇒ Object
- #slice_output(output, grid_x, grid_y) ⇒ Object
- #to_hash(network = nil) ⇒ Object
- #transfer_error(deltas) ⇒ Object
- #update_weights!(inputs, deltas) ⇒ Object
- #vertical_span ⇒ Object
- #weight_deltas(inputs, deltas) ⇒ Object
Constructor Details
#initialize(width, height, horizontal_step, vertical_step, internal_layer, input_width, input_height, int_output_width, int_output_height, update_weights_with = :average) ⇒ BoxLayer
Returns a new instance of BoxLayer.
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/coo-coo/convolution.rb', line 19 def initialize(width, height, horizontal_step, vertical_step, internal_layer, input_width, input_height, int_output_width, int_output_height, update_weights_with = :average) @internal_layer = internal_layer @width = width @height = height @horizontal_step = horizontal_step @vertical_step = vertical_step @input_width = input_width @input_height = input_height raise ArgumentError.new("Input size mismatch: #{input_width * input_height} is not #{internal_layer.num_inputs}") if internal_layer.num_inputs != (input_width * input_height) @int_output_width = int_output_width @int_output_height = int_output_height raise ArgumentError.new("Input size mismatch: #{int_output_width * int_output_height} is not #{internal_layer.size}") if internal_layer.size != (int_output_width * int_output_height) @delta_accumulator = delta_accumulator || :average raise ArgumentError.new("Weights delta accumulator can only be averaged or summed") unless [ :average, :sum ].include?(@delta_accumulator) end |
Instance Attribute Details
#delta_accumulator ⇒ Object (readonly)
Returns the value of attribute delta_accumulator.
17 18 19 |
# File 'lib/coo-coo/convolution.rb', line 17 def delta_accumulator @delta_accumulator end |
#height ⇒ Object (readonly)
Returns the value of attribute height.
9 10 11 |
# File 'lib/coo-coo/convolution.rb', line 9 def height @height end |
#horizontal_step ⇒ Object (readonly)
Returns the value of attribute horizontal_step.
10 11 12 |
# File 'lib/coo-coo/convolution.rb', line 10 def horizontal_step @horizontal_step end |
#input_height ⇒ Object (readonly)
Returns the value of attribute input_height.
13 14 15 |
# File 'lib/coo-coo/convolution.rb', line 13 def input_height @input_height end |
#input_width ⇒ Object (readonly)
Returns the value of attribute input_width.
12 13 14 |
# File 'lib/coo-coo/convolution.rb', line 12 def input_width @input_width end |
#int_output_height ⇒ Object (readonly)
Returns the value of attribute int_output_height.
15 16 17 |
# File 'lib/coo-coo/convolution.rb', line 15 def int_output_height @int_output_height end |
#int_output_width ⇒ Object (readonly)
Returns the value of attribute int_output_width.
14 15 16 |
# File 'lib/coo-coo/convolution.rb', line 14 def int_output_width @int_output_width end |
#internal_layer ⇒ Object (readonly)
Returns the value of attribute internal_layer.
16 17 18 |
# File 'lib/coo-coo/convolution.rb', line 16 def internal_layer @internal_layer end |
#vertical_step ⇒ Object (readonly)
Returns the value of attribute vertical_step.
11 12 13 |
# File 'lib/coo-coo/convolution.rb', line 11 def vertical_step @vertical_step end |
#width ⇒ Object (readonly)
Returns the value of attribute width.
8 9 10 |
# File 'lib/coo-coo/convolution.rb', line 8 def width @width end |
Class Method Details
.from_hash(h, network = nil) ⇒ Object
165 166 167 168 169 170 171 172 |
# File 'lib/coo-coo/convolution.rb', line 165 def self.from_hash(h, network = nil) self.new(h.fetch(:width), h.fetch(:height), h.fetch(:horizontal_step), h.fetch(:vertical_step), LayerFactory.from_hash(h.fetch(:internal_layer)), h.fetch(:input_width), h.fetch(:input_height), h.fetch(:int_output_width), h.fetch(:int_output_height), h.fetch(:delta_accumulator, :average)) end |
Instance Method Details
#==(other) ⇒ Object
136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/coo-coo/convolution.rb', line 136 def ==(other) other.kind_of?(self.class) && width == other.width && height == other.height && horizontal_step == other.horizontal_step && vertical_step == other.vertical_step && input_width == other.input_width && input_height == other.input_height && int_output_width == other.int_output_width && int_output_height == other.int_output_height && internal_layer == other.internal_layer && delta_accumulator == other.delta_accumulator end |
#activation_function ⇒ Object
35 36 37 |
# File 'lib/coo-coo/convolution.rb', line 35 def activation_function internal_layer.activation_function end |
#adjust_weights!(deltas) ⇒ Object
114 115 116 117 |
# File 'lib/coo-coo/convolution.rb', line 114 def adjust_weights!(deltas) @internal_layer.adjust_weights!(deltas) self end |
#backprop(input, output, errors, hidden_state) ⇒ Object
92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/coo-coo/convolution.rb', line 92 def backprop(input, output, errors, hidden_state) hs = hidden_state[self] || Array.new deltas = each_area do |grid_x, grid_y| hs_index = grid_y * horizontal_span + grid_x d, layer_hs = @internal_layer.backprop(slice_input(input, grid_x, grid_y), slice_output(output, grid_x, grid_y), slice_output(errors, grid_x, grid_y), hs[hs_index]) hs[hs_index] = layer_hs d end hidden_state[self] = hs [ Sequence[deltas.collect { |d| Sequence[d] }], hidden_state ] end |
#each_area ⇒ Object
private
176 177 178 179 180 181 182 183 184 |
# File 'lib/coo-coo/convolution.rb', line 176 def each_area return to_enum(:each_area) unless block_given? vertical_span.to_i.times.collect do |grid_y| horizontal_span.to_i.times.collect do |grid_x| yield(grid_x, grid_y) end end end |
#flatten_areas(outputs, w, h, inner_width) ⇒ Object
67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/coo-coo/convolution.rb', line 67 def flatten_areas(outputs, w, h, inner_width) out = CooCoo::Vector.new(w * h) each_area do |grid_x, grid_y| area_output = outputs[grid_y][grid_x] gx = grid_x * w / horizontal_span.to_f gy = grid_y * h / vertical_span.to_f out.set2d!(w, area_output, inner_width, gx, gy) end out end |
#forward(input, hidden_state) ⇒ Object
80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/coo-coo/convolution.rb', line 80 def forward(input, hidden_state) hs = hidden_state[self] || Array.new outputs = each_area do |grid_x, grid_y| hs_index = (grid_y * horizontal_span + grid_x).to_i output, layer_hs = @internal_layer.forward(slice_input(input, grid_x, grid_y), hs[hs_index]) hs[hs_index] = layer_hs output end hidden_state[self] = hs [ flatten_areas(outputs, horizontal_span * int_output_width, vertical_span * int_output_height, int_output_width), hidden_state ] end |
#horizontal_span ⇒ Object
39 40 41 |
# File 'lib/coo-coo/convolution.rb', line 39 def horizontal_span @horizontal_span ||= (@width / @horizontal_step.to_f).ceil end |
#neurons ⇒ Object
63 64 65 |
# File 'lib/coo-coo/convolution.rb', line 63 def neurons internal_layer.neurons end |
#num_inputs ⇒ Object
47 48 49 |
# File 'lib/coo-coo/convolution.rb', line 47 def num_inputs @width * @height end |
#output_height ⇒ Object
55 56 57 |
# File 'lib/coo-coo/convolution.rb', line 55 def output_height (vertical_span * int_output_height).to_i end |
#output_width ⇒ Object
51 52 53 |
# File 'lib/coo-coo/convolution.rb', line 51 def output_width (horizontal_span * int_output_width).to_i end |
#size ⇒ Object
59 60 61 |
# File 'lib/coo-coo/convolution.rb', line 59 def size output_height * output_width end |
#slice_input(input, grid_x, grid_y) ⇒ Object
186 187 188 189 190 191 192 193 194 |
# File 'lib/coo-coo/convolution.rb', line 186 def slice_input(input, grid_x, grid_y) origin_x = grid_x * @horizontal_step origin_y = grid_y * @vertical_step input.slice_2d(@width, @height, origin_x, origin_y, @input_width, @input_height, 0.0) end |
#slice_output(output, grid_x, grid_y) ⇒ Object
196 197 198 199 200 201 202 203 204 |
# File 'lib/coo-coo/convolution.rb', line 196 def slice_output(output, grid_x, grid_y) origin_x = grid_x * @int_output_width origin_y = grid_y * @int_output_height output.slice_2d((horizontal_span * @int_output_width).to_i, (vertical_span * @int_output_height).to_i, origin_x, origin_y, @int_output_width, @int_output_height, 0.0) end |
#to_hash(network = nil) ⇒ Object
150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/coo-coo/convolution.rb', line 150 def to_hash(network = nil) { type: self.class.to_s, width: @width, height: @height, horizontal_step: @horizontal_step, vertical_step: @vertical_step, input_width: @input_width, input_height: @input_height, int_output_width: @int_output_width, int_output_height: @int_output_height, delta_accumulator: @delta_accumulator, internal_layer: @internal_layer.to_hash(network) } end |
#transfer_error(deltas) ⇒ Object
104 105 106 107 108 |
# File 'lib/coo-coo/convolution.rb', line 104 def transfer_error(deltas) flatten_areas(each_area do |grid_x, grid_y| @internal_layer.transfer_error(deltas[grid_y][grid_x]).to_a end, width, height, input_width) end |
#update_weights!(inputs, deltas) ⇒ Object
110 111 112 |
# File 'lib/coo-coo/convolution.rb', line 110 def update_weights!(inputs, deltas) adjust_weights!(*weight_deltas(inputs, deltas)) end |
#vertical_span ⇒ Object
43 44 45 |
# File 'lib/coo-coo/convolution.rb', line 43 def vertical_span @vertical_span ||= (@height / @vertical_step.to_f).ceil end |
#weight_deltas(inputs, deltas) ⇒ Object
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/coo-coo/convolution.rb', line 119 def weight_deltas(inputs, deltas) #rate = rate / (@horizontal_span * @vertical_span).to_f change = [] wd = [] d = [] each_area do |grid_x, grid_y| hs_index = grid_y * horizontal_span + grid_x delta, hs = @internal_layer. weight_deltas(slice_input(inputs, grid_x, grid_y), deltas[grid_y][grid_x]) d << delta end Sequence[d].send(@delta_accumulator) end |