class Newral::Training::HillClimbing

Attributes

best_error[R]
best_function[R]
input[R]
needed_iterations[R]

Public Class Methods

new( input: [], output: [], iterations:10**5, klass: Newral::Functions::Polynomial, klass_args: {}, start_function: nil ) click to toggle source
# File lib/newral/training/hill_climbing.rb, line 5
def initialize( input: [], output: [], iterations:10**5, klass: Newral::Functions::Polynomial, klass_args: {}, start_function: nil  )
  @input = input
  @output = output
  @iterations = iterations
  @klass = klass
  @klass_args = klass_args
  @best_function = start_function
  @needed_iterations = 0
end

Public Instance Methods

process( start_fresh: false, max_error:0.01 ) click to toggle source
# File lib/newral/training/hill_climbing.rb, line 16
def process( start_fresh: false, max_error:0.01 )
  @best_function = case 
    when start_fresh then @klass.create_random( @klass_args ) 
    when  @best_function then @best_function
  else 
     @klass.create_random( @klass_args )
  end
  
  function = @best_function.dup.move_random( @klass_args )
  @best_error = @best_function.calculate_error( input: @input, output: @output )
  number_of_directions = @best_function.number_of_directions
  step_sizes = [1]*number_of_directions
  acceleration = 1.2
  candidates = [
    -acceleration,
    -1/acceleration,
    0,
    1/acceleration,
    acceleration
  ]
  i=0 
  best_local_function = @best_function.dup
  before_error = 99999
  after_error = 1
  moved = true
  while i<@iterations  && @best_error > max_error 
    moved = false
    before_error = function.calculate_error( input: @input, output: @output )
    number_of_directions.times do |direction|
      best_candidate = -1
      best_candidate_error = 9999999
      candidates.each do |candidate| 
        temp_function = function.dup.move( direction: direction, step: step_sizes[ direction ]*candidate)
        error = temp_function.calculate_error( input: @input, output: @output )
        if error < best_candidate_error
          best_candidate = candidate
          best_candidate_error = error
          if error < @best_error
            @best_error = best_candidate_error
            @best_function = temp_function.dup
          end
        end 
      end
      if best_candidate == 0
        step_sizes[direction] = step_sizes[direction] / acceleration # take it slower
      else
        moved = true
        function.move( direction: direction, step: step_sizes[ direction ]*best_candidate )
        # puts "moving #{direction} by #{(step_sizes[ direction ]*candidates[best_candidate]).to_s}"
        step_sizes[direction] = step_sizes[ direction ] * best_candidate # accelerate
      end
    end
    after_error = function.calculate_error( input: @input, output: @output )
    i=i+1
  end
  @needed_iterations = i 
  @best_function
end