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.
-
#eye ⇒ Object
readonly
Returns the value of attribute eye.
-
#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.
-
#rescale_lrate ⇒ Object
readonly
Returns the value of attribute rescale_lrate.
-
#rescale_popsize ⇒ Object
readonly
Returns the value of attribute rescale_popsize.
-
#rng ⇒ Object
readonly
Returns the value of attribute rng.
-
#sigma ⇒ Object
readonly
Returns the value of attribute sigma.
Instance Method Summary collapse
-
#cmaes_lrate ⇒ NArray, Float
Magic numbers from CMA-ES (TODO: add proper citation).
-
#cmaes_popsize ⇒ NArray, Integer
Magic numbers from CMA-ES (TODO: add proper citation).
-
#cmaes_utilities ⇒ NArray
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, rescale_popsize: 1, rescale_lrate: 1) ⇒ 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) ⇒ NArray
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 ⇒ NArray
Samples a standard normal distribution to construct a NArray 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, rescale_popsize: 1, rescale_lrate: 1) ⇒ Base
NES object initialization
22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 22 def initialize ndims, obj_fn, opt_type, rseed: nil, mu_init: 0, sigma_init: 1, parallel_fit: false, rescale_popsize: 1, rescale_lrate: 1 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 @rescale_popsize, @rescale_lrate = rescale_popsize, rescale_lrate @eye = NArray.eye(ndims) 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 |
#eye ⇒ Object (readonly)
Returns the value of attribute eye.
5 6 7 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 5 def eye @eye 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 |
#rescale_lrate ⇒ Object (readonly)
Returns the value of attribute rescale_lrate.
5 6 7 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 5 def rescale_lrate @rescale_lrate end |
#rescale_popsize ⇒ Object (readonly)
Returns the value of attribute rescale_popsize.
5 6 7 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 5 def rescale_popsize @rescale_popsize 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 ⇒ NArray, Float
Magic numbers from CMA-ES (TODO: add proper citation)
70 71 72 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 70 def cmaes_lrate (3+Math.log(ndims)) / (5*Math.sqrt(ndims)) end |
#cmaes_popsize ⇒ NArray, Integer
Magic numbers from CMA-ES (TODO: add proper citation)
76 77 78 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 76 def cmaes_popsize [5, 4 + (3*Math.log(ndims)).floor].max end |
#cmaes_utilities ⇒ NArray
Magic numbers from CMA-ES (TODO: add proper citation)
56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 56 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 NArray[vals] end |
#interface_methods ⇒ Object
Declaring interface methods - implement these in child class!
133 134 135 136 137 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 133 [: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
52 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 52 def lrate; @lrate ||= cmaes_lrate * rescale_lrate end |
#move_inds(inds) ⇒ NArray
Move standard normal samples to current distribution
92 93 94 95 96 97 98 99 100 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 92 def move_inds inds # TODO: can we reduce the transpositions? # multi_mu = NMatrix[*inds.rows.times.collect {mu.to_a}, dtype: dtype].transpose # (multi_mu + sigma.dot(inds.transpose)).transpose mu_tile = mu.tile(inds.shape.first, 1).transpose (mu_tile + sigma.dot(inds.transpose)).transpose end |
#popsize ⇒ Object
Memoized automatic magic numbers NOTE: Doubling popsize and halving lrate often helps
50 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 50 def popsize; @popsize ||= cmaes_popsize * rescale_popsize 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.
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 106 def sorted_inds # Xumo::NArray implements the Box-Muller, but no random seed (yet) samples = standard_normal_samples # samples = NArray.new([popsize, ndims]).rand_norm(0,1) inds = move_inds(samples) 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.to_a, inds, samples.to_a].transpose.sort_by(&:first) # sorted.reverse! if opt_type==:min # this_best = sorted.last.take(2) # NArray[*sorted.map(&:last)] sort_idxs = fits.sort_index sort_idxs = sort_idxs.reverse if opt_type == :min this_best = [fits[sort_idxs[-1]], inds[sort_idxs[-1], true]] opt_cmp_fn = opt_type==:min ? :< : :> @best = this_best if this_best.first.send(opt_cmp_fn, best.first) samples[sort_idxs,true] end |
#standard_normal_sample ⇒ Float
Xumo::NArray implements this but no random seed selection yet
Box-Muller transform: generates standard (unit) normal distribution samples
39 40 41 42 43 44 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 39 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 ⇒ NArray
Xumo::NArray implements this but no random seed selection yet
Samples a standard normal distribution to construct a NArray of
popsize multivariate samples of length ndims
84 85 86 87 88 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 84 def standard_normal_samples NArray.zeros([popsize, ndims]).tap do |ret| ret.each_with_index { |_,*i| ret[*i] = standard_normal_sample } end end |
#utils ⇒ Object
Memoized automatic magic numbers NOTE: Doubling popsize and halving lrate often helps
48 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/base.rb', line 48 def utils; @utilities ||= cmaes_utilities end |