colgreen / sharpneat

SharpNEAT - Evolution of Neural Networks. A C# .NET Framework.
https://sharpneat.sourceforge.io/
Other
388 stars 100 forks source link

Where does the initial genome come from? #37

Closed Supagoat closed 5 years ago

Supagoat commented 5 years ago

All of the examples I've seen read a genome from an XML file.... How did that genome ever get created? If I have a new experiment I want to run, how do I just generate a default NeatGenome to start it off? Or can I just create one with an empty network and SharpNeat will do the rest over the generations?

colgreen commented 5 years ago

All of the problem tasks are represented by an 'experiment' class (i.e. an implementation of IGuiNeatExperiment or INeatExperiment), and each of those classes has this method (or a variation on it):

    /// <summary>
    /// Create and return a NeatEvolutionAlgorithm object ready for running the NEAT algorithm/search. Various sub-parts
    /// of the algorithm are also constructed and connected up.
    /// This overload accepts a population size parameter that specifies how many genomes to create in an initial randomly
    /// generated population.
    /// </summary>
    public NeatEvolutionAlgorithm<NeatGenome> CreateEvolutionAlgorithm(int populationSize)
    {
        // Create a genome factory with our neat genome parameters object and the appropriate number of input and output neuron genes.
        IGenomeFactory<NeatGenome> genomeFactory = CreateGenomeFactory();

        // Create an initial population of randomly generated genomes.
        List<NeatGenome> genomeList = genomeFactory.CreateGenomeList(populationSize, 0);

        // Create evolution algorithm.
        return CreateEvolutionAlgorithm(genomeFactory, genomeList);
    }

So you can see that genomFactory creates new genomes. It does this as follows. Each problem domain defines how many neural net inputs and outputs are requried for that task (these are fixed numbers for a given task). So we can create a minimal genome with just input and output nodes, and no hidden nodes. The genome factory goes one step further and creates random connections between the input and output nodes in each genome.

How many connections are created is controlled by this property/setting:

public class NeatGenomeParameters
{
    /// <summary>
    /// Gets or sets a proportion that specifies the number of interconnections to make between input and 
    /// output neurons in an initial random population. This is a proportion of the total number of
    /// possible interconnections.
    /// </summary>
    public double InitialInterconnectionsProportion
    {
        get { return _initialInterconnectionsProportion; }
        set { _initialInterconnectionsProportion = value; }
    }
}

So e.g. if you run the GUI and select a task, click the 'Create Random Population' button and then 'Start', then the evolutionary algorithm is working with a randomly generated initial population using the scheme described above.

Hope that helps.

Colin

Supagoat commented 5 years ago

Aha, gotcha thanks! I had gotten confused by the constructor of NeatGenome which takes a GenomeFactory of its own. That sent me down a circular dependency confusion.