Not long ago, a client wanted to fit a set of data points to a Weibull curve of the form:

The earlier example Find an exponential least squares fit for a set of points in C# explains how to find a least squares fit for exponential data. This example uses a similar technique with the following differences:

- This example uses a different function F, error function E, and partial derivatives
- This example’s functions have 4 parameters a, b, c, and d instead of just 3
- The ranges for test values of a, b, c, and d are different so they fit the data better

The following code shows the function.

// Return the function for x, a, b, and c. public static double F(double x, double a, double b, double c, double d) { return a - b * Math.Exp(-c * Math.Pow(x, d)); }

The following method calculates the error squared for a set of points and the coefficients a, b, c, and d.

// Return the sum of errors squared for // the given points and parameters. public static double ErrorSquared(List<PointF> pts, double a, double b, double c, double d) { double total_error = 0; for (int i = 0; i < pts.Count; i++) { double new_error = pts[i].Y - F(pts[i].X, a, b, c, d); if (total_error > 1E+15) break; total_error += new_error * new_error; } return total_error; }

This method calculates the function’s values at each point’s X coordinate, subtracts that from the data point’s X value, and squares the differences. It adds up the results for all of the points.

Like the previous example, this program uses the error function’s gradient to follow the surface (in this case a 4D surface) towards a minimum. To do that it uses the error function’s partial derivatives. For example, the following method calculates the function’s partial derivative with respect to a.

// dE/da private static double dEda(List<PointF> pts, double a, double b, double c, double d) { double total = 0; for (int i = 0; i < pts.Count; i++) { total += 2 * (F(pts[i].X, a, b, c, d) - pts[i].Y) * dFda(pts[i].X, a, b, c, d); } return total; }

The program uses the partial derivatives to find the error function’s gradient and then follows the opposite of the gradient to a minimum. See the earlier example for more details about how this technique works. For more information on classical Weibull functions, see: