public double Minimize(double[][] inputs, double[] outputs)
{
Array.Clear(hessian, 0, hessian.Length);
Array.Clear(gradient, 0, gradient.Length);
errors = new double[inputs.Length];
jacobian = new double[inputs.Length, numberOfParameters];
for (int i = 0; i < inputs.Length; i++)
errors[i] = outputs[i] - Function(weights, inputs[i]);
var g = new double[numberOfParameters];
for (int i = 0; i < inputs.Length; i++)
{
Gradient(weights, inputs[i], result: g);
for (int j = 0; j < gradient.Length; j++)
jacobian[i, j] = -g[j];
if (Token.IsCancellationRequested)
break;
}
// Compute error gradient using Jacobian
jacobian.TransposeAndDot(errors, result: gradient);
// Compute Quasi-Hessian Matrix approximation
jacobian.TransposeAndDot(jacobian, result: hessian);
decomposition = new SingularValueDecomposition(hessian,
computeLeftSingularVectors: true, computeRightSingularVectors: true, autoTranspose: true);
deltas = decomposition.Solve(gradient);
for (int i = 0; i < deltas.Length; i++)
weights[i] -= deltas[i];
return Value = ComputeError(inputs, outputs);
}