Scipy minimize fail to iterate
See original GitHub issueHi, I am litteraly going crazy with Scipy.minimize.
I am simply trying to fit a certain list to a set of parameters representing a bezier curve.
My input is the “curveToFitArray”. I have an initial guess “x0” that I cut in half to have bezier points coordinates in “Y” and “Z”. I want to find the parameters that minimize the error between the curve generated by my bezier parametrization and the real curve this way:
#!/home/charles/miniconda3/envs/default/bin/python
from scipy.optimize import minimize
from scipy.interpolate import interp1d
import numpy as np
from scipy.special import comb
def bernstein_poly(i, n, t):
return comb(n, i) * ( t**(n-i) ) * (1 - t)**i
def bezier_curve(points, nTimes=50):
nPoints = len(points)
xPoints = np.array([p[0] for p in points])
yPoints = np.array([p[1] for p in points])
t = 0.5 * (1 - np.cos(np.linspace(0,np.pi,nTimes)))
polynomial_array = np.array([bernstein_poly(i, nPoints-1, t) for i in range(0, nPoints)])
xvals = np.dot(xPoints, polynomial_array)
yvals = np.dot(yPoints, polynomial_array)
return [list(c) for c in zip(xvals,yvals)]
def bspline(p,scale=[1.0,1.0],U='Y',V='X',nPoints=50):
point_list = [[u*scale[0],v*scale[1]] for u,v in zip(p[U],p[V])]
BSpline = bezier_curve(point_list,nPoints)
#pts_BSpline = np.array(BSpline).T
return sorted(BSpline, key=lambda x: x[0])
def Distance(curve):
distance = np.cumsum(np.sqrt(np.sum(np.diff(curve, axis=0)**2, axis=1)))
distance = np.insert(distance, 0, 0)/distance[-1]
return distance
def divide(curve, n):
distance = Distance(curve)
alpha = np.linspace(0, 1, n)
interpolation = interp1d(distance, curve, kind='linear', axis=0)
interp_sort = sorted([[s, *c] for s, c in zip(alpha, interpolation(alpha))], key=lambda x: x[0])
return [c[1:] for c in interp_sort]
def parseParameters(x):
d = {}
d["Y"] = list(x[0:4])
d["Z"] = list(x[4:])
return d
def objective(x,curveToFit):
parameters = parseParameters(x)
curveEval = divide(bspline(p = parameters,U='Y',V='Z',nPoints=len(curveToFit)),len(curveToFit))
curveEval = np.array(curveEval)
curveToFit = np.array(curveToFit)
print("curveToFit",curveToFit)
print("curveEval",curveEval)
error = np.sqrt((np.subtract(curveEval, curveToFit)** 2))
print("error",error)
error = np.sum(error)
return error
curveToFit = [[0.0, 0.0], [0.08462454350227121, -0.0006072162233802024], [0.16920310091996732, -0.0034025456809973417], [0.2533683125896774, -0.012003143737867554], [0.337444, -0.021644]]
x0 = [0.0, 0.050616600000000005, 0.253083, 0.337444, 0.0, 0.0, -0.021644, -0.021644]
bounds = [[0.0, 0.0], [-0.015, 0.35244400000000004], [-0.015, 0.35244400000000004], [0.337444, 0.337444],[0.0, 0.0], [-0.036643999999999996, 0.015], [-0.036643999999999996, 0.015], [-0.021644, -0.021644]]
result = minimize(
fun = objective,
x0 = x0,
bounds = bounds,
method='L-BFGS-B', # L-BFGS-B, SLSQP
args=(curveToFit),
options={'disp':True}
)
print(result)
I had it working nicely a few months ago. Then did problably some modifications on my code without checking the fitting was still working. Now I cant remember what I changed to make it stop working…
The algorithm just doesnt iterate and return a result very close to x0 everytime
Thanks a lot
Issue Analytics
- State:
- Created 3 years ago
- Comments:12 (7 by maintainers)
Top Results From Across the Web
SciPy's minimize is not iterating at all - Stack Overflow
Your code had just some confusing variables so I just cleared that out and simplified some lines, now the minimization works correctly.
Read more >scipy.optimize.minimize — SciPy v1.9.3 Manual
Maximum number of iterations to perform. Depending on the method each iteration may use several function evaluations. dispbool. Set to True to print...
Read more >scipy.optimize.show_options — SciPy v0.13.0 Reference Guide
The calculation will terminate if the relative error between two consecutive iterates is at most xtol. maxfev : int. The maximum number of...
Read more >minimize(method='trust-constr') — SciPy v1.9.3 Manual
Tolerance for the barrier subproblem at the last iteration. Only for problems with inequality constraints. barrier_parameterfloat. Barrier parameter at the last ...
Read more >scipy.optimize.least_squares — SciPy v1.9.3 Manual
scipy.optimize.least_squares# · 'exact' is suitable for not very large problems with dense Jacobian matrices. The computational complexity per iteration is ...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found

I believe this issue should be fixed with #13096, with the fix being available in scipy 1.8.
If I understand correctly the issue arises because of problems estimating the gradient when a lower bound was equal to an upper bound. Changes made to strictly obey bounds during finite difference differentiation caused approx_derivative to start returning grads containing NaN. L-BFGS-B (and a couple of others) didn’t like that. The fix in #13096 factorises parameters with equal bounds out.
i am getting this same issue with L-BFGS-B not progressing (NaN gradient) if any bounds have equal upper/lower, however I am quite sure the same approach was working in previous scipy versions with L-BFGS-B. The docs generally suggests using bounds exactly this way to keep parameters fixed, so it would be great if it could be fixed again. thanks 😃