Ejemplo n.º 1
0
        /// <summary>
        /// Create a single child genome by performing crossover on two or more parents.
        /// </summary>
        /// <param name="rnd">A random number generator.</param>
        /// <param name="parents">The parents.</param>
        /// <param name="cutLength">The cut length for sequences of genes that crossover together.</param>
        /// <returns>The new child genome.</returns>
        public static Genome[] Crossover(Random rnd, Genome[] parents, int cutLength)
        {
            int genomeSize = parents[0].Genes.Length;
            var offspring = new Genome(genomeSize);

            var result = new Genome[1];
            result[0] = offspring;

            int currentIndex = 0;
            int cutCount = 0;
            int parentIndex = 0;
            Genome currentParent = parents[parentIndex];

            while (currentIndex < parents[0].Genes.Length)
            {
                offspring.Genes[currentIndex] = currentParent.Genes[currentIndex];
                currentIndex++;
                cutCount++;
                if (cutCount > cutLength)
                {
                    parentIndex++;
                    if (parentIndex >= parents.Length)
                    {
                        parentIndex = 0;
                    }
                    currentParent = parents[parentIndex];
                    cutCount = 0;
                }
            }

            return result;
        }
Ejemplo n.º 2
0
        public double[] Compute(double[] input, Genome genome)
        {
            // first, compute the output values of each of the RBFs.
            // Add in one additional RBF output for bias (always set to one).
            var rbfOutput = new double[_rbfCount + 1];
            rbfOutput[rbfOutput.Length - 1] = 1; // bias

            for (int rbfIndex = 0; rbfIndex < _rbfCount; rbfIndex++)
            {
                // weight the input
                var weightedInput = new double[input.Length];

                for (int inputIndex = 0; inputIndex < input.Length; inputIndex++)
                {
                    int memoryIndex = _indexInputWeights + (rbfIndex*_inputCount) + inputIndex;
                    weightedInput[inputIndex] = input[inputIndex]*genome.Genes[memoryIndex];
                }

                // calculate the rbf
                rbfOutput[rbfIndex] = CalculateGaussian(genome, rbfIndex, weightedInput);
            }

            // second, calculate the output, which is the result of the weighted result of the RBF's.
            var result = new double[_outputCount];

            for (int outputIndex = 0; outputIndex < result.Length; outputIndex++)
            {
                double sum = 0;
                for (int rbfIndex = 0; rbfIndex < rbfOutput.Length; rbfIndex++)
                {
                    int memoryIndex = _indexOutputWeights + (outputIndex*rbfOutput.Length) + rbfIndex;
                    sum += rbfOutput[rbfIndex]*genome.Genes[memoryIndex];
                }
                result[outputIndex] = sum;
            }

            return result;
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Score the model when the output is regression.  
        /// For regression, the score is mean square error (MSE).
        /// http://www.heatonresearch.com/wiki/Mean_Square_Error
        /// </summary>
        /// <param name="model">The model to score.</param>
        /// <param name="testSubject">The test subject.</param>
        /// <param name="input">The input.</param>
        /// <param name="ideal">The ideal.</param>
        /// <returns>The score.</returns>
        private static double ScoreRegression(IGAModel model, Genome testSubject, double[][] input, double[][] ideal)
        {
            double error = 0;
            double elementCount = 0;

            Parallel.For(0, input.Length, row =>
            {
                double[] output = model.Compute(input[row], testSubject);
                for (int col = 0; col < output.Length; col++)
                {
                    double delta = output[col] - ideal[row][col];
                    error += delta * delta;
                    elementCount++;
                }
            });

            return Math.Sqrt(error / elementCount);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Score the model when the output is classification.  
        /// For classification, the score is the percentage correct.
        /// </summary>
        /// <param name="model">The model to score.</param>
        /// <param name="testSubject">The test subject.</param>
        /// <param name="input">The input.</param>
        /// <param name="ideal">The ideal.</param>
        /// <returns>The score.</returns>
        private static double ScoreClassification(IGAModel model, Genome testSubject, double[][] input, double[][] ideal)
        {
            double error = 0;
            double elementCount = 0;
            int badCount = 0;

            Parallel.For(0, input.Length, row =>
            {
                double[] output = model.Compute(input[row], testSubject);
                int outputIndex = FindTopIndex(output);
                int idealIndex = FindTopIndex(ideal[row]);
                if (outputIndex != idealIndex)
                {
                    badCount++;
                }
                elementCount++;
            });

            return badCount / elementCount;
        }
Ejemplo n.º 5
0
 /// <summary>
 /// Score the model for regression or classification.
 /// For classification, the score is the percentage correct.  
 /// For regression, the score is mean square error (MSE).
 /// http://www.heatonresearch.com/wiki/Mean_Square_Error
 /// </summary>
 /// <param name="model">The model to score.</param>
 /// <param name="testSubject">The test subject.</param>
 /// <param name="input">The input.</param>
 /// <param name="ideal">The ideal.</param>
 /// <returns>The score.</returns>
 public static double Score(IGAModel model, Genome testSubject, double[][] input, double[][] ideal)
 {
     if (ideal[0].Length > 1)
     {
         return ScoreClassification(model, testSubject, input, ideal);
     }
     return ScoreRegression(model, testSubject, input, ideal);
 }
Ejemplo n.º 6
0
        /// <summary>
        /// Produce a new genome, by randomly changing the parent.  However, the parent is
        /// not actually changed. 
        /// </summary>
        /// <param name="rnd">Random number generator.</param>
        /// <param name="parent">The parent genome.</param>
        /// <param name="minRange">The minimum amount by which a gene will change.</param>
        /// <param name="maxRange">The maximum amount by which a gene will change.</param>
        /// <returns>The new child genome.</returns>
        public static Genome Mutate(Random rnd, Genome parent, double minRange, double maxRange)
        {
            bool didMutate = false;
            var result = new Genome(parent.Genes.Length);
            for (int i = 0; i < parent.Genes.Length; i++)
            {
                if (rnd.NextDouble() < 0.2)
                {
                    double d = RandomUtil.RangeDouble(rnd, minRange, maxRange);
                    result.Genes[i] += d;
                    didMutate = true;
                }
                else
                {
                    result.Genes[i] = parent.Genes[i];
                }
            }

            if (!didMutate)
            {
                int i = RandomUtil.RangeInt(rnd, 0, parent.Genes.Length);
                result.Genes[i] += RandomUtil.RangeDouble(rnd, minRange, maxRange);
            }

            return result;
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Generate a random starting population.
        /// </summary>
        public void Generate()
        {
            var rnd = new Random();
            _genomes.Clear();
            _bestGenome = null;

            for (int i = 0; i < _config.PopulationSize; i++)
            {
                Genome genome = _config.Model.GenerateRandomGenome(rnd, _config);
                _genomes.Add(genome);
                UpdateBestGenome(genome);
            }
        }
Ejemplo n.º 8
0
 public Genome Mutate(Random rnd, Genome parent)
 {
     return TypicalGAModel.Mutate(rnd, parent, -0.01, +0.01);
 }
Ejemplo n.º 9
0
 /// <summary>
 /// Update the best genome.
 /// </summary>
 /// <param name="g">The genome to evaluate.</param>
 private void UpdateBestGenome(Genome g)
 {
     if (_config.MaxGoal)
     {
         if (_bestGenome == null || g.Score > _bestGenome.Score)
         {
             _bestGenome = g;
         }
     }
     else
     {
         if (_bestGenome == null || g.Score < _bestGenome.Score)
         {
             _bestGenome = g;
         }
     }
 }
Ejemplo n.º 10
0
 /// <summary>
 /// Score all genomes.
 /// </summary>
 /// <param name="trainingInput">The training input.</param>
 /// <param name="trainingIdeal">The ideal output.</param>
 public void ScoreAll(double[][] trainingInput, double[][] trainingIdeal)
 {
     _bestGenome = null;
     foreach (Genome genome in _genomes)
     {
         UpdateBestGenome(genome);
         genome.Score = _config.Model.Score(genome, trainingInput, trainingIdeal);
     }
 }
Ejemplo n.º 11
0
 /// <summary>
 /// Determine if one genome is better than another.
 /// </summary>
 /// <param name="a">The first genome.</param>
 /// <param name="b">The second genome.</param>
 /// <returns>True, if a is better than b.</returns>
 public bool IsBetterThan(Genome a, Genome b)
 {
     if (_config.MaxGoal)
     {
         return a.Score > b.Score;
     }
     return a.Score < b.Score;
 }
Ejemplo n.º 12
0
        private double CalculateGaussian(Genome genome, int rbfIndex, double[] xValues)
        {
            int rbfArrayIndex = _indexRBFParams + ((_inputCount + 1)*rbfIndex);
            double value = 0;
            double width = genome.Genes[rbfArrayIndex];

            for (int i = 0; i < _inputCount; i++)
            {
                double center = genome.Genes[rbfArrayIndex + i + 1];
                value += Math.Pow(xValues[i] - center, 2)/(2.0*width*width);
            }

            return Math.Exp(-value);
        }
Ejemplo n.º 13
0
 public double Score(Genome testSubject, double[][] input, double[][] ideal)
 {
     return TypicalGAModel.Score(this, testSubject, input, ideal);
 }
Ejemplo n.º 14
0
        public static Genome GenerateRandomGenome(Random rnd, ConfigScript script, int genomeSize)
        {
            var result = new Genome(genomeSize);

            for (int i = 0; i < result.Genes.Length; i++)
            {
                result.Genes[i] = rnd.NextDouble();
            }

            return result;
        }
Ejemplo n.º 15
0
 /// <summary>
 /// Add a new child genome and replace low-scoring population member.
 /// This is how unfit genomes are removed.
 /// </summary>
 /// <param name="rnd">A random number generator.</param>
 /// <param name="child">The new child to add.</param>
 public void AddChildAndReplace(Random rnd, Genome child)
 {
     int killIndex = TournamentForWorst(rnd);
     _genomes[killIndex] = child;
     UpdateBestGenome(child);
 }
Ejemplo n.º 16
0
        /// <summary>
        /// Perform a crossover.
        /// </summary>
        /// <param name="rnd">The random number generator.</param>
        private void PerformCrossover(Random rnd)
        {
            // first, find the correct number of optimal parents
            int parentsNeeded = _population.Config.MaxParents;
            var parents = new Genome[parentsNeeded];
            int parentIndex = 0;
            int tries = 0;

            while (parentIndex < parentsNeeded)
            {
                // select a potential parent
                Genome parent = _population.TournamentForBest(rnd);
                bool goodParent = true;

                // do we already have this parent?
                for (int i = 0; i < parentIndex; i++)
                {
                    if (parents[i] == parent)
                    {
                        goodParent = false;
                        break;
                    }
                }

                // add the parent if acceptable
                if (goodParent)
                {
                    parents[parentIndex++] = parent;
                }

                // might get into an endless loop with a really small population, don't do that!
                tries++;
                if (tries > 10000)
                {
                    throw new InvalidOperationException("Failed to find acceptable parenents for crossover.");
                }
            }

            // we now have a good batch of parents, so call the crossover operation
            Genome[] children = _population.Config.Model.Crossover(rnd, parents);

            // integrate any children into the population
            foreach (Genome child in children)
            {
                child.Score = _population.Config.Model.Score(child, _trainingInput, _trainingIdeal);
                _population.AddChildAndReplace(rnd, child);
            }
        }
Ejemplo n.º 17
0
 public Genome[] Crossover(Random rnd, Genome[] parents)
 {
     return TypicalGAModel.Crossover(rnd, parents, _cutLength);
 }