[shark] 10/58: Implemented Cross Entropy algorithm
Ghislain Vaillant
ghisvail-guest at moszumanska.debian.org
Wed Mar 16 10:05:27 UTC 2016
This is an automated email from the git hooks/post-receive script.
ghisvail-guest pushed a commit to branch master
in repository shark.
commit b954018cd66329b37bfd43f3d4d653c1cf5b5a7f
Author: Jens Holm <jensgholm15 at gmail.com>
Date: Wed Jan 27 17:34:44 2016 +0100
Implemented Cross Entropy algorithm
---
Test/Algorithms/DirectSearch/CrossEntropy.cpp | 56 +++++
Test/CMakeLists.txt | 1 +
.../shark/Algorithms/DirectSearch/CrossEntropy.h | 238 +++++++++++++++++++++
src/Algorithms/DirectSearch/CrossEntropy.cpp | 220 +++++++++++++++++++
4 files changed, 515 insertions(+)
diff --git a/Test/Algorithms/DirectSearch/CrossEntropy.cpp b/Test/Algorithms/DirectSearch/CrossEntropy.cpp
new file mode 100644
index 0000000..3f8b44c
--- /dev/null
+++ b/Test/Algorithms/DirectSearch/CrossEntropy.cpp
@@ -0,0 +1,56 @@
+#define BOOST_TEST_MODULE DirectSearch_CrossEntropy
+#include <boost/test/unit_test.hpp>
+#include <boost/test/floating_point_comparison.hpp>
+
+#include <shark/Algorithms/DirectSearch/CrossEntropy.h>
+#include <shark/ObjectiveFunctions/Benchmarks/Rosenbrock.h>
+#include <shark/ObjectiveFunctions/Benchmarks/Cigar.h>
+#include <shark/ObjectiveFunctions/Benchmarks/Discus.h>
+#include <shark/ObjectiveFunctions/Benchmarks/Ellipsoid.h>
+#include <shark/ObjectiveFunctions/Benchmarks/Sphere.h>
+#include <shark/ObjectiveFunctions/Benchmarks/DiffPowers.h>
+
+#include "../testFunction.h"
+
+using namespace shark;
+
+BOOST_AUTO_TEST_SUITE (Algorithms_DirectSearch_CrossEntropy)
+
+BOOST_AUTO_TEST_CASE( CrossEntropy_Cigar )
+{
+ Cigar function(3);
+ CrossEntropy optimizer;
+
+ std::cout<<"Testing: "<<optimizer.name()<<" with "<<function.name()<<std::endl;
+ test_function( optimizer, function, _trials = 10, _iterations = 1000, _epsilon = 1E-10 );
+}
+
+BOOST_AUTO_TEST_CASE( CrossEntropy_Discus )
+{
+ Discus function(3);
+ CrossEntropy optimizer;
+
+ std::cout<<"\nTesting: "<<optimizer.name()<<" with "<<function.name()<<std::endl;
+ test_function( optimizer, function, _trials = 10, _iterations = 1000, _epsilon = 1E-10 );
+}
+
+BOOST_AUTO_TEST_CASE( CrossEntropy_Ellipsoid )
+{
+ Ellipsoid function(5);
+ CrossEntropy optimizer;
+
+ std::cout << "\nTesting: " << optimizer.name() << " with " << function.name() << std::endl;
+ test_function( optimizer, function, _trials = 10, _iterations = 1000, _epsilon = 1E-10 );
+}
+
+BOOST_AUTO_TEST_CASE( CrossEntropy_DiffPowers )
+{
+ DiffPowers function( 3 );
+ CrossEntropy optimizer;
+
+ std::cout << "\nTesting: " << optimizer.name() << " with " << function.name() << std::endl;
+ test_function( optimizer, function, _trials = 10, _iterations = 10000, _epsilon = 1E-10 );
+}
+
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/Test/CMakeLists.txt b/Test/CMakeLists.txt
index b7a1193..8f00920 100644
--- a/Test/CMakeLists.txt
+++ b/Test/CMakeLists.txt
@@ -80,6 +80,7 @@ shark_add_test( LinAlg/PartlyPrecomputedMatrix.cpp LinAlg_PartlyPrecomputedMatri
shark_add_test( Algorithms/DirectSearch/CMA.cpp DirectSearch_CMA )
shark_add_test( Algorithms/DirectSearch/CMSA.cpp DirectSearch_CMSA )
shark_add_test( Algorithms/DirectSearch/ElitistCMA.cpp DirectSearch_ElitistCMA )
+shark_add_test( Algorithms/DirectSearch/CrossEntropy.cpp DirectSearch_CrossEntropy )
shark_add_test( Algorithms/DirectSearch/VDCMA.cpp DirectSearch_VDCMA )
shark_add_test( Algorithms/DirectSearch/MOCMA.cpp DirectSearch_MOCMA )
shark_add_test( Algorithms/DirectSearch/SteadyStateMOCMA.cpp DirectSearch_SteadyStateMOCMA )
diff --git a/include/shark/Algorithms/DirectSearch/CrossEntropy.h b/include/shark/Algorithms/DirectSearch/CrossEntropy.h
new file mode 100644
index 0000000..51c6d3b
--- /dev/null
+++ b/include/shark/Algorithms/DirectSearch/CrossEntropy.h
@@ -0,0 +1,238 @@
+//===========================================================================
+/*!
+ *
+ * \brief Implements the Cross Entropy Algorithm.
+ *
+ * Christophe Thiery, Bruno Scherrer. Improvements on Learning Tetris with Cross Entropy.
+ * International Computer Games Association Journal, ICGA, 2009, 32. <inria-00418930>
+ *
+ *
+ * \author Jens Holm, Mathias Petræus and Mark Wulff
+ * \date January 2016
+ *
+ * \par Copyright 1995-2015 Shark Development Team
+ *
+ * <BR><HR>
+ * This file is part of Shark.
+ * <http://image.diku.dk/shark/>
+ *
+ * Shark is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Shark is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Shark. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+//===========================================================================
+
+
+#ifndef SHARK_ALGORITHMS_DIRECT_SEARCH_CROSSENTROPY_H
+#define SHARK_ALGORITHMS_DIRECT_SEARCH_CROSSENTROPY_H
+
+#include <shark/Core/DLLSupport.h>
+#include <shark/Algorithms/AbstractSingleObjectiveOptimizer.h>
+#include <shark/Statistics/Distributions/MultiVariateNormalDistribution.h>
+#include <shark/Algorithms/DirectSearch/Individual.h>
+
+#include <boost/shared_ptr.hpp>
+
+namespace shark {
+
+ class CrossEntropy : public AbstractSingleObjectiveOptimizer<RealVector >
+ {
+ public:
+
+ /**
+ * \brief Interface class for noise type.
+ */
+ class INoiseType {
+ public:
+ virtual double noiseValue (int t) const { return 0.0; };
+ virtual std::string name() const { return std::string("Default noise of 0"); }
+ };
+
+ /**
+ * \brief Smart pointer for noise type.
+ */
+ typedef boost::shared_ptr<INoiseType> StrongNoisePtr;
+
+ /**
+ * \brief Constant noise term z_t = noise.
+ */
+ class ConstantNoise : public INoiseType {
+ public:
+ ConstantNoise ( double noise ) { m_noise = noise; };
+ virtual double noiseValue (int t) const { return std::max(m_noise, 0.0); }
+ virtual std::string name() const {
+ std::stringstream ss;
+ ss << "z(t) = " << m_noise;
+ return std::string(ss.str());
+ }
+ private:
+ double m_noise;
+ };
+
+ /**
+ * \brief Linear noise term z_t = a + t / b.
+ */
+ class LinearNoise : public INoiseType {
+ public:
+ LinearNoise ( double a, double b ) { m_a = a; m_b = b; };
+ virtual double noiseValue (int t) const { return std::max(m_a + (t * m_b), 0.0); }
+ virtual std::string name() const {
+ std::stringstream ss;
+ std::string sign = (m_b < 0.0 ? " - " : " + ");
+ ss << "z(t) = " << m_a << sign << "t * " << std::abs(m_b);
+ return std::string(ss.str());
+ }
+ private:
+ double m_a, m_b;
+ };
+
+
+ /**
+ * \brief Default c'tor.
+ */
+ SHARK_EXPORT_SYMBOL CrossEntropy();
+
+ /// \brief From INameable: return the class name.
+ std::string name() const
+ { return "Cross Entropy"; }
+
+ /**
+ * \brief Sets default value for Population size.
+ */
+ SHARK_EXPORT_SYMBOL static unsigned suggestPopulationSize( ) ;
+
+ /**
+ * \brief Calculates selection size for the supplied population size.
+ */
+ SHARK_EXPORT_SYMBOL static unsigned suggestSelectionSize( unsigned int populationSize ) ;
+
+ void read( InArchive & archive );
+ void write( OutArchive & archive ) const;
+
+ using AbstractSingleObjectiveOptimizer<RealVector >::init;
+ /**
+ * \brief Initializes the algorithm for the supplied objective function and the initial mean p.
+ */
+ SHARK_EXPORT_SYMBOL void init( ObjectiveFunctionType& function, SearchPointType const& p);
+
+ /**
+ * \brief Inits the Cross Entropy, only with the objective function
+ */
+ SHARK_EXPORT_SYMBOL void init( ObjectiveFunctionType& function );
+
+ /**
+ * \brief Initializes the algorithm for the supplied objective function.
+ */
+ SHARK_EXPORT_SYMBOL void init(
+ ObjectiveFunctionType& function,
+ SearchPointType const& initialSearchPoint,
+ unsigned int populationSize,
+ unsigned int selectionSize,
+ RealVector initialSigma
+ );
+
+ /**
+ * \brief Executes one iteration of the algorithm.
+ */
+ SHARK_EXPORT_SYMBOL void step(ObjectiveFunctionType const& function);
+
+ /** \brief Access the current variance. */
+ RealVector const& variance() const {
+ return m_variance;
+ }
+
+ /** \brief Set the variance to a vector */
+ void setVariance(RealVector variance) {
+ assert(variance.size() == m_variance.size());
+ m_variance = variance;
+ }
+
+ /** \brief Set all variance values */
+ void setVariance(double variance){
+ for(int i = 0; i < m_variance.size(); i++)
+ m_variance(i) = variance;
+ }
+
+ /** \brief Access the current population mean. */
+ RealVector const& mean() const {
+ return m_mean;
+ }
+
+ /**
+ * \brief Returns the size of the parent population.
+ */
+ unsigned int selectionSize() const {
+ return m_selectionSize;
+ }
+
+ /**
+ * \brief Returns a mutable reference to the size of the parent population.
+ */
+ unsigned int& selectionSize(){
+ return m_selectionSize;
+ }
+
+ /**
+ * \brief Returns a immutable reference to the size of the population.
+ */
+ unsigned int populationSize()const{
+ return m_populationSize;
+ }
+
+ /**
+ * \brief Returns a mutable reference to the size of the population.
+ */
+ unsigned int & populationSize(){
+ return m_populationSize;
+ }
+
+ /**
+ * \brief Set the noise type from a raw pointer.
+ */
+ void setNoiseType( INoiseType* noiseType ) {
+ m_noise.reset();
+ m_noise = boost::shared_ptr<INoiseType> (noiseType);
+ }
+
+ /**
+ * \brief Get an immutable reference to Noise Type.
+ */
+ const INoiseType &getNoiseType( ) const {
+ return *m_noise.get();
+ }
+
+
+ protected:
+ /**
+ * \brief Updates the strategy parameters based on the supplied parent population.
+ */
+ SHARK_EXPORT_SYMBOL void updateStrategyParameters( const std::vector<Individual<RealVector, double, RealVector> > & parents ) ;
+
+ std::size_t m_numberOfVariables; ///< Stores the dimensionality of the search space.
+ unsigned int m_selectionSize; ///< Number of vectors chosen when updating distribution parameters.
+ unsigned int m_populationSize; ///< Number of vectors sampled in a generation.
+
+ RealVector m_variance; ///< Variance for sample parameters.
+
+ StrongNoisePtr m_noise; ///< Noise type to apply in the update of distribution parameters.
+
+ RealVector m_mean; ///< The mean of the population.
+
+ unsigned m_counter; ///< Counter for generations.
+
+ Normal< Rng::rng_type > m_distribution; ///< Normal distribution.
+
+ };
+}
+
+#endif
diff --git a/src/Algorithms/DirectSearch/CrossEntropy.cpp b/src/Algorithms/DirectSearch/CrossEntropy.cpp
new file mode 100644
index 0000000..15713df
--- /dev/null
+++ b/src/Algorithms/DirectSearch/CrossEntropy.cpp
@@ -0,0 +1,220 @@
+/*!
+ *
+ * \brief Implements the Cross Entropy Algorithm.
+ *
+ * Christophe Thiery, Bruno Scherrer. Improvements on Learning Tetris with Cross Entropy.
+ * International Computer Games Association Journal, ICGA, 2009, 32. <inria-00418930>
+ *
+ *
+ * \author Jens Holm, Mathias Petræus and Mark Wulff
+ * \date January 2016
+ *
+ * \par Copyright 1995-2015 Shark Development Team
+ *
+ * <BR><HR>
+ * This file is part of Shark.
+ * <http://image.diku.dk/shark/>
+ *
+ * Shark is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Shark is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Shark. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+ #define SHARK_COMPILE_DLL
+
+#include <shark/Core/Exception.h>
+#include <shark/Algorithms/DirectSearch/Operators/Evaluation/PenalizingEvaluator.h>
+#include <shark/Algorithms/DirectSearch/FitnessExtractor.h>
+#include <shark/Algorithms/DirectSearch/Operators/Selection/ElitistSelection.h>
+#include <shark/Algorithms/DirectSearch/CrossEntropy.h>
+
+using namespace shark;
+
+/**
+* \brief Suggest a population size of 100.
+*/
+unsigned CrossEntropy::suggestPopulationSize( ) {
+ /*
+ * Most papers suggests a population size of 100, thus
+ * simply choose 100.
+ */
+ return 100;
+}
+
+/**
+* \brief Calculates Selection Size for the supplied Population Size.
+*/
+unsigned int CrossEntropy::suggestSelectionSize( unsigned int populationSize ) {
+ /*
+ * Most papers says 10% of the population size is used for
+ * the new generation, thus, just take 10% of the population size.
+ */
+ return (unsigned int) (populationSize / 10.0);
+}
+
+CrossEntropy::CrossEntropy()
+: m_variance( 0 )
+, m_counter( 0 )
+, m_distribution( Normal< Rng::rng_type >( Rng::globalRng, 0, 1.0 ) )
+, m_noise (boost::shared_ptr<INoiseType> (new ConstantNoise(0.0)))
+{
+ m_features |= REQUIRES_VALUE;
+}
+
+void CrossEntropy::read( InArchive & archive ) {
+ archive >> m_numberOfVariables;
+ archive >> m_selectionSize;
+ archive >> m_populationSize;
+
+ archive >> m_variance;
+
+ archive >> m_mean;
+
+ archive >> m_counter;
+}
+
+void CrossEntropy::write( OutArchive & archive ) const {
+ archive << m_numberOfVariables;
+ archive << m_selectionSize;
+ archive << m_populationSize;
+
+ archive << m_variance;
+
+ archive << m_mean;
+
+ archive << m_counter;
+}
+
+
+void CrossEntropy::init( ObjectiveFunctionType & function, SearchPointType const& p) {
+
+ unsigned int populationSize = CrossEntropy::suggestPopulationSize( );
+ unsigned int selectionSize = CrossEntropy::suggestSelectionSize( populationSize );
+ RealVector initialVariance(p.size());
+
+ // Most papers set the variance to 100 by default.
+ for(int i = 0; i < p.size(); i++)
+ {
+ initialVariance(i) = 100;
+ }
+ init( function,
+ p,
+ populationSize,
+ selectionSize,
+ initialVariance
+ );
+}
+
+/**
+* \brief Initializes the algorithm for the supplied objective function.
+*/
+void CrossEntropy::init(
+ ObjectiveFunctionType& function,
+ SearchPointType const& initialSearchPoint,
+ unsigned int populationSize,
+ unsigned int selectionSize,
+ RealVector initialVariance
+) {
+ checkFeatures(function);
+ function.init();
+
+ m_numberOfVariables = function.numberOfVariables();
+ m_populationSize = populationSize;
+ m_selectionSize = static_cast<unsigned int>(::floor(selectionSize));
+ m_variance = initialVariance;
+
+ m_mean.resize( m_numberOfVariables );
+ m_mean.clear();
+
+ m_mean = initialSearchPoint;
+ m_best.point = initialSearchPoint;
+ m_best.value = function(initialSearchPoint);
+ m_counter = 0;
+
+}
+
+/**
+* \brief Updates the strategy parameters based on the supplied parent population.
+*/
+void CrossEntropy::updateStrategyParameters( const std::vector<Individual<RealVector, double> > & parents ) {
+
+ /* Calculate the centroid of the parents */
+ RealVector m(m_numberOfVariables);
+ for (int i = 0; i < m_numberOfVariables; i++)
+ {
+ m(i) = 0;
+ for (int j = 0; j < parents.size(); j++)
+ {
+ m(i) += parents[j].searchPoint()(i);
+ }
+ m(i) /= double(parents.size());
+ }
+
+
+ // mean update
+ m_mean = m;
+
+ // Variance update
+ size_t nParents = parents.size();
+ double normalizationFactor = 1.0 / double(nParents);
+
+ for (int j = 0; j < m_numberOfVariables; j++) {
+ double innerSum = 0.0;
+ for (int i = 0; i < parents.size(); i++) {
+ double diff = parents[i].searchPoint()(j) - m(j);
+ innerSum += diff * diff;
+ }
+ innerSum *= normalizationFactor;
+
+ // Apply noise
+ m_variance(j) = innerSum + m_noise->noiseValue(m_counter);
+ }
+
+}
+
+/**
+* \brief Executes one iteration of the algorithm.
+*/
+void CrossEntropy::step(ObjectiveFunctionType const& function){
+
+ std::vector< Individual<RealVector, double> > offspring( m_populationSize );
+
+ PenalizingEvaluator penalizingEvaluator;
+ for( unsigned int i = 0; i < offspring.size(); i++ ) {
+ RealVector sample(m_numberOfVariables);
+ for (int j = 0; j < m_numberOfVariables; j++)
+ {
+ sample(j) = m_distribution(m_mean(j), m_variance(j)); // N (0, 100)
+ }
+ offspring[i].searchPoint() = sample;
+ }
+
+ penalizingEvaluator( function, offspring.begin(), offspring.end() );
+
+ // Selection
+ std::vector< Individual<RealVector, double> > parents( m_selectionSize );
+ ElitistSelection<FitnessExtractor> selection;
+ selection(offspring.begin(),offspring.end(),parents.begin(), parents.end());
+ // Strategy parameter update
+ m_counter++; // increase generation counter
+ updateStrategyParameters( parents );
+
+ m_best.point= parents[ 0 ].searchPoint();
+ m_best.value= parents[ 0 ].unpenalizedFitness();
+}
+
+void CrossEntropy::init(ObjectiveFunctionType& function ){
+ if(!(function.features() & ObjectiveFunctionType::CAN_PROPOSE_STARTING_POINT))
+ throw SHARKEXCEPTION( "[AbstractSingleObjectiveOptimizer::init] Objective function does not propose a starting point");
+ CrossEntropy::init(function,function.proposeStartingPoint());
+}
+
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/shark.git
More information about the debian-science-commits
mailing list