Attempts to fix genetic training
This commit is contained in:
parent
6698148d2c
commit
fbed641470
60
src/main.nim
60
src/main.nim
|
@ -7,6 +7,7 @@ import std/tables
|
|||
import std/math
|
||||
import std/random
|
||||
import std/algorithm
|
||||
import std/strformat
|
||||
|
||||
|
||||
## A bunch of activation functions
|
||||
|
@ -27,28 +28,29 @@ func ind2sub(n: int, shape: tuple[rows, cols: int]): tuple[row, col: int] =
|
|||
|
||||
proc loss(params: TableRef[string, float]): float =
|
||||
## Our loss function for tris
|
||||
result = params["moves"]
|
||||
if int(params["result"]) == GameStatus.Draw.int:
|
||||
result += 6.0
|
||||
elif int(params["result"]) == GameStatus.Lose.int:
|
||||
result += 12.0
|
||||
result = sigmoid(result)
|
||||
if params.hasKey("sameMove"):
|
||||
result = 24 - params["moves"]
|
||||
else:
|
||||
result = params["moves"]
|
||||
if int(params["result"]) == GameStatus.Draw.int:
|
||||
result += 6
|
||||
elif int(params["result"]) == GameStatus.Lose.int:
|
||||
result += 12
|
||||
echo result
|
||||
|
||||
|
||||
proc compareNetworks(a, b: NeuralNetwork): int =
|
||||
if a.params.len() == 0:
|
||||
return -1
|
||||
elif b.params.len() == 0:
|
||||
return 1
|
||||
return cmp(loss(a.params), loss(b.params))
|
||||
|
||||
|
||||
proc crossover(a, b: NeuralNetwork): NeuralNetwork =
|
||||
result = deepCopy(a)
|
||||
for i, layer in a.layers:
|
||||
result.layers[i].weights = layer.weights.copy()
|
||||
result.layers[i].biases = layer.biases.copy()
|
||||
var i = 0
|
||||
while i < a.layers.len():
|
||||
result.layers[i] = new(Layer)
|
||||
result.layers[i].inputSize = a.layers[i].inputSize
|
||||
result.layers[i].outputSize = a.layers[i].outputSize
|
||||
# We inherit 50% of our weights and biases from our first
|
||||
# parent and the other 50% from the other parent
|
||||
result.layers[i].weights = where(rand[float](a.layers[i].weights.shape) >= 0.5, a.layers[i].weights, b.layers[i].weights)
|
||||
|
@ -65,23 +67,25 @@ proc crossover(a, b: NeuralNetwork): NeuralNetwork =
|
|||
|
||||
|
||||
## Our training program
|
||||
const Population = 2
|
||||
const Iterations = 100
|
||||
const Population = 100
|
||||
const Iterations = 300
|
||||
const Epochs = 10
|
||||
const Take = 2
|
||||
const Take = 15
|
||||
|
||||
|
||||
var networks: seq[NeuralNetwork] = @[]
|
||||
var best: seq[NeuralNetwork] = @[]
|
||||
for _ in 0..<Population:
|
||||
networks.add(newNeuralNetwork(@[9, 8, 10, 9], activationFunc=newActivation(sigmoid, func (x, y: float): float = 0.0),
|
||||
lossFunc=newLoss(loss, func (x, y: float): float = 0.0), weightRange=(-1.0, +1.0), learnRate=0.02))
|
||||
networks.add(newNeuralNetwork(@[9, 16, 12, 9], activationFunc=newActivation(sigmoid, func (x, y: float): float = 0.0),
|
||||
lossFunc=newLoss(loss, func (x, y: float): float = 0.0), weightRange=(-1.0, +1.0), biasRange=(-0.5, 0.5),
|
||||
learnRate=0.02))
|
||||
|
||||
var gameOne: TrisGame
|
||||
var gameTwo: TrisGame
|
||||
var one: NeuralNetwork
|
||||
var two: NeuralNetwork
|
||||
var pos: tuple[row, col: int]
|
||||
var lost: bool = false
|
||||
|
||||
for epoch in 0..<Epochs:
|
||||
for iteration in 0..<Iterations:
|
||||
gameOne = newTrisGame()
|
||||
|
@ -99,21 +103,21 @@ for epoch in 0..<Epochs:
|
|||
# We consider this a loss
|
||||
one.params["result"] = float(Lose)
|
||||
two.params["result"] = float(Lose)
|
||||
lost = true
|
||||
one.params["sameMove"] = 1.0
|
||||
two.params["sameMove"] = 1.0
|
||||
break
|
||||
gameTwo.place(TileKind.Self, pos.row, pos.col)
|
||||
gameOne.place(TileKind.Enemy, pos.row, pos.col)
|
||||
if not lost:
|
||||
if not one.params.hasKey("sameMove"):
|
||||
one.params["result"] = gameOne.get().float()
|
||||
two.params["result"] = gameTwo.get().float()
|
||||
else:
|
||||
lost = false
|
||||
one.params["moves"] = gameOne.moves.float()
|
||||
two.params["moves"] = gameTwo.moves.float()
|
||||
networks.sort(cmp=compareNetworks)
|
||||
networks = networks[0..<Take]
|
||||
one = sample(networks)
|
||||
two = sample(networks)
|
||||
while one == two:
|
||||
two = sample(networks)
|
||||
networks.add(one.crossover(two))
|
||||
best = networks[0..<Take]
|
||||
while networks.len() < Population:
|
||||
one = sample(best)
|
||||
two = sample(best)
|
||||
while one == two:
|
||||
two = sample(best)
|
||||
networks.add(one.crossover(two))
|
|
@ -85,7 +85,7 @@ proc newActivation*(function: proc (input: float): float {.noSideEffect.}, deriv
|
|||
result.derivative = derivative
|
||||
|
||||
|
||||
proc newLayer*(inputSize: int, outputSize: int, weightRange: tuple[start, stop: float]): Layer =
|
||||
proc newLayer*(inputSize: int, outputSize: int, weightRange, biasRange: tuple[start, stop: float]): Layer =
|
||||
## Creates a new layer with inputSize input
|
||||
## parameters and outputSize outgoing outputs.
|
||||
## Weights are initialized with random values
|
||||
|
@ -96,7 +96,7 @@ proc newLayer*(inputSize: int, outputSize: int, weightRange: tuple[start, stop:
|
|||
var biases = newSeqOfCap[float](outputSize)
|
||||
var biasGradients = newSeqOfCap[float](outputSize)
|
||||
for _ in 0..<outputSize:
|
||||
biases.add(0.0)
|
||||
biases.add(rand(biasRange.start..biasRange.stop))
|
||||
biasGradients.add(0.0)
|
||||
var weights = newSeqOfCap[seq[float]](inputSize * outputSize)
|
||||
var weightGradients = newSeqOfCap[seq[float]](inputSize * outputSize)
|
||||
|
@ -113,13 +113,13 @@ proc newLayer*(inputSize: int, outputSize: int, weightRange: tuple[start, stop:
|
|||
|
||||
|
||||
proc newNeuralNetwork*(layers: seq[int], activationFunc: Activation, lossFunc: Loss,
|
||||
learnRate: float, weightRange: tuple[start, stop: float]): NeuralNetwork =
|
||||
learnRate: float, weightRange, biasRange: tuple[start, stop: float]): NeuralNetwork =
|
||||
## Initializes a new neural network
|
||||
## with the given layer layout
|
||||
new(result)
|
||||
result.layers = newSeqOfCap[Layer](len(layers))
|
||||
for i in 0..<layers.high():
|
||||
result.layers.add(newLayer(layers[i], layers[i + 1], weightRange))
|
||||
result.layers.add(newLayer(layers[i], layers[i + 1], weightRange, biasRange))
|
||||
result.activation = activationFunc
|
||||
result.loss = lossFunc
|
||||
result.learnRate = learnRate
|
||||
|
|
Loading…
Reference in New Issue