我想在Python 2.7(在Jupyter笔记本中)中使用HIPS autograd(https://github.com/HIPS/autograd)来查找参数 x 。我的正演模型(在给定时间点观察 t 作为参数 x 的函数)是 t 的分段函数。因此,我选择使用autograd.numpy.piecewise函数。我的损失(或客观)函数是一个直接的均方误差。我无法使用autograd.grad计算自动渐变。
下面的简单代码示例:
import autograd.numpy as anp
from autograd import grad
def forward_model(x, t): # it's a rectangular box of width x and height 1/x centered at the origin
y = anp.piecewise(t, [t < -x/2., (t >= -x/2.) & (t < x/2.), t >= x/2.], [0., 1/x, 0.])
return y
def loss(x, t, y):
y_hat = forward_model(x, t)
return anp.mean( (y_hat - y)**2 ) # mean squared error loss
x_star = 1. # ground truth parameter x
t = anp.linspace(-1., 1., 1001) # time points to evaluate function
y = forward_model(x_star, t)
x_init = 0.5
loss_init = loss(x_init, t, y)
grad_loss = grad(loss)
grad_init = grad_loss(x_init, t, y)
我得到的完整错误是:
ValueErrorTraceback (most recent call last) <ipython-input-507-e643ed94813b> in <module>()
16 loss_init = loss(x_init, t, y)
17 grad_loss = grad(loss)
---> 18 grad_init = grad_loss(x_init, t, y)
C:\Users\alan_dong\AppData\Local\Continuum\Anaconda2\lib\site-packages\autograd\wrap_util.pyc in nary_f(*args, **kwargs)
18 else:
19 x = tuple(args[i] for i in argnum)
---> 20 return unary_operator(unary_f, x, *nary_op_args, **nary_op_kwargs)
21 return nary_f
22 return nary_operator
C:\Users\alan_dong\AppData\Local\Continuum\Anaconda2\lib\site-packages\autograd\differential_operators.pyc in grad(fun, x)
22 arguments as `fun`, but returns the gradient instead. The function `fun`
23 should be scalar-valued. The gradient has the same type as the argument."""
---> 24 vjp, ans = _make_vjp(fun, x)
25 if not vspace(ans).size == 1:
26 raise TypeError("Grad only applies to real scalar-output functions. "
C:\Users\alan_dong\AppData\Local\Continuum\Anaconda2\lib\site-packages\autograd\core.pyc in make_vjp(fun, x)
8 def make_vjp(fun, x):
9 start_node = VJPNode.new_root(x)
---> 10 end_value, end_node = trace(start_node, fun, x)
11 if end_node is None:
12 def vjp(g): return vspace(x).zeros()
C:\Users\alan_dong\AppData\Local\Continuum\Anaconda2\lib\site-packages\autograd\tracer.pyc in trace(start_node, fun, x)
8 with trace_stack.new_trace() as t:
9 start_box = new_box(x, t, start_node)
---> 10 end_box = fun(start_box)
11 if isbox(end_box) and end_box._trace == start_box._trace:
12 return end_box._value, end_box._node
C:\Users\alan_dong\AppData\Local\Continuum\Anaconda2\lib\site-packages\autograd\wrap_util.pyc in unary_f(x)
13 else:
14 subargs = subvals(args, zip(argnum, x))
---> 15 return fun(*subargs, **kwargs)
16 if isinstance(argnum, int):
17 x = args[argnum]
<ipython-input-507-e643ed94813b> in loss(x, t, y)
6
7 def loss(x, t, y):
----> 8 y_hat = forward_model(x, t)
9 return anp.mean( (y_hat - y)**2 ) # mean squared error loss
10
<ipython-input-507-e643ed94813b> in forward_model(x, t)
2
3 def forward_model(x, t): # it's a rectangular box of width x and height 1/x centered at the origin
----> 4 y = anp.piecewise(t, [t < -x/2., (t >= -x/2.) & (t < x/2.), t >= x/2.], [0., 1/x, 0.])
5 return y
6
C:\Users\alan_dong\AppData\Local\Continuum\Anaconda2\lib\site-packages\autograd\tracer.pyc in f_wrapped(*args, **kwargs)
46 return new_box(ans, trace, node)
47 else:
---> 48 return f_raw(*args, **kwargs)
49 f_wrapped.fun = f_raw
50 f_wrapped._is_autograd_primitive = True
C:\Users\alan_dong\AppData\Local\Continuum\Anaconda2\lib\site-packages\numpy\lib\function_base.pyc in piecewise(x, condlist, funclist, *args, **kw) 1347 item
= funclist[k] 1348 if not isinstance(item, collections.Callable):
-> 1349 y[condlist[k]] = item 1350 else: 1351 vals = x[condlist[k]]
ValueError: setting an array element with a sequence.
我认为这与numpy.piecewise的funclist论证有关。当我改变正向模型(因此没有任何函数依赖于x)
时y = anp.piecewise(t, [t < -x/2., (t >= -x/2.) & (t < x/2.), t >= x/2.], [0., 1., 0.])
错误消失了。有任何想法吗?谢谢!
答案 0 :(得分:0)
似乎numpy.piecewise不受autograd支持。我最终将其更改为使用numpy.select的实现,该实现计算整个时间窗口中的每个函数,而不仅仅是其条件处于活动状态的区域。它似乎效率低下,但我想替代方法是编写一个自定义的autograd原语...