scipy.optimize.minimize雅可比函数导致'值错误:具有多个元素的数组的真值是模糊的'

时间:2016-07-14 16:56:24

标签: python machine-learning scipy

我使用的是BFGS方法,给出了我的平方指数/ RBF内核的负对数似然,以及它的梯度(雅可比)。离开渐变,它使用第一个差异工作正常 - 但

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
一旦我尝试使用NLL的渐变,就会出现

错误。另请注意,虽然我在下面的SE_der函数(渐变/雅可比)中的源代码在结果中不使用.any()或.all(),但我也尝试了这两个,只是为了得到完全相同的错误。

前面的描述是:

Traceback (most recent call last):
File "loaddata.py", line 107, in <module>
gp.fit(X, y)
File "/home/justinting/programming/bhm/ML/gp.py", line 33, in fit
res = minimize(self.SE_NLL, gp_hp_guess, method='bfgs', jac=True)
File "/usr/lib/python3.5/site-packages/scipy/optimize/_minimize.py", line 441, in minimize
return _minimize_bfgs(fun, x0, args, jac, callback, **options)
File "/usr/lib/python3.5/site-packages/scipy/optimize/optimize.py", line 865, in _minimize_bfgs
old_fval, old_old_fval)
File "/usr/lib/python3.5/site-packages/scipy/optimize/optimize.py", line 706, in _line_search_wolfe12
old_fval, old_old_fval)
File "/usr/lib/python3.5/site-packages/scipy/optimize/linesearch.py", line 282, in line_search_wolfe2
phi, derphi, old_fval, old_old_fval, derphi0, c1, c2, amax)
File "/usr/lib/python3.5/site-packages/scipy/optimize/linesearch.py", line 379, in scalar_search_wolfe2
if (phi_a1 > phi0 + c1 * alpha1 * derphi0) or \

相关代码如下:

gp_hp_guess = [1.0] * 3 # initial guess
res = minimize(self.SE_NLL, gp_hp_guess, method='bfgs', jac=self.SE_der)

# other stuff

def SE_der(self, args):

    [f_err, l_scale, n_err] = args
    L = self.L_create(f_err, l_scale, n_err)
    alpha = linalg.solve(L.T, (linalg.solve(L, self.y))) # save for use with derivative func
    aaT = alpha.dot(alpha.T)
    K_inv = np.linalg.inv(L.T).dot(np.linalg.inv(L))
    # self.K_inv = np.linalg.inv(self.L.T).dot(np.linalg.inv(self.L))
    dK_dtheta = np.gradient(self.K_se(self.X, self.X, f_err, l_scale))[0]
    der = 0.5 * np.matrix.trace((aaT - K_inv).dot(dK_dtheta))
    return -der

def SE_NLL(self, args):

    [f_err, l_scale, n_err] = args
    L = self.L_create(f_err, l_scale, n_err)

    alpha = linalg.solve(L.T, (linalg.solve(L, self.y))) # save for use with derivative func
    nll = (
        0.5 * self.y.T.dot(alpha) + 
        np.matrix.trace(L) + # sum of diagonal
        L.shape[0]/2 * math.log(2*math.pi)
            )
    return nll

我遗漏了辅助函数的源代码,因为NLL在不使用渐变函数时工作正常,并且它们共享相同的辅助函数。

当事后调用SE_der函数直接传入优化参数(而不是实际使用优化中的渐变)时,它会按预期输出一个数字(或者至少我认为这是预期的),所以我我没有发现问题。

这个错误是我对scipy在雅可比功能中所期望的东西或其他东西的误解吗?我尝试挖掘Python源代码,但是处理函数的实际函数调用隐藏在Github上似乎不在Python代码中的函数后面 - 我不确定它们是否在私有/ C ++ repos中在其他地方。

1 个答案:

答案 0 :(得分:1)

看侧栏吧。查看有关同一ValueError的所有SO问题?

虽然环境各不相同,但几乎在每种情况下都是在Python上下文中使用一个需要标量布尔值的布尔数组的结果。

一个简单的例子是

In [236]: if np.arange(10)>5:print('yes')
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-236-633002262b65> in <module>()
----> 1 if np.arange(10)>5:print('yes')

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

np.arange(10)>5生成一个布尔数组np.array([False, False, ...])

组合布尔表达式也可以产生这种效果。 np.arange(10)>5 | np.arange(10)<2产生这个,(np.arange(10)>5) | (np.arange(10)<2)没有 - 因为逻辑运算符的存在。在这种情况下使用and代替|是没有希望的。

我会更详细地查看您的代码,但与此同时,这可能会帮助您自己找到问题。

==================

来自错误堆栈的

if (phi_a1 > phi0 + c1 * alpha1 * derphi0) or \

此时的代码期望(phi_a1 > phi0 + c1 * alpha1 * derphi0)(以及or之后的任何内容)成为标量。据推测,其中一个变量是具有多个值的数组。不可否认,这是在调用堆栈中发生的,因此很难将这些值追溯到您的代码中。

打印,专注于可变类型和形状,可能是最有用的。有时在这些迭代求解器上,代码在一个循环中运行良好,然后一些变量更改为数组,并在下一个循环中窒息。

==================

您为什么使用np.matrix.trace?在我的测试中产生一个2d单个元素np.matrix。它不会产生这种ValueError,但它仍然存在疑问。