genetic.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. package genetic
  2. import (
  3. "fmt"
  4. "log"
  5. "math/rand"
  6. "sort"
  7. neuralnetwork "../neuralnetwork"
  8. )
  9. type PopulationConfig struct {
  10. PopulationSize int
  11. SelectionSize float64 // 0..1 persentage of success individuals to be used as parents for population
  12. CrossbreedPart float64 // 0..1 persentage of weights and biases to be exchanged beetween individuals while Crossbreed
  13. }
  14. type Population struct {
  15. populationConfig *PopulationConfig
  16. Networks []*neuralnetwork.NeuralNetwork
  17. verifier PopulationVerifier
  18. mutagen Mutagen
  19. etalonsCount int
  20. }
  21. func NewPopulation(verifier PopulationVerifier, mutagen Mutagen, populationConfig PopulationConfig, sizes []int) (p *Population) {
  22. if populationConfig.PopulationSize%2 != 0 {
  23. return nil
  24. }
  25. p = &Population{
  26. populationConfig: &populationConfig,
  27. Networks: make([]*neuralnetwork.NeuralNetwork, populationConfig.PopulationSize),
  28. verifier: verifier,
  29. mutagen: mutagen,
  30. etalonsCount: int(float64(populationConfig.PopulationSize) * populationConfig.SelectionSize),
  31. }
  32. if p.etalonsCount%2 != 0 {
  33. p.etalonsCount -= 1
  34. }
  35. for i := 0; i < populationConfig.PopulationSize; i++ {
  36. var err error
  37. p.Networks[i], err = neuralnetwork.NewNeuralNetwork(sizes, nil)
  38. if err != nil {
  39. log.Fatal("Could not initialize NeuralNetwork")
  40. }
  41. }
  42. return
  43. }
  44. func (p *Population) NaturalSelection(generationCount int) {
  45. for g := 0; g < generationCount; g++ {
  46. p.crossbreedPopulation(p.verifier.Verify(p))
  47. }
  48. }
  49. func (p *Population) crossbreedPopulation(fitnesses []*IndividalFitness) {
  50. sort.Slice(fitnesses, func(i, j int) bool {
  51. return fitnesses[i].Fitness > fitnesses[j].Fitness //Descent order best will be on top, worst in the bottom
  52. })
  53. //Collect etalons from upper part of neural network list and crossbreed/mutate them
  54. etalonNetworks := make([]*neuralnetwork.NeuralNetwork, p.etalonsCount)
  55. for i := 1; i < p.etalonsCount; i += 2 {
  56. firstParent := fitnesses[i-1].Index
  57. secondParent := fitnesses[i].Index
  58. fmt.Printf("Result i %v firstParent %v secondParent %v firstFitness %v secondFitness %v\n", i, firstParent, secondParent, fitnesses[i-1].Fitness, fitnesses[i].Fitness)
  59. etalonNetworks[i-1] = p.Networks[firstParent].Copy()
  60. etalonNetworks[i] = p.Networks[secondParent].Copy()
  61. crossbreed(p.Networks[firstParent], p.Networks[secondParent], p.populationConfig.CrossbreedPart)
  62. p.mutagen.Mutate(p.Networks[firstParent])
  63. p.mutagen.Mutate(p.Networks[secondParent])
  64. }
  65. //Rest of networks are based on collected etalons but crossbreed/mutate own way
  66. for i := p.etalonsCount + 1; i < p.populationConfig.PopulationSize; i += 2 {
  67. firstParent := fitnesses[i-1].Index
  68. secondParent := fitnesses[i].Index
  69. fmt.Printf("Result i %v firstParent %v secondParent %v firstFitness %v secondFitness %v firstEtalon %v secondEtalon %v\n",
  70. i, firstParent, secondParent,
  71. fitnesses[i-1].Fitness, fitnesses[i].Fitness,
  72. fitnesses[(i-1)%p.etalonsCount].Index, fitnesses[(i)%p.etalonsCount].Index)
  73. firstParentEtalon := etalonNetworks[(i-1)%p.etalonsCount]
  74. secondParenEtalon := etalonNetworks[(i)%p.etalonsCount]
  75. p.Networks[firstParent] = firstParentEtalon.Copy()
  76. p.Networks[secondParent] = secondParenEtalon.Copy()
  77. crossbreed(p.Networks[firstParent], p.Networks[secondParent], p.populationConfig.CrossbreedPart)
  78. p.mutagen.Mutate(p.Networks[firstParent])
  79. p.mutagen.Mutate(p.Networks[secondParent])
  80. }
  81. }
  82. func crossbreed(firstParent, secondParent *neuralnetwork.NeuralNetwork, crossbreedPart float64) {
  83. for l := 1; l < firstParent.LayerCount; l++ {
  84. firstParentWeights := firstParent.Weights[l]
  85. secondParentWeights := secondParent.Weights[l]
  86. firstParentBiases := firstParent.Biases[l]
  87. secondParentBiases := secondParent.Biases[l]
  88. r, c := firstParentWeights.Dims()
  89. rp := int(float64(r) * crossbreedPart)
  90. cp := int(float64(c) * crossbreedPart)
  91. r = int(rand.Uint32())%(r-rp) + rp
  92. c = int(rand.Uint32())%(c-cp) + cp
  93. // for i := 0; i < int(float64(r)*crossbreedPart); i++ {
  94. for i := 0; i < r; i++ {
  95. for j := 0; j < c; j++ {
  96. // Swap first half of weights
  97. w := firstParentWeights.At(i, j)
  98. firstParentWeights.Set(i, j, secondParentWeights.At(i, j))
  99. secondParentWeights.Set(i, j, w)
  100. }
  101. // Swap first half of biases
  102. b := firstParentBiases.At(i, 0)
  103. firstParentBiases.Set(i, 0, secondParentBiases.At(i, 0))
  104. secondParentBiases.Set(i, 0, b)
  105. }
  106. }
  107. }