func (shc *StochasticHillClimber) Train(cortex *ng.Cortex, scape Scape) (resultNeuralNet *ng.Cortex, fitness float64, succeeded bool) { shc.validate() numAttempts := 0 fittestNeuralNet := cortex.Copy() resultNeuralNet = cortex // Apply NN to problem and save fitness fitness = scape.Fitness(fittestNeuralNet) logg.LogTo("MAIN", "Initial fitness: %v", fitness) if fitness > shc.FitnessThreshold { succeeded = true return } for i := 0; ; i++ { // Save the genotype candidateNeuralNet := fittestNeuralNet.Copy() // Perturb synaptic weights and biases PerturbParameters(candidateNeuralNet, shc.WeightSaturationRange) // Re-Apply NN to problem candidateFitness := scape.Fitness(candidateNeuralNet) logg.LogTo("DEBUG", "candidate fitness: %v", fitness) // If fitness of perturbed NN is higher, discard original NN and keep new // If fitness of original is higher, discard perturbed and keep old. if candidateFitness > fitness { logg.LogTo("MAIN", "i: %v candidateFitness: %v > fitness: %v", i, candidateFitness, fitness) i = 0 fittestNeuralNet = candidateNeuralNet resultNeuralNet = candidateNeuralNet.Copy() fitness = candidateFitness } if candidateFitness > shc.FitnessThreshold { logg.LogTo("MAIN", "candidateFitness: %v > Threshold. Success at i=%v", candidateFitness, i) succeeded = true break } if ng.IntModuloProper(i, shc.MaxIterationsBeforeRestart) { logg.LogTo("MAIN", "** restart hill climber. fitness: %f i/max: %d/%d", fitness, numAttempts, shc.MaxAttempts) numAttempts += 1 i = 0 shc.resetParametersToRandom(fittestNeuralNet) ng.SeedRandom() } if numAttempts >= shc.MaxAttempts { succeeded = false break } } return }
func (tmt *TopologyMutatingTrainer) Train(cortex *ng.Cortex, scape Scape) (fittestCortex *ng.Cortex, succeeded bool) { ng.SeedRandom() shc := tmt.StochasticHillClimber includeNonTopological := false mutators := CortexMutatorsNonRecurrent(includeNonTopological) originalCortex := cortex.Copy() currentCortex := cortex // Apply NN to problem and save fitness logg.LogTo("MAIN", "Get initial fitness") fitness := scape.Fitness(currentCortex) logg.LogTo("MAIN", "Initial fitness: %v", fitness) if fitness > shc.FitnessThreshold { succeeded = true return } for i := 0; ; i++ { logg.LogTo("MAIN", "Before mutate. i/max: %d/%d", i, tmt.MaxAttempts) // before we mutate the cortex, we need to init it, // otherwise things like Outsplice will fail because // there are no DataChan's. currentCortex.Init() // mutate the network randInt := RandomIntInRange(0, len(mutators)) mutator := mutators[randInt] ok, _ := mutator(currentCortex) if !ok { logg.LogTo("MAIN", "Mutate didn't work, retrying...") continue } isValid := currentCortex.Validate() if !isValid { logg.LogPanic("Cortex did not validate") } filenameJson := fmt.Sprintf("cortex-%v.json", i) currentCortex.MarshalJSONToFile(filenameJson) filenameSvg := fmt.Sprintf("cortex-%v.svg", i) currentCortex.RenderSVGFile(filenameSvg) logg.LogTo("MAIN", "Post mutate cortex svg: %v json: %v", filenameSvg, filenameJson) logg.LogTo("MAIN", "Run stochastic hill climber..") // memetic step: call stochastic hill climber and see if it can solve it fittestCortex, _, succeeded = shc.Train(currentCortex, scape) logg.LogTo("MAIN", "stochastic hill climber finished. succeeded: %v", succeeded) if succeeded { succeeded = true break } if i >= tmt.MaxAttempts { succeeded = false break } if ng.IntModuloProper(i, tmt.MaxIterationsBeforeRestart) { logg.LogTo("MAIN", "** Restart . i/max: %d/%d", i, tmt.MaxAttempts) currentCortex = originalCortex.Copy() isValid := currentCortex.Validate() if !isValid { currentCortex.Repair() // TODO: remove workaround isValid = currentCortex.Validate() if !isValid { logg.LogPanic("Cortex could not be repaired") } } } } return }