class CooCoo::Trainer::Batch
Trains a network by only adjusting the network once a batch. This opens up parallelism during learning as more examples can be ran at one time.
Constants
- DEFAULT_OPTIONS
Public Instance Methods
options()
click to toggle source
Calls superclass method
CooCoo::Trainer::Base#options
# File lib/coo-coo/trainer/batch.rb, line 13 def options super(DEFAULT_OPTIONS) do |o, options| o.on('--processes INTEGER', Integer, 'Number of threads or processes to use for the batch.') do |n| options.processes = n end end end
train(options, &block)
click to toggle source
@option options [Integer] :processes How many threads or processes to use for the batch. Defaults to the processor count, {Parallel#processor_count}.
# File lib/coo-coo/trainer/batch.rb, line 22 def train(options, &block) options = options.to_h network = options.fetch(:network) training_data = options.fetch(:data) learning_rate = options.fetch(:learning_rate, 0.3) batch_size = options.fetch(:batch_size, 1024) cost_function = options.fetch(:cost_function, CostFunctions::MeanSquare) processes = options.fetch(:processes, Parallel.processor_count) t = Time.now training_data.each_slice(batch_size).with_index do |batch, i| deltas_errors = in_parallel(processes, batch) do |(expecting, input)| output, hidden_state = network.forward(input, Hash.new) target = network.prep_output_target(expecting) final_output = network.final_output(output) errors = cost_function.derivative(target, final_output) new_deltas, hidden_state = network.backprop(input, output, errors, hidden_state) new_deltas = network.weight_deltas(input, output, new_deltas * learning_rate) [ new_deltas, cost_function.call(target, final_output) ] end deltas, total_errors = deltas_errors.transpose network.adjust_weights!(accumulate_deltas(deltas)) if block block.call(BatchStats.new(self, i, batch_size, Time.now - t, CooCoo::Sequence[total_errors].sum)) end t = Time.now end end
Protected Instance Methods
accumulate_deltas(deltas)
click to toggle source
# File lib/coo-coo/trainer/batch.rb, line 68 def accumulate_deltas(deltas) weight = 1.0 / deltas.size.to_f acc = deltas[0] deltas[1, deltas.size].each do |step| step.each_with_index do |layer, i| acc[i] += layer * weight end end acc end
in_parallel(processes, *args, &block)
click to toggle source
# File lib/coo-coo/trainer/batch.rb, line 58 def in_parallel(processes, *args, &block) opts = if CUDA.available? # CUDA can't fork so keep it in a single Ruby { in_threads: processes } else { in_processes: processes } end Parallel.map(*args, opts, &block) end