Reputation: 397
Trying to obtain the d value (integer) for which the Std_Diff objective function is minimal, using Scipy minimize.
My code:
def Std_Diff(d):
return std(diff(df['BN'].values,d));
from scipy.optimize import minimize
b=(3,)
res = minimize(Std_Diff,(1,), method='SLSQP', bounds = b)
The **df['BN'].values** are
Out[72]:
array([ 2, 2, 2, 2, 3, 2, 7, 5, 7, 11, 8, 2, 11, 7, 15, 8, 7,
12, 21, 19, 32, 35, 40, 35, 21, 19, 25, 20, 40, 80, 99], dtype=int64)
Error is
IndexError: too many indices for array
In case I do not use bounds
:
res = minimize(Std_Diff,(1,), method='SLSQP')
I get another error:
> in _minimize_slsqp(func, x0, args, jac, bounds, constraints, maxiter,
> ftol, iprint, disp, eps, callback, **unknown_options)
> 368 fx = float(np.asarray(func(x)))
> 369 except:
> --> 370 raise ValueError("Objective function must return a scalar")
> 371 # Compute the constraints
> 372 if cons['eq']: ValueError: Objective function must return a scalar.
Upvotes: 3
Views: 1855
Reputation: 231325
(I was stumbling around at the start, but I'll leave here so you can get some ideas of how to debug.)
You invoke minimize
with:
Std_Diff,(1,)
that is the initial values is a scalar (or 1 number). minimize
takes it's clue from that and sets the search variable to the same. That's the d
it passes to your function, Std_Diff
. But it also expects that function to return a single value as well. In other words, minimize a scalar function of a scalar value.
So std(diff(df['BN'].values,1))
should return a scalar. Evidently it does not.
OK, testing with the supposed values
In [115]: bf
Out[115]:
array([ 2, 2, 2, 2, 3, 2, 7, 5, 7, 11, 8, 2, 11, 7, 15, 8, 7,
12, 21, 19, 32, 35, 40, 35, 21, 19, 25, 20, 40, 80, 99], dtype=int64)
In [116]: np.std(np.diff(bf,1))
Out[116]: 9.9219733700285424
So my first guess is wrong.
Looking more carefully at the error stack, I see that the error occurs in your function, not after. It looks like a problem with the use of d
.
/usr/local/lib/python3.5/dist-packages/numpy/lib/function_base.py in diff(a, n, axis)
1913 raise ValueError(
-> 1914 "order must be non-negative but got " + repr(n))
1915 a = asanyarray(a)
ValueError: order must be non-negative but got array([-64259548.28233695])
In the unbounded case, the search variable can go negative (very much so), raising an error in np.diff
.
(the error you show is from During handling of the above exception, another exception occurred:
. It's not the primary error, but a secondary one.)
The problem when specifying bounds, is that specification is incomplete. It requires a (min,max) tuple for each variable. So this works:
In [147]: minimize(Std_Diff,1, method='SLSQP', bounds=((3,None),))
...
Out[147]:
fun: 9.921973370028542
jac: array([ 64259549.28233695])
message: 'Positive directional derivative for linesearch'
nfev: 3
nit: 5
njev: 1
status: 8
success: False
x: array([ 1.])
Bounds for variables (only for L-BFGS-B, TNC and SLSQP).
(min, max)
pairs for each element inx
, defining the bounds on that parameter. Use None for one ofmin
ormax
when there is no bound in that direction.
Look at the error line:
--> 341 bnderr = bnds[:, 0] > bnds[:, 1]
it expects bnds
to be a 2d array with 2 columns. For example:
In [153]: np.array(((3,10),))
Out[153]: array([[ 3, 10]])
In [154]: np.array((3,))
Out[154]: array([3])
I also modified the function to have a clearer idea of how its values changed
def Std_Diff(d):
print(d)
r = np.std(np.diff(bf,d))
print(r)
return r
Upvotes: 2