question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Scipy minimize fail to iterate

See original GitHub issue

Hi, 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:closed
  • Created 3 years ago
  • Comments:12 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
andyfaffcommented, Nov 12, 2021

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.

1reaction
marcoaqilcommented, Jul 29, 2021

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 😃

Read more comments on GitHub >

github_iconTop 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 >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found