Class: MachineLearningWorkbench::Optimizer::NaturalEvolutionStrategies::BDNES
- Inherits:
-
Base
- Object
- Base
- MachineLearningWorkbench::Optimizer::NaturalEvolutionStrategies::BDNES
- Defined in:
- lib/machine_learning_workbench/optimizer/natural_evolution_strategies/bdnes.rb
Overview
Block-Diagonal Natural Evolution Strategies
Constant Summary collapse
- MAX_RSEED =
same range as Random.new_seed
10**Random.new_seed.size
Instance Attribute Summary collapse
-
#best ⇒ Object
readonly
Returns the value of attribute best.
-
#blocks ⇒ Object
readonly
Returns the value of attribute blocks.
-
#last_fits ⇒ Object
readonly
Returns the value of attribute last_fits.
-
#ndims_lst ⇒ Object
readonly
Returns the value of attribute ndims_lst.
-
#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.
-
#popsize ⇒ Object
readonly
Returns the value of attribute popsize.
-
#rng ⇒ Object
readonly
Returns the value of attribute rng.
Attributes inherited from Base
#eye, #ndims, #rescale_lrate, #rescale_popsize, #sigma
Instance Method Summary collapse
- #convergence ⇒ Object
-
#initialize(ndims_lst, obj_fn, opt_type, parallel_fit: false, rseed: nil, **init_opts) ⇒ BDNES
constructor
Initialize a list of XNES, one for each block see class ‘Base` for the description of the rest of the arguments.
- #load(data) ⇒ Object
- #mu ⇒ Object
- #save ⇒ Object
- #sorted_inds_lst ⇒ Object
-
#train(picks: sorted_inds_lst) ⇒ Object
duck-type the interface: [:train, :mu, :convergence, :save, :load].
Methods inherited from Base
#cmaes_lrate, #cmaes_popsize, #cmaes_utilities, #interface_methods, #lrate, #move_inds, #sorted_inds, #standard_normal_sample, #standard_normal_samples, #utils
Constructor Details
#initialize(ndims_lst, obj_fn, opt_type, parallel_fit: false, rseed: nil, **init_opts) ⇒ BDNES
Initialize a list of XNES, one for each block see class ‘Base` for the description of the rest of the arguments.
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/bdnes.rb', line 17 def initialize ndims_lst, obj_fn, opt_type, parallel_fit: false, rseed: nil, **init_opts # mu_init: 0, sigma_init: 1 # init_opts = {rseed: rseed, mu_init: mu_init, sigma_init: sigma_init} # TODO: accept list of `mu_init`s and `sigma_init`s @ndims_lst, @obj_fn, @opt_type, @parallel_fit = ndims_lst, obj_fn, opt_type, parallel_fit block_fit = -> (*args) { raise "Should never be called" } # the BD-NES seed should ensure deterministic reproducibility # but each block should have a different seed rseed ||= Random.new_seed # puts "BD-NES rseed: #{s}" # currently disabled @rng = Random.new rseed @blocks = ndims_lst.map do |ndims| b_rseed = rng.rand MAX_RSEED XNES.new ndims, block_fit, opt_type, rseed: b_rseed, **init_opts end # Need `popsize` to be the same for all blocks, to make complete individuals @popsize = blocks.map(&:popsize).max blocks.each { |xnes| xnes.instance_variable_set :@popsize, popsize } @best = [(opt_type==:max ? -1 : 1) * Float::INFINITY, nil] @last_fits = [] end |
Instance Attribute Details
#best ⇒ Object (readonly)
Returns the value of attribute best.
8 9 10 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/bdnes.rb', line 8 def best @best end |
#blocks ⇒ Object (readonly)
Returns the value of attribute blocks.
8 9 10 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/bdnes.rb', line 8 def blocks @blocks end |
#last_fits ⇒ Object (readonly)
Returns the value of attribute last_fits.
8 9 10 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/bdnes.rb', line 8 def last_fits @last_fits end |
#ndims_lst ⇒ Object (readonly)
Returns the value of attribute ndims_lst.
8 9 10 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/bdnes.rb', line 8 def ndims_lst @ndims_lst end |
#obj_fn ⇒ Object (readonly)
Returns the value of attribute obj_fn.
8 9 10 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/bdnes.rb', line 8 def obj_fn @obj_fn end |
#opt_type ⇒ Object (readonly)
Returns the value of attribute opt_type.
8 9 10 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/bdnes.rb', line 8 def opt_type @opt_type end |
#parallel_fit ⇒ Object (readonly)
Returns the value of attribute parallel_fit.
8 9 10 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/bdnes.rb', line 8 def parallel_fit @parallel_fit end |
#popsize ⇒ Object (readonly)
Returns the value of attribute popsize.
8 9 10 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/bdnes.rb', line 8 def popsize @popsize end |
#rng ⇒ Object (readonly)
Returns the value of attribute rng.
8 9 10 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/bdnes.rb', line 8 def rng @rng end |
Instance Method Details
#convergence ⇒ Object
96 97 98 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/bdnes.rb', line 96 def convergence blocks.map(&:convergence).reduce(:+) end |
#load(data) ⇒ Object
104 105 106 107 108 109 110 111 112 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/bdnes.rb', line 104 def load data fit = -> (*args) { raise "Should never be called" } @blocks = data.map do |block_data| ndims = block_data.first.size XNES.new(ndims, fit, opt_type).tap do |nes| nes.load block_data end end end |
#mu ⇒ Object
92 93 94 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/bdnes.rb', line 92 def mu blocks.map(&:mu).reduce { |mem, var| mem.concatenate var, axis: 1 } end |
#save ⇒ Object
100 101 102 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/bdnes.rb', line 100 def save blocks.map &:save end |
#sorted_inds_lst ⇒ Object
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/bdnes.rb', line 40 def sorted_inds_lst # Build samples and inds from the list of blocks samples_lst, inds_lst = blocks.map do |xnes| samples = xnes.standard_normal_samples inds = xnes.move_inds(samples) [samples.to_a, inds] end.transpose # Join the individuals for evaluation full_inds = inds_lst.reduce { |mem, var| mem.concatenate var, axis: 1 } # Need to fix sample dimensions for sorting # - current dims: nblocks x ninds x [block sizes] # - for sorting: ninds x nblocks x [block sizes] full_samples = samples_lst.transpose # Evaluate fitness of complete individuals fits = parallel_fit ? obj_fn.call(full_inds) : full_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 # Sort inds based on fit and opt_type, save best # sorted = [fits, full_inds, full_samples].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) # sorted_samples = sorted.map(&:last) sort_idxs = fits.sort_index sort_idxs = sort_idxs.reverse if opt_type == :min this_best = [fits[sort_idxs[-1]], full_inds[sort_idxs[-1]]] opt_cmp_fn = opt_type==:min ? :< : :> @best = this_best if this_best.first.send(opt_cmp_fn, best.first) sorted_samples = full_samples.values_at *sort_idxs # Need to bring back sample dimensions for each block # - current dims: ninds x nblocks x [block sizes] # - target blocks list: nblocks x ninds x [block sizes] block_samples = sorted_samples.transpose # then back to NArray for usage in training block_samples.map &:to_na end |
#train(picks: sorted_inds_lst) ⇒ Object
duck-type the interface: [:train, :mu, :convergence, :save, :load]
86 87 88 89 90 |
# File 'lib/machine_learning_workbench/optimizer/natural_evolution_strategies/bdnes.rb', line 86 def train picks: sorted_inds_lst blocks.zip(sorted_inds_lst).each do |xnes, s_inds| xnes.train picks: s_inds end end |