public NeuralNetwork(int pNbInputs, int[] pNbHiddens, int pNbOutputs, ActivationFunctions.eActivationFunction pActivationFunction = ActivationFunctions.eActivationFunction.Sigmoid, bool pAllowNegative = false) { NbInputs = pNbInputs; NbHiddens = pNbHiddens; NbOutputs = pNbOutputs; _allowNegative = pAllowNegative; _rnd = new Random(); ActivationFunction = pActivationFunction; _weights = new List <Matrix>(); _neurons = new List <Matrix>(); _bias = new List <Matrix>(); Matrix Weights_IH = new Matrix(pNbHiddens[0], pNbInputs); Matrix Bias = new Matrix(pNbHiddens[0], 1); Weights_IH.Randomize(_rnd, pAllowNegative); Bias.Randomize(_rnd, pAllowNegative); _weights.Add(Weights_IH); _bias.Add(Bias); for (int i = 0; i < pNbHiddens.Length; i++) { Matrix w; Matrix b; if (i < pNbHiddens.Length - 1) { w = new Matrix(pNbHiddens[i + 1], pNbHiddens[i]); b = new Matrix(pNbHiddens[i + 1], 1); } else { w = new Matrix(pNbOutputs, pNbHiddens[i]); b = new Matrix(pNbOutputs, 1); } // Poids w.Randomize(_rnd, pAllowNegative); _weights.Add(w); // Biais b.Randomize(_rnd, pAllowNegative); _bias.Add(b); } }
/// <summary> /// Créé une nouvelle génération de la population. /// </summary> /// <param name="pSavePopulation">Sauvegarde la population avant de générer une nouvelle.</param> /// <param name="pPathFile">Chemin du fichier de destination.</param> public void NextGeneration(bool pSavePopulation = false, string pPathFile = "Population") { int populationNumber = Genomes.Count; #region Evaluation du score total int totalFitness = 0; int maxFitness = 0; for (int i = 0; i < Genomes.Count; i++) { GeneticNeuralNetwork g = Genomes[i]; g.FitnessScore = (int)Math.Pow(g.FitnessScore, 4); if (g.FitnessScore > 0) { totalFitness += g.FitnessScore; } if (g.FitnessScore > maxFitness) { maxFitness = g.FitnessScore; } } #endregion #region Sauvegarde la génération actuelle if (pSavePopulation) { Export(totalFitness + "_" + pPathFile); } #endregion // Si le Fitness max est supérieur au minimum acceptable, // conserve le nombre de couches cachées du réseau de neurones. // Sinon, génère un nouveau schéma de réseau de neurones. if (maxFitness > MinimumAcceptableFitness) { #region Génère des enfants List <GeneticNeuralNetwork> nextPopulation = new List <GeneticNeuralNetwork>(); while (nextPopulation.Count < populationNumber) { bool selected = false; GeneticNeuralNetwork p1; GeneticNeuralNetwork p2; #region Sélectionne deux parents et les retire du sac do { int indexP1 = _rnd.Next(Genomes.Count); p1 = Genomes[indexP1]; if (_rnd.Next(totalFitness) < p1.FitnessScore) { selected = true; } } while (!selected); selected = false; do { int indexP2 = _rnd.Next(Genomes.Count); p2 = Genomes[indexP2]; if (_rnd.Next(totalFitness) < p1.FitnessScore) { selected = true; } } while (!selected); #endregion GeneticNeuralNetwork[] childs = GeneticNeuralNetwork.CreateChilds(p1, p2, _rnd); if (nextPopulation.Count == populationNumber - 1) { nextPopulation.Add(childs[0]); } else { nextPopulation.AddRange(childs); } } #endregion #region Effectue une mutation sur les enfants for (int i = 0; i < nextPopulation.Count; i++) { GeneticNeuralNetwork c = nextPopulation[i]; c.Mutate(_rnd, MutationRate); } #endregion OnGenomesDeletion?.Invoke(this, new PopulationManagerEventArgs(Genomes)); Genomes = nextPopulation; } else { GeneticNeuralNetwork g = Genomes[0]; int nbInputs = g.NbInputs; int nbOutputs = g.NbOutputs; int[] hidden = new int[_rnd.Next(1, 20)]; ActivationFunctions.eActivationFunction function = g.ActivationFunction; for (int i = 0; i < hidden.Length; i++) { hidden[i] = _rnd.Next(nbOutputs, nbInputs + nbOutputs); } OnGenomesDeletion?.Invoke(this, new PopulationManagerEventArgs(Genomes)); Genomes = new List <GeneticNeuralNetwork>(); for (int i = 0; i < populationNumber; i++) { Genomes.Add(new GeneticNeuralNetwork(nbInputs, hidden, nbOutputs, function, true)); } } OnGenomesChanged?.Invoke(this, new PopulationManagerEventArgs(Genomes)); Generation++; }