Hello.
Le jeu. 20 janv. 2022 à 15:06, qiqi tang <[email protected]> a écrit :
>
> Dear Sir/Madam,
> I recently used the CurveFitter tool inside the commons package and
> I found a problem that I couldn't constrain the relevant parameters.
A possible approach is to transform the relevant parameters so
that whatever value is tried by the optimizer, it always maps to a
value within the allowed range (see below).
> The specific relevant codes are as follows:
import org.apache.commons.math4.legacy.analysis.function.Logit;
import org.apache.commons.math4.legacy.analysis.function.Sigmoid;
> public class MyFuncFitter extends AbstractCurveFitter {
private Sigmoid constrainedM;
private Logit unconstrainedK;
private Sigmoid constrainedK;
private Logit unconstrainedK
public MyFuncFitter(minM, maxM, minK, maxK) {
constrainedM = new Sigmoid(minM, maxM);
unconstrainedM = new Logit(minM, maxM);
constrainedK = new Sigmoid(minK, maxK);
unconstrainedK = new Logit(minK, maxK);
}
> @Override
> protected LeastSquaresProblem
> getProblem(Collection<WeightedObservedPoint> points) {
> final int len = points.size();
> final double[] target = new double[len];
> final double[] weights = new double[len];
> final double[] initialGuess = {
unconstrainedM.value(50),
unconstrainedK.value(1.0),
1.0
};
>
> int i = 0;
> for (WeightedObservedPoint point : points) {
> target[i] = point.getY();
> weights[i] = point.getWeight();
> i += 1;
> }
>
> final AbstractCurveFitter.TheoreticalValuesFunction model =
> new AbstractCurveFitter.TheoreticalValuesFunction(new MyFunc(),
> points);
>
> return new LeastSquaresBuilder().
> maxEvaluations(Integer.MAX_VALUE).
> maxIterations(Integer.MAX_VALUE).
> start(initialGuess).
> target(target).
> weight(new DiagonalMatrix(weights)).
> model(model.getModelFunction(),
> model.getModelFunctionJacobian()).build();
> }}
>
> public class MyFunc implements ParametricUnivariateFunction {
> @Override
> public double value(double x, double... parameters) {
final double m = constrainedM.value(parameters[0]);
final double k = constrainedK.value(parameters[1]);
final double b = parameters[2];
> return m * k * b * Math.exp(-k * x) * Math.pow(1 - Math.exp(-k
> * x), b - 1);
> }
>
> @Override
> public double[] gradient(double x, double... parameters) {
final double m = constrainedM.value(parameters[0]);
final double k = constrainedK.value(parameters[1]);
final double b = parameters[2];
> return new double[]{
> b * k * Math.exp(-k * x) * Math.pow(1 - Math.exp(-k *
> x), b - 1),
> (b - 1) * b * k * m * x * Math.exp(-2 * k * x) *
> Math.pow(1 - Math.exp(-k * x), b - 2) + b * m * Math.exp(-k * x) *
> Math.pow(1 - Math.exp(-k * x), b - 1) - b * k * m * x * Math.exp(-k *
> x) * Math.pow(1 - Math.exp(-k * x), b - 1),
> k * m * Math.exp(-k * x) * Math.pow(1 - Math.exp(-k *
> x), b - 1) + b * k * m * Math.exp(-k * x) * Math.pow(1 - Math.exp(-k *
> x), b - 1) * Math.log(1 - Math.exp(-k * x))
> };
@Override
public double[] fit(Collection<WeightedObservedPoint> points) {
final double[] p = super.fit(points);
return new double[] {
constrainedM.value(p[0]),
constrainedK.value(p[1]),
p[2]
};
}
> }
>
> public static void main(String[] args) {
> MyFuncFitter fitter = new MyFuncFitter();
> ArrayList<WeightedObservedPoint> points = new ArrayList<>();
> points.add(new WeightedObservedPoint(1.0, 0.25, 3.801713179));
> points.add(new WeightedObservedPoint(1.0, 4, 10.46561902));
> final double coeffs[] = fitter.fit(points);
> System.out.println(Arrays.toString(coeffs));
> }}
>
> Then, What should I do to limit the parameters 'm' to 1 to 100 and 'k'
> to 100 to 10,000,It would be nice if the code dome was available.
I don't understand what "code dome" means.
> Please help me thank you very much!
Let us know how the above suggestion (untested code) went.
Best regards,
Gilles
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]