[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