class CooCoo::Convolution::BoxLayer
Attributes
delta_accumulator[R]
height[R]
horizontal_step[R]
input_height[R]
input_width[R]
int_output_height[R]
int_output_width[R]
internal_layer[R]
vertical_step[R]
width[R]
Public Class Methods
from_hash(h, network = nil)
click to toggle source
# 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
new(width, height, horizontal_step, vertical_step, internal_layer, input_width, input_height, int_output_width, int_output_height, update_weights_with = :average)
click to toggle source
# 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
Public Instance Methods
==(other)
click to toggle source
# 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()
click to toggle source
# File lib/coo-coo/convolution.rb, line 35 def activation_function internal_layer.activation_function end
adjust_weights!(deltas)
click to toggle source
# 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)
click to toggle source
# 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() { |grid_x, grid_y| ... }
click to toggle source
private
# 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)
click to toggle source
# 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)
click to toggle source
# 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()
click to toggle source
# File lib/coo-coo/convolution.rb, line 39 def horizontal_span @horizontal_span ||= (@width / @horizontal_step.to_f).ceil end
neurons()
click to toggle source
# File lib/coo-coo/convolution.rb, line 63 def neurons internal_layer.neurons end
num_inputs()
click to toggle source
# File lib/coo-coo/convolution.rb, line 47 def num_inputs @width * @height end
output_height()
click to toggle source
# File lib/coo-coo/convolution.rb, line 55 def output_height (vertical_span * int_output_height).to_i end
output_width()
click to toggle source
# File lib/coo-coo/convolution.rb, line 51 def output_width (horizontal_span * int_output_width).to_i end
size()
click to toggle source
# File lib/coo-coo/convolution.rb, line 59 def size output_height * output_width end
slice_input(input, grid_x, grid_y)
click to toggle source
# 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)
click to toggle source
# 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)
click to toggle source
# 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)
click to toggle source
# 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)
click to toggle source
# File lib/coo-coo/convolution.rb, line 110 def update_weights!(inputs, deltas) adjust_weights!(*weight_deltas(inputs, deltas)) end
vertical_span()
click to toggle source
# File lib/coo-coo/convolution.rb, line 43 def vertical_span @vertical_span ||= (@height / @vertical_step.to_f).ceil end
weight_deltas(inputs, deltas)
click to toggle source
# 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