Gilles,

Thanks so much for your patiently response! I know I can write a gradient
method for a specific function, but my purpose is to make the gradient
method suitable for any function of yi = f(xi, p1, p2, p3, ...). That means
the users don't need to override a new fixed gradient method for a new
function, just like the SciPy's curve_fit (
https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.curve_fit.html).
So I tried to calculate gradient array through numerical differentiation (
https://github.com/meteoinfo/MeteoInfo/blob/master/meteoinfo-math/src/main/java/org/meteoinfo/math/optimize/MyParametricUnivariateFunction.java#L33-L56,
the code also is attache below), and please let me know whether the code is
correct for my purpose? Thanks!

@Override
public double[] gradient(double v, double... parameters) {
    function.setParameters(parameters);

    // create a differentiator
    FiniteDifferencesDifferentiator differentiator =
            new FiniteDifferencesDifferentiator(nbPoints, stepSize);

    // create a new function that computes both the value and the derivatives
    // using DerivativeStructure
    UnivariateDifferentiableFunction diffFunc =
differentiator.differentiate(function);

    double y = function.value(v);
    int n = parameters.length;
    double[] gradients = new double[n];
    for (int i = 0; i < n; i++) {
        DerivativeStructure xDS = new DerivativeStructure(n, 1, i,
parameters[i]);
        DerivativeStructure yDS = diffFunc.value(xDS);
        int[] idx = new int[n];
        idx[i] = 1;
        gradients[i] = yDS.getPartialDerivative(idx);
    }

    return gradients;
}


By the way, I am using Apache commons math 3.6.1 at present. Today I also
tried the 4.0-SNAPSHOT version but the result is the same.

Regards
Yaqiang

On Mon, Aug 1, 2022 at 8:33 PM Gilles Sadowski <gillese...@gmail.com> wrote:

> Hi.
>
> Le dim. 31 juil. 2022 à 18:05, Yaqiang Wang <yaqiang.w...@gmail.com> a
> écrit :
> >
> > Currently I just want to fit univariate function such as the following
> Python function:
> >
> > def func(x, a, b, c):
> >     return a * exp(-b * x) + c
> >
> >
> > I also tried using SimpleCurveFitter to do it.
> MyParametricUnivariateFunction implements ParametricUnivariateFunction and
> overrides value and gradient methods (
> https://github.com/meteoinfo/MeteoInfo/blob/master/meteoinfo-math/src/main/java/org/meteoinfo/math/optimize/MyParametricUnivariateFunction.java),
> and the gradient array is calculated through numerical differentiation.
>
> Given a list of points, { xi } (i = 0, 1, ... , N), and their associated
> values,
> { y_i }, "SimpleCurveFitter" aims at finding the best fit of an assumed
> function "f"
>   yi = f(xi, p1, p2, p3, ...)
> whose parameters p1, p2, p3, ... can be adjusted.
> Internally, "SimpleCurveFitter" computes the Jacobian matrix
>   df(x0)/dp1 df(x0)/dp2 df(x0)/dp3 ...
>   df(x1)/dp1 df(x1)/dp2 df(x1)/dp3 ...
>      ....
>   df(xN)/dp1 df(xN)/dp2 df(xN)/dp3 ...
> needed by the "Levenberg-Marquardt" least-squares optimizer.
> The gradient of "f" is an array where each slot contains the partial
> derivative of the univariate function (at the given "x") wrt to each
> _parameter_.
> For your function above, the code would be (untested):
> ---CUT---
> public class MyFunction implements ParametricUnivariateFunction {
>
>     public double value(double x, double ... parameters) {
>         final double a = parameters[0];
>         final double b = parameters[1];
>         final double c = parameters[2];
>         return a * Math.exp(-b * x) + c
>     }
>
>     public double[] gradient(double x, double ... parameters) {
>         final double a = parameters[0];
>         final double b = parameters[1];
>         final double c = parameters[2];
>         final double[] grad = new double[3];
>         grad[0] = Math.exp(-b * x);
>         grad[1] = -a * x * grad[0];
>         grad[2] = 1;
>         return grad;
>     }
> }
> ---CUT---
>
> HTH,
> Gilles
>
> > [...]
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscr...@commons.apache.org
> For additional commands, e-mail: user-h...@commons.apache.org
>
>

-- 
*************************************************
Dr. Yaqiang Wang
Chinese Academy of Meteorological Sciences (CAMS)
46, Zhong-Guan-Cun South Avenue
Beijing, 100081
China

yaqiang.w...@gmail.com

www.meteothink.org
**************************************************

Reply via email to