public double Run(double[] input, double[] output)
{
// Zero gradient
ResetGradient();
// Compute forward pass
network.Compute(input);
// Copy network outputs to local thread
var networkOutputs = this.networkOutputs.Value;
for (int j = 0; j < networkOutputs.Length; j++)
networkOutputs[j] = network.Layers[j].Output;
// Calculate network error
double error = CalculateError(output);
// Calculate weights updates
CalculateGradient(input);
// Update the network
UpdateNetwork();
return error;
}