public static void Train(NeuralNetwork net, TrainingConfiguration config, TrainingSet trainingSet, Action <double> reportProgress) { Enumerable.Range(0, config.MaxEpoch) .ForEach(epochNo => { PerformTrainingEpoch(net, config, trainingSet); var currentTotalError = ErrorFunctions.TotalError(net, trainingSet); reportProgress(currentTotalError); }); }
private static void PerformTrainingEpoch(NeuralNetwork net, TrainingConfiguration config, TrainingSet trainingSet) { trainingSet.ForEach(sample => { var netOutput = net.ForwardPass(sample.Input); var outputDeltas = netOutput.Zip(sample.Ideal, (actual, ideal) => OutputDelta(ideal, actual)).ToList(); var outputWeightsAdjustments = outputDeltas .Select(d => net.HiddenLayer.Select(h => h.LastOutput).Select(h => OutputWeightDelta(d, h))); var outputDeltaPairs = net.OutputLayer.Zip(outputDeltas, (output, oDelta) => new { output, oDelta }); var outputWeightedDeltaSums = net.HiddenLayer .Select((_, idx) => outputDeltaPairs .Select(outputDeltaPair => outputDeltaPair.output.Weights[idx] * outputDeltaPair.oDelta) .Sum()); var hiddenDeltaPairs = net.HiddenLayer.Select(h => h.LastOutput) .Zip(outputWeightedDeltaSums, (h, delta) => new { HiddenOutput = h, Delta = delta }); var hiddenWeightsAdjustments = hiddenDeltaPairs.Select(hd => sample.Input.Select(i => HiddenWeightDelta(hd.Delta, hd.HiddenOutput, i))); UpdateWeights(outputWeightsAdjustments, hiddenWeightsAdjustments, net, config); }); }
private static void UpdateWeights(IEnumerable <IEnumerable <double> > outputWeightsAdjustments, IEnumerable <IEnumerable <double> > hiddenWeightsAdjustments, NeuralNetwork net, TrainingConfiguration config) { net.OutputLayer.Zip(outputWeightsAdjustments, (o, deltas) => new { o, deltas }) .ForEach(od => od.o.Weights = CalculateNewWeights(od.o.Weights, od.deltas, config.LearningRate)); net.HiddenLayer.Zip(hiddenWeightsAdjustments, (h, deltas) => new { h, deltas }) .ForEach(od => od.h.Weights = CalculateNewWeights(od.h.Weights, od.deltas, config.LearningRate)); }