使用Scipy最小化最小化功能

时间:2017-08-21 20:57:57

标签: python scipy

尝试使用Scipy最小化获得Std_Diff目标函数最小的d值(整数)。

我的代码:

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)

错误是

  

IndexError:数组索引太多

如果我不使用bounds

res = minimize(Std_Diff,(1,), method='SLSQP')

我收到另一个错误:

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

1 个答案:

答案 0 :(得分:2)

(我一开始就磕磕绊绊,但我会离开这里,这样你就可以了解如何调试。)

您使用以下命令调用minimize

Std_Diff,(1,)

即初始值是标量(或1个数字)。 minimize从中获取线索并将搜索变量设置为相同。这是d传递给您的函数Std_Diff。但它也期望该函数也返回单个值。换句话说,最小化标量值的标量函数。

所以std(diff(df['BN'].values,1))应该返回一个标量。显然它没有。

好的,用假设的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

所以我的第一个猜测是错误的。

仔细查看错误堆栈,我发现错误发生在您的函数中,而不是之后。使用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])

在无界的情况下,搜索变量可能会变为负数(非常如此),在np.diff中引发错误。

(您显示的错误来自During handling of the above exception, another exception occurred:。这不是主要错误,而是辅助错误。)

指定边界时的问题是规范不完整。它需要每个变量的(最小,最大)元组。所以这有效:

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.])
  

变量的界限(仅适用于L-BFGS-B,TNC和SLSQP)。       (min, max)中每个元素的x对,定义       该参数的界限。对min或其中一个使用无       max当那个方向没有界限时。{/ p>

查看错误行:

--> 341         bnderr = bnds[:, 0] > bnds[:, 1]

它希望bnds是一个包含2列的二维数组。例如:

In [153]: np.array(((3,10),))
Out[153]: array([[ 3, 10]])
In [154]: np.array((3,))
Out[154]: array([3])

我还修改了函数,以便更清楚地了解其值如何变化

def Std_Diff(d):
    print(d)
    r = np.std(np.diff(bf,d))
    print(r)
    return r