Class: MachineLearningWorkbench::Optimizer::NaturalEvolutionStrategies::Base
- Inherits:
-
Object
- Object
- MachineLearningWorkbench::Optimizer::NaturalEvolutionStrategies::Base
- Defined in:
- lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb
Overview
Natural Evolution Strategies base class
Instance Attribute Summary collapse
-
#best ⇒ Object
readonly
Returns the value of attribute best.
-
#id ⇒ Object
readonly
Returns the value of attribute id.
-
#last_fits ⇒ Object
readonly
Returns the value of attribute last_fits.
-
#mu ⇒ Object
readonly
Returns the value of attribute mu.
-
#ndims ⇒ Object
readonly
Returns the value of attribute ndims.
-
#obj_fn ⇒ Object
readonly
Returns the value of attribute obj_fn.
-
#opt_type ⇒ Object
readonly
Returns the value of attribute opt_type.
-
#parallel_fit ⇒ Object
readonly
Returns the value of attribute parallel_fit.
-
#rng ⇒ Object
readonly
Returns the value of attribute rng.
-
#sigma ⇒ Object
readonly
Returns the value of attribute sigma.
Instance Method Summary collapse
-
#cmaes_lrate ⇒ NMatrix, Float
Magic numbers from CMA-ES (TODO: add proper citation).
-
#cmaes_popsize ⇒ NMatrix, Integer
Magic numbers from CMA-ES (TODO: add proper citation).
-
#cmaes_utilities ⇒ NMatrix
Magic numbers from CMA-ES (TODO: add proper citation).
-
#initialize(ndims, obj_fn, opt_type, rseed: nil, mu_init: 0, sigma_init: 1, parallel_fit: false) ⇒ Base
constructor
NES object initialization.
-
#interface_methods ⇒ Object
Declaring interface methods - implement these in child class!.
-
#lrate ⇒ Object
Memoized automatic magic numbers NOTE: Doubling popsize and halving lrate often helps.
-
#move_inds(inds) ⇒ NMatrix
Move standard normal samples to current distribution.
-
#popsize ⇒ Object
Memoized automatic magic numbers NOTE: Doubling popsize and halving lrate often helps.
-
#sorted_inds ⇒ Object
Sorted individuals NOTE: Algorithm equations are meant for fitness maximization.
-
#standard_normal_sample ⇒ Float
Box-Muller transform: generates standard (unit) normal distribution samples.
-
#standard_normal_samples ⇒ NMatrix
Samples a standard normal distribution to construct a NMatrix of popsize multivariate samples of length ndims.
-
#utils ⇒ Object
Memoized automatic magic numbers NOTE: Doubling popsize and halving lrate often helps.
Constructor Details
#initialize(ndims, obj_fn, opt_type, rseed: nil, mu_init: 0, sigma_init: 1, parallel_fit: false) ⇒ Base
NES object initialization
19 20 21 22 23 24 25 26 27 28 29 30 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 19 def initialize ndims, obj_fn, opt_type, rseed: nil, mu_init: 0, sigma_init: 1, parallel_fit: false raise ArgumentError unless [:min, :max].include? opt_type raise ArgumentError unless obj_fn.respond_to? :call @ndims, @opt_type, @obj_fn, @parallel_fit = ndims, opt_type, obj_fn, parallel_fit @id = NMatrix.identity(ndims, dtype: :float64) rseed ||= Random.new_seed # puts "NES rseed: #{s}" # currently disabled @rng = Random.new rseed @best = [(opt_type==:max ? -1 : 1) * Float::INFINITY, nil] @last_fits = [] initialize_distribution mu_init: mu_init, sigma_init: sigma_init end |
Instance Attribute Details
#best ⇒ Object (readonly)
Returns the value of attribute best.
5 6 7 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 5 def best @best end |
#id ⇒ Object (readonly)
Returns the value of attribute id.
5 6 7 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 5 def id @id end |
#last_fits ⇒ Object (readonly)
Returns the value of attribute last_fits.
5 6 7 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 5 def last_fits @last_fits end |
#mu ⇒ Object (readonly)
Returns the value of attribute mu.
5 6 7 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 5 def mu @mu end |
#ndims ⇒ Object (readonly)
Returns the value of attribute ndims.
5 6 7 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 5 def ndims @ndims end |
#obj_fn ⇒ Object (readonly)
Returns the value of attribute obj_fn.
5 6 7 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 5 def obj_fn @obj_fn end |
#opt_type ⇒ Object (readonly)
Returns the value of attribute opt_type.
5 6 7 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 5 def opt_type @opt_type end |
#parallel_fit ⇒ Object (readonly)
Returns the value of attribute parallel_fit.
5 6 7 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 5 def parallel_fit @parallel_fit end |
#rng ⇒ Object (readonly)
Returns the value of attribute rng.
5 6 7 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 5 def rng @rng end |
#sigma ⇒ Object (readonly)
Returns the value of attribute sigma.
5 6 7 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 5 def sigma @sigma end |
Instance Method Details
#cmaes_lrate ⇒ NMatrix, Float
Magic numbers from CMA-ES (TODO: add proper citation)
65 66 67 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 65 def cmaes_lrate (3+Math.log(ndims)) / (5*Math.sqrt(ndims)) end |
#cmaes_popsize ⇒ NMatrix, Integer
Magic numbers from CMA-ES (TODO: add proper citation)
71 72 73 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 71 def cmaes_popsize [5, 4 + (3*Math.log(ndims)).floor].max end |
#cmaes_utilities ⇒ NMatrix
Magic numbers from CMA-ES (TODO: add proper citation)
51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 51 def cmaes_utilities # Algorithm equations are meant for fitness maximization # Match utilities with individuals sorted by INCREASING fitness log_range = (1..popsize).collect do |v| [0, Math.log(popsize.to_f/2 - 1) - Math.log(v)].max end total = log_range.reduce(:+) buf = 1.0/popsize vals = log_range.collect { |v| v / total - buf }.reverse NMatrix[vals, dtype: :float64] end |
#interface_methods ⇒ Object
Declaring interface methods - implement these in child class!
113 114 115 116 117 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 113 [:train, :initialize_distribution, :convergence].each do |mname| define_method mname do raise NotImplementedError, "Implement in child class!" end end |
#lrate ⇒ Object
Memoized automatic magic numbers NOTE: Doubling popsize and halving lrate often helps
47 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 47 def lrate; @lrate ||= cmaes_lrate end |
#move_inds(inds) ⇒ NMatrix
Move standard normal samples to current distribution
84 85 86 87 88 89 90 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 84 def move_inds inds # TODO: can we reduce the transpositions? # sigma.dot(inds.transpose).map(&mu.method(:+)).transpose multi_mu = NMatrix[*inds.rows.times.collect {mu.to_a}, dtype: :float64].transpose (multi_mu + sigma.dot(inds.transpose)).transpose # sigma.dot(inds.transpose).transpose + inds.rows.times.collect {mu.to_a}.to_nm end |
#popsize ⇒ Object
Memoized automatic magic numbers NOTE: Doubling popsize and halving lrate often helps
45 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 45 def popsize; @popsize ||= cmaes_popsize * 2 end |
#sorted_inds ⇒ Object
Sorted individuals NOTE: Algorithm equations are meant for fitness maximization. Utilities need to be matched with individuals sorted by INCREASING fitness. Then reverse order for minimization.
96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 96 def sorted_inds samples = standard_normal_samples inds = move_inds(samples).to_a fits = parallel_fit ? obj_fn.call(inds) : inds.map(&obj_fn) # Quick cure for NaN fitnesses fits.map! { |x| x.nan? ? (opt_type==:max ? -1 : 1) * Float::INFINITY : x } @last_fits = fits # allows checking for stagnation sorted = [fits, inds, samples.to_a].transpose.sort_by(&:first) sorted.reverse! if opt_type==:min this_best = sorted.last.take(2) opt_cmp_fn = opt_type==:min ? :< : :> @best = this_best if this_best.first.send(opt_cmp_fn, best.first) NMatrix[*sorted.map(&:last), dtype: :float64] end |
#standard_normal_sample ⇒ Float
Box-Muller transform: generates standard (unit) normal distribution samples
34 35 36 37 38 39 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 34 def standard_normal_sample rho = Math.sqrt(-2.0 * Math.log(rng.rand)) theta = 2 * Math::PI * rng.rand tfn = rng.rand > 0.5 ? :cos : :sin rho * Math.send(tfn, theta) end |
#standard_normal_samples ⇒ NMatrix
Samples a standard normal distribution to construct a NMatrix of
popsize multivariate samples of length ndims
78 79 80 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 78 def standard_normal_samples NMatrix.new([popsize, ndims], dtype: :float64) { standard_normal_sample } end |
#utils ⇒ Object
Memoized automatic magic numbers NOTE: Doubling popsize and halving lrate often helps
43 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 43 def utils; @utilities ||= cmaes_utilities end |