NeuroEvolution

This tutorial introduces using the CGP-Library as a NeuroEvolutionary training method.

NeuroEvolution is the application of Evolutionary Algorithms towards the training of artificial neural networks.  In the case of CGP it is referred to as Cartesian Genetic Programming of Artificial Neural Networks (CGPANN).

If you have been wondering why the CGP-Library contains connection weights which have previously been ignored, this is why.  If you intend to use CGP-Library for NeuroEvolution is is advised that you read the Getting Started and Custom Fitness Function tutorials first.

Summary
NeuroEvolutionThis tutorial introduces using the CGP-Library as a NeuroEvolutionary training method.
The ProgramA simple program demonstrating the use of the CGP-Library towards NeuroEvolution.
Stepping Through the CodeA close look at each line of the example code.

The Program

A simple program demonstrating the use of the CGP-Library towards NeuroEvolution.

The program below is provided in the CGP-Library download within /examples/neuroEvolution.c and is included in the code:blocks project.

#include <stdio.h>
#include <math.h>
#include "../src/cgp.h"

double sinWave(struct parameters *params, struct chromosome *chromo, struct dataSet *data){

    double i;

    double error = 0;
    double range = 6;
    double stepSize = 0.5;

    double inputs[1];

    for(i=0; i<range; i += stepSize){

        inputs[0] = i;

        executeChromosome(chromo, inputs);

        error += fabs(getChromosomeOutput(chromo, 0) - sin(i));
    }
    return error;
}


int main(void){

    struct parameters *params = NULL;
    struct chromosome *chromo = NULL;

    int numInputs = 1;
    int numNodes = 20;
    int numOutputs = 1;
    int nodeArity = 5;

    int numGens = 25000;
    double targetFitness = 0.5;
    int updateFrequency = 500;

    double weightRange = 5;

    params = initialiseParameters(numInputs, numNodes, numOutputs, nodeArity);

    setTargetFitness(params, targetFitness);

    setUpdateFrequency(params, updateFrequency);

    setConnectionWeightRange(params, weightRange);

    setCustomFitnessFunction(params, sinWave, "sinWave");

    addNodeFunction(params, "tanh,softsign");

    chromo = runCGP(params, NULL, numGens);

    printChromosome(chromo, 1);

    freeChromosome(chromo);
    freeParameters(params);

    return 0;
}

Stepping Through the Code

A close look at each line of the example code.

Artificial neural networks typically output values between [0,1] or [-1,1] therefore the dataSet used should contain outputs with these ranges or a custom fitness function should be defined which accommodates these output ranges.  Here a custom fitness function shall be described.  See Custom Fitness Function for further details on defining custom fitness functions.

The custom fitness function defined here assesses how accurately the given chromosome implements a sin wave.

double sinWave(struct parameters *params, struct chromosome *chromo, struct dataSet *data){

double i;

double error = 0;
double range = 6;
double stepSize = 0.5;

double inputs[1];

for(i=0; i<range; i += stepSize){

    inputs[0] = i;

    executeChromosome(chromo, inputs);

    error += fabs(getChromosomeOutput(chromo, 0) - sin(i));
}
return error;
}

In the main function a parameters and chromosome structure are defined.  The parameters structure is then initialised and various attributes are set.

Of these attributes the connection weight range is set using setConnectionWeightRange.  Where the second parameter gives the connection weight range in the form of +/- connection weight range.  The connection weight range gives the range of values which each connection weight can take.

setConnectionWeightRange(params, weightRange);

Next we change the default fitness function to be our custom sinWave fitness function.

setCustomFitnessFunction(params, sinWave, "sinWave");

In previous tutorials the node functions used have been standard genetic programming functions, here however we shall be using neuron transfer functions.  The neuron transfer functions selected are hyperbolic tangent and soft sign.  Both hyperbolic tangent and soft sign functions produce outputs in the range [-1,1] which is suited to our sinWave fitness function.

addNodeFunction(params, "tanh,softsign");

Now when we use runCGP or repeatCGP the CGP-Library shall be evolving Artificial Neural Networks!

chromo = runCGP(params, NULL, numGens);

And that’s it, by using neuron transfer function and selecting suitable fitness functions the CGP-Library can be easily used for NeuroEvolution.

This tutorial introduces and steps through a simple program which uses the CGP-Library to solve a symbolic regression problem.
This tutorial introduces how to use a custom fitness functions with the CGP-Library.
struct dataSet
Stores a data set which can be used by fitness functions when calculating a chromosomes fitness.
struct parameters
Stores general evolutionary and chromosome parameters used by the CGP-Library.
struct chromosome
Stores a CGP chromosome instances used by the CGP-Library.
DLL_EXPORT void setConnectionWeightRange(struct parameters *params,
double weightRange)
Sets the connection weight range in the given parameters.
DLL_EXPORT struct chromosome* runCGP(struct parameters *params,
struct dataSet *data,
int numGens)
Applies CGP to the given task.
DLL_EXPORT struct results* repeatCGP(struct parameters *params,
struct dataSet *data,
int numGens,
int numRuns)
Repeatedly applies CGP to the given task.
Close