public Ann(int inputs, int outputs, ActivationFunction.ActivationMethod activationMethod) { if (inputs < 1 || outputs < 1) { throw new ArgumentOutOfRangeException("There must be at least one input and one output."); } this.activationMethod = activationMethod; InitNeurons(inputs, outputs); InitSynapses(); }
public Ann Train(int maxGenerations, int generationSize, double?errorThreshold, int mutationRate, int mutationRolls, bool waitForFlag, double[][] inputs, double[][] expectedOutputs, Crossover.CrossoverOperation crossoverOperation, ActivationFunction.ActivationMethod activationMethod) { Ann[] generation = new Ann[generationSize]; int inputCount = inputs[0].Length; int outputCount = expectedOutputs[0].Length; for (int generationId = 0; generationId < maxGenerations; generationId++) { if (generationId == 0) { for (int startingIndividual = 0; startingIndividual < generationSize; startingIndividual++) { Ann ann = new Ann(inputCount, outputCount, activationMethod); double error = CalculateError(ann, inputs, expectedOutputs); ann.Error = error; generation[startingIndividual] = ann; } } else { Ann parentA = generation[0]; Ann parentB = generation[1]; for (int newIndividual = 0; newIndividual < generationSize; newIndividual++) { generation = generation.OrderByDescending(x => x.Error).ToArray(); Ann child = crossoverOperation.Invoke(parentA, parentB); Mutations.RollToCauseRandomMutation(child, mutationRate, mutationRolls); double error = CalculateError(child, inputs, expectedOutputs); child.Error = error; if (child.Error < generation[0].Error) { generation[0] = child; } } } generation.ToList().ForEach(x => { x.Error = CalculateError(x, inputs, expectedOutputs); x.Generation = generationId; }); generation = generation.OrderBy(x => x.Error).ToArray(); if (waitForFlag) { waitFlag = true; OnGenerationEnd?.Invoke(generation[0]); while (waitFlag) { } } else { OnGenerationEnd?.Invoke(generation[0]); } if (errorThreshold != null && generation[0].Error < errorThreshold) { return(generation[0]); } } return(generation[0]); }