/// <summary> /// Checks if new given network is better than current best. If it is, stores it as best. /// </summary> /// <param name="newNetwork"></param> /// <returns>True if best network was changed. Otherwise, false</returns> private bool UpdateBestNetwork(NeuralNetwork newNetwork) { var tester = new NetworkTester(ErrorCalculator); if (BestNetwork is null) //save new network as best { BestNetwork = newNetwork; BestTestError = tester.TestNetwork(BestNetwork, DataProvider); return(true); } else // test new network and compare { var newNetworkError = tester.TestNetwork(newNetwork, DataProvider); if (newNetworkError < BestTestError) { BestNetwork = newNetwork; BestTestError = newNetworkError; return(true); } else { return(false); } } }
public void TrainNetwork(ref NeuralNetwork networkToTrain, int maxEpochs, double desiredErrorRate = 0) { var learnSet = DataProvider.LearnSet; //shorter var TempTestErrorHistory = Vector <double> .Build.Dense(maxEpochs + 1); Vector <double> TemporaryEpochErrorHistory = Vector <double> .Build.Dense(maxEpochs, 0); //place to temporary store epoch errors for all epochs TempTestErrorHistory[0] = Double.MaxValue; // assume error at beginning is maximal TemporaryEpochErrorHistory[0] = Double.MaxValue; // assume error at beginning is maximal int shuffleAmount = (int)Math.Round(Math.Log(learnSet.Length, 2)); // calculate how much should shuffle learn set depending on its size Vector <double> output; Vector <double> errorVector; int EpochIndex = 1; // epochs are counted starting from 1 while (EpochIndex < maxEpochs) { DataProvider.ShuffleDataSet(learnSet, shuffleAmount); // shuffle some data in learn set CurrentEpochErrorVector = Vector <double> .Build.Dense(learnSet.Length, 0); // init with 0s #region calculate epoch for (int dataIndex = 0; dataIndex < learnSet.Length; dataIndex++) { output = networkToTrain.CalculateOutput(learnSet[dataIndex].X, CalculateMode.OutputsAndDerivatives); errorVector = ErrorCalculator.CalculateErrorVector(output, learnSet[dataIndex].D); CurrentEpochErrorVector[dataIndex] = ErrorCalculator.CalculateErrorSum(output, learnSet[dataIndex].D); #region adapt weights LearningAlgorithm.AdaptWeights(networkToTrain, errorVector, CurrentEpochErrorVector[dataIndex], CurrentEpochErrorVector[dataIndex.Previous()]); #endregion } #endregion #region epoch error TemporaryEpochErrorHistory[EpochIndex] = ErrorCalculator.CalculateEpochError(CurrentEpochErrorVector); if (TemporaryEpochErrorHistory[EpochIndex] <= desiredErrorRate) //learning is done { return; } #endregion #region Adapt Learning Rate LearningAlgorithm.AdaptLearningRate(TemporaryEpochErrorHistory[EpochIndex], TemporaryEpochErrorHistory[EpochIndex.Previous()]); #endregion #region create and store test results var testError = tester.TestNetwork(networkToTrain, DataProvider); TempTestErrorHistory[EpochIndex] = testError; #endregion #region update best network state if (TempTestErrorHistory[EpochIndex] < BestError) { BestNetworkState = networkToTrain.DeepCopy(); BestError = TempTestErrorHistory[EpochIndex]; } #endregion EpochIndex++; } #region save errors for all epochs that actually were calculated TestErrorHistory = Vector <double> .Build.Dense(EpochIndex); EpochErrorHistory = Vector <double> .Build.Dense(EpochIndex); TemporaryEpochErrorHistory.CopySubVectorTo(EpochErrorHistory, 0, 0, EpochIndex); TempTestErrorHistory.CopySubVectorTo(TestErrorHistory, 0, 0, EpochIndex); #endregion //restore best network state ( on set for verifying) networkToTrain = BestNetworkState; }