tBuLi / symfit

Symbolic Fitting; fitting as it should be.
http://symfit.readthedocs.org
MIT License
232 stars 17 forks source link

Conflicting fitting results with minimizer TrustConstr and COBYLA #324

Closed antonykamp closed 3 years ago

antonykamp commented 3 years ago

Even when the minimizer TrustConstr is advertised in scipy as the most flexible and powerful method available, symfit returns different results for fitting without constraints. For example, as a result of the following code, we get a=2.4131... and b=2.1003....

from symfit.core.support import parameters, variables
from symfit.core.models import Model
from symfit.core.minimizers import TrustConstr
from symfit.core.fit import Fit

import numpy as np

x, y = variables('x, y')
a, b = parameters('a, b')
x_data = np.linspace(1, 10, 10)
y_data = 3 * np.linspace(1, 10, 10) ** 2
model = Model({y: a * x ** b})

fit = Fit(x=x_data, y=y_data, minimizer=TrustConstr, model=model)
fit_result = fit.execute()
print(fit_result.value(a)) # 2.4131388...
print(fit_result.value(b)) # 2.1003748...

The same problem exists with COBYLA. Why is that?

pckroon commented 3 years ago

I've 3D plotted the objective function vs A and B, and there's a diagonal crossing the global minimum that's rather flat. The diagonal runs, approximately, from (2, 2.2) to (4, 1.86). For comparison, some residual values:

a b R
3 2 0
2.4131 2.1004 87.1
2 2.2 493
4 1.86 217
1 1 210232
Minimizing this function by calling scipy manually (and without supplying derivatives): minimizer result
L-BFGS-B global minimum
COBYLA Max function evaluations (1000) reached
COBYLA with maxiter=10000 f=32, a=2.63, b=2.06
COBYLA with maxiter=10000, tol=1e-8 global minimum
trust-constr global minimum (!)
trust-constr with jac='cs' global minimum (!)
trust-constr with jac='cs', hess=BFGS(exception_strategy='skip_update') global minimum (!)
trust-constr with jac=analytical jac, hess='cs' global minimum (!)

So we should carefully check the trust-constr wrapping.