public void Descend(double[] input, double momentum, double learningrate, bool output, bool usemomentum) { for (int i = 0; i < Length; i++) { for (int ii = 0; ii < InputLength; ii++) { //Weight gradients WeightGradient[i, ii] = input[ii] * ActivationFunctions.TanhDerriv(Values[i]) * Errors[i]; if (usemomentum) { WeightMomentum[i, ii] = (WeightMomentum[i, ii] * momentum) - (learningrate * WeightGradient[i, ii]); WeightGradient[i, ii] += WeightMomentum[i, ii]; } } if (output) { continue; } //Bias gradients BiasGradient[i] = ActivationFunctions.TanhDerriv(Values[i]) * Errors[i]; if (usemomentum) { BiasMomentum[i] = (BiasMomentum[i] * momentum) - (learningrate * BiasGradient[i]); BiasGradient[i] += BiasMomentum[i]; } } }
public void Backprop(Layer output) { Errors = new double[Length]; for (int k = 0; k < output.Length; k++) { for (int j = 0; j < Length; j++) { Errors[j] += output.Weights[k, j] * ActivationFunctions.TanhDerriv(output.Values[k]) * output.Errors[k]; } } }
public void Calculate(double[] input, bool output) { Values = new double[Length]; for (int k = 0; k < Length; k++) { for (int j = 0; j < InputLength; j++) { Values[k] += ((Weights[k, j] + WeightMomentum[k, j]) * input[j]); } if (!output) { Values[k] += Biases[k] + BiasMomentum[k]; Values[k] = ActivationFunctions.Tanh(Values[k]); } else { Values[k] = Values[k]; } } }
private void Button2_Click(object sender, EventArgs e) { //This button is a toggle (prevents clicking before ready again, as well) if (Training) { Training = false; Buttons[1].Enabled = false; return; } Training = true; //Need to check number of games //Index 0 is file format var thread = new Thread(() => { //TODO: find actual number of games available for (int j = 1; j < 20058; j++) { while (Training) { var moves = IO.ReadGame(j); for (int c = 0; c < moves.Count; c++) { //Whatever the player did is the right move var possibilities = new List <Board>(); //Generate moves from the same board as the players if (c != 0) { possibilities = moves[c - 1].GenMoves(true); } //Generate moves from a fresh board if none exists prior in array else { possibilities = (new Board(new Player(true), new Player(false), new Piece[8, 8], true).initBoard().GenMoves(true)); } //Translate board to numbers var doubleboard = eval(moves[c], c % 2 == 0); //Foreach move the player could have made, evaluate it in relation to their actual move foreach (Board b in possibilities) { //The player's move was the right one if (b.RecentMove[0] == moves[c].RecentMove[0] && b.RecentMove[1] == moves[c].RecentMove[1]) //Calculation and backpropegation of error { ActiveNN.Run(ActivationFunctions.Normalize(doubleboard, 8, 8), 1, false); } //Other moves are not else { ActiveNN.Run(ActivationFunctions.Normalize(doubleboard, 8, 8), 0, false); } } //TODO: add feedback for evaluating player board states (one of the players won after all) } //Batch descent ActiveNN.Run(moves.Count); //Enable button in case it was disabled before continuing (once save is finished) if (j % SaveEveryX == 0) { new Task(() => { IO.Write(ActiveNN, 0); Invoke(new Action(() => { Buttons[1].Enabled = true; })); }).Start(); } } } }); thread.IsBackground = true; thread.Start(); double[,] eval(Board move, bool isw) { var input = new double[8, 8]; for (int i = 0; i < 8; i++) { for (int ii = 0; ii < 8; ii++) { //Set piece values equal to standard chess piece values Piece p = move.Pieces[i, ii]; //Don't have to set empty piece = 0 b/c array initialization does it automatically if (p is Empty) { continue; } if (p is Pawn) { input[i, ii] = 1d; } if (p is Knight || p is Bishop) { input[i, ii] = 3d; } if (p is Rook) { input[i, ii] = 5d; } if (p is Queen) { input[i, ii] = 9d; } if (p is King) { input[i, ii] = 15d; } //Set opposite color piece values to negative if (p.Player.IsW != isw) { input[i, ii] *= -1; } } } return(input); } }