Dan
Dan

Reputation: 45

Why am I getting an error when I run BFGS optimization in scipy?

I am still learning the optimize function in scipy so as a test I wanted to optimize

def f(x):
    return (x-2)**2+2

This should give a minimum of (2, 2). Then I set x0 = np.array([1.3, 0.7, 0.8, 1.9, 1.2]). When I ran res = minimize(f, x0, method='BFGS', options={'disp': True}), I got the following error

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/scipy/optimize/optimize.py in _minimize_bfgs(fun, x0, args, jac, callback, gtol, norm, eps, maxiter, disp, return_all, finite_diff_rel_step, **unknown_options)
   1211         try:
-> 1212             old_fval = old_fval.item()
   1213         except (ValueError, AttributeError) as e:

ValueError: can only convert an array of size 1 to a Python scalar

The above exception was the direct cause of the following exception:

ValueError                                Traceback (most recent call last)
<ipython-input-16-a687d5eaf37f> in <module>
----> 1 res = minimize(f, x0, method='BFGS', options={'disp': True})

/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/scipy/optimize/_minimize.py in minimize(fun, x0, args, method, jac, hess, hessp, bounds, constraints, tol, callback, options)
    616         return _minimize_cg(fun, x0, args, jac, callback, **options)
    617     elif meth == 'bfgs':
--> 618         return _minimize_bfgs(fun, x0, args, jac, callback, **options)
    619     elif meth == 'newton-cg':
    620         return _minimize_newtoncg(fun, x0, args, jac, hess, hessp, callback,

/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/scipy/optimize/optimize.py in _minimize_bfgs(fun, x0, args, jac, callback, gtol, norm, eps, maxiter, disp, return_all, finite_diff_rel_step, **unknown_options)
   1212             old_fval = old_fval.item()
   1213         except (ValueError, AttributeError) as e:
-> 1214             raise ValueError("The user-provided "
   1215                              "objective function must "
   1216                              "return a scalar value.") from e

ValueError: The user-provided objective function must return a scalar value.

Could someone help me understand what is happening?

Upvotes: 1

Views: 929

Answers (1)

CypherX
CypherX

Reputation: 7353

You were copying the x0 used for scipy.optimize.rosen: Rosenbrock objective function in the example of scipy.optimize.minimize. The Rosenbrock function applies a sum() on the various x0 values you provide and hence evaluates to a scalar.

Note that BFGS is essentially going to use the function and it's derivatives at a point (x). The x0 is only the starting point (a trial solution), where the algorithm starts to look for the solution from. If your objective function provides you with only a scalar, you cannot pass multiple x0 values to it.

# This should work for you
from scipy.optimize import minimize

x0 = 1.3 # an initial value for f(x)
res = minimize(f, x0, method='BFGS', options={'disp': True})

When can/should you pass multiple x0 values?

Say, your objective function has the following form. This will require you to provide an array of 5 initial values to x0.

def f(x):
    return 10.0 * (x[0]**3 - 0.5 * x[1]**2 + 7.0 * x[2]**(-1.5)) - 6.0 * (x[3] - 2*x[4])**2

References

Upvotes: 1

Related Questions