private void CalculateUpdates(double[] input)
{
// 1 - calculate updates for the first layer
Layer layer = network.Layers[0];
double[] errors = neuronErrors[0];
double[][] layerWeightsUpdates = weightsUpdates[0];
double[] layerThresholdUpdates = thresholdsUpdates[0];
// cache for frequently used values
double cachedMomentum = learningRate * momentum;
double cached1mMomentum = learningRate * (1 - momentum);
double cachedError;
// for each neuron of the layer
for (int i = 0; i < layer.Neurons.Length; i++)
{
cachedError = errors[i] * cached1mMomentum;
double[] neuronWeightUpdates = layerWeightsUpdates[i];
// for each weight of the neuron
for (int j = 0; j < neuronWeightUpdates.Length; j++)
{
// calculate weight update
neuronWeightUpdates[j] = cachedMomentum * neuronWeightUpdates[j] + cachedError * input[j];
}
// calculate threshold update
layerThresholdUpdates[i] = cachedMomentum * layerThresholdUpdates[i] + cachedError;
}
// 2 - for all other layers
for (int k = 1; k < network.Layers.Length; k++)
{
Layer layerPrev = network.Layers[k - 1];
layer = network.Layers[k];
errors = neuronErrors[k];
layerWeightsUpdates = weightsUpdates[k];
layerThresholdUpdates = thresholdsUpdates[k];
// for each neuron of the layer
for (int i = 0; i < layer.Neurons.Length; i++)
{
cachedError = errors[i] * cached1mMomentum;
double[] neuronWeightUpdates = layerWeightsUpdates[i];
// for each synapse of the neuron
for (int j = 0; j < neuronWeightUpdates.Length; j++)
{
// calculate weight update
neuronWeightUpdates[j] = cachedMomentum * neuronWeightUpdates[j] + cachedError * layerPrev.Neurons[j].Output;
}
// calculate threshold update
layerThresholdUpdates[i] = cachedMomentum * layerThresholdUpdates[i] + cachedError;
}
}
}