PopulationBasedStepSizeAdaptation.h
Go to the documentation of this file.
1/*!
2 * \brief Implements the tep size adaptation based on the success of the new population compared to the old
3 *
4 * \author O.Krause
5 * \date 2014
6 *
7 * \par Copyright 1995-2017 Shark Development Team
8 *
9 * <BR><HR>
10 * This file is part of Shark.
11 * <https://shark-ml.github.io/Shark/>
12 *
13 * Shark is free software: you can redistribute it and/or modify
14 * it under the terms of the GNU Lesser General Public License as published
15 * by the Free Software Foundation, either version 3 of the License, or
16 * (at your option) any later version.
17 *
18 * Shark is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License for more details.
22 *
23 * You should have received a copy of the GNU Lesser General Public License
24 * along with Shark. If not, see <http://www.gnu.org/licenses/>.
25 *
26 */
27#ifndef SHARK_ALGORITHMS_DIRECTSEARCH_OPERATORS_POPULATION_BASED_STEP_SIZE_ADAPTATION_H
28#define SHARK_ALGORITHMS_DIRECTSEARCH_OPERATORS_POPULATION_BASED_STEP_SIZE_ADAPTATION_H
29
30#include <shark/LinAlg/Base.h>
31#include <cmath>
32
33namespace shark {
34
35/// \brief Step size adaptation based on the success of the new population compared to the old
36///
37/// This is the step size adaptation algorithm as proposed in
38/// Ilya Loshchilov, "A Computationally Efficient Limited Memory CMA-ES for Large Scale Optimization"
39///
40/// It ranks the old and new population together and checks whether the mean rank of the new population
41/// is lower than the old one in this combined population. If this is true, the step size is increased
42/// in an exponential fashion. More formally, let \f$ r_t(i) \f$ be the rank of the i-th individual in the
43/// current population in the combined ranking and \f$ r_{t-1}(i) \f$ the rank of the i-th previous
44/// individual. Then we have
45/// \f[ z_t \leftarrow \frac 1 {\lamba^2} \sum_i^{\lambda} r_{t-1}(i) - r_t(i) - z*\f]
46/// where \f$ z* \f$ is a target success value, which defaults to 0.25
47/// this statistic is stabilised using an exponential average:
48/// \f[ s_t \leftarrow (1-c)*s_{t-1} + c*z_t \f]
49/// where the learning rate c defaults to 0.3
50/// finally we adapt the step size sigma by
51/// \f[ \sigma_t = \sigma_{t-1} exp(s_t/d) \f]
52/// where the damping factor d defaults to 1
54public:
56
57 /////Getter and Setter functions/////////
58
59 double targetSuccessRate()const{
61 }
62
65 }
66
67 double learningRate()const{
68 return m_c;
69 }
70
71 double& learningRate(){
72 return m_c;
73 }
74
75 double dampingFactor()const{
76 return m_d;
77 }
78
79 double& dampingFactor(){
80 return m_d;
81 }
82
83 double stepSize()const{
84 return m_stepSize;
85 }
86
87 ///\brief Initializes a new trial by setting the initial learning rate and resetting the internal values.
88 void init(double initialStepSize){
89 m_stepSize = initialStepSize;
90 m_s = 0;
91 m_prevFitness.resize(0);
92 }
93
94 /// \brief updates the step size using the newly sampled population
95 ///
96 /// The offspring is assumed to be ordered in ascending order by their penalizedFitness
97 /// (this is the same as ordering by the unpenalized fitness in an unconstrained setting)
98 template<class Population>
99 void update(Population const& offspring){
100 std::size_t lambda = offspring.size();
101 if (m_prevFitness.size() == lambda){
102 //get estimate of z
103 std::size_t indexOld = 0;
104 std::size_t indexNew = 0;
105 std::size_t rank = 1;
106 double z = 0;
107 while(indexOld < lambda && indexNew < lambda){
108 if (offspring[indexNew].penalizedFitness() <= m_prevFitness[indexOld]){
109 z-=rank;
110 ++indexNew;
111 }
112 else{
113 z+=rank;
114 ++indexOld;
115 }
116 ++rank;
117 }
118 //case 1: the worst elements in the old population are better than the worst in the new
119 while(indexNew < lambda){
120 z-=rank;
121 ++indexNew;
122 ++rank;
123 }
124 //case 2: the opposite
125 while(indexOld< lambda){
126 z += rank;
127 ++indexOld;
128 ++rank;
129 }
130 z /= lambda*lambda;
132 m_s = (1-m_c)*m_s +m_c*z;
133 m_stepSize *= std::exp(m_s/m_d);
134 }
135
136 //store fitness values of last iteration
137 m_prevFitness.resize(lambda);
138 for(std::size_t i = 0; i != lambda; ++i)
139 m_prevFitness(i) = offspring[i].penalizedFitness();
140 }
141protected:
142 double m_stepSize;///< current value for the step size
143 RealVector m_prevFitness;///< fitness values of the previous iteration for ranking
144 double m_s; ///< The time average of the population success
145
146 //hyper parameters
148 double m_c;
149 double m_d;
150};
151
152}
153
154#endif