我使用的是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中在其他地方。
答案 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,但它仍然存在疑问。