Open sjperkins opened 6 years ago
Hi, I had a similar issue where I was doing physics simulations that involved complex numbers. I got around this by using the following, which seems to be working okay for me but you should double check for your own scenario.
from autograd.core import make_vjp as _make_vjp, make_jvp as _make_jvp
from autograd.extend import primitive, defvjp_argnum, vspace
from autograd.wrap_util import unary_to_nary
from autograd.builtins import tuple as atuple
@unary_to_nary
def jacobian_pkl(fun, x):
vjp, ans = _make_vjp(fun, x)
ans_vspace = vspace(ans)
jacobian_shape = ans_vspace.shape + vspace(x).shape
grads = map(vjp, ans_vspace.standard_basis())
grads_out = np.stack(grads)
if(np.prod(jacobian_shape) == np.prod(grads_out.shape)):
return np.reshape(grads_out, jacobian_shape)
else:
my_jacobian_shape = ans_vspace.shape + vspace(x).shape + (2,) # 2 to support real/im
re_im_grads = np.squeeze(np.reshape(grads_out, my_jacobian_shape))
out = re_im_grads[..., 0] + 1j * re_im_grads[..., 1]
return out
Edit: I tested the above hack a bit more and it seems to not work in some cases that I did not carefully debug. Separating real/im below works fine.
In my case I also had some affine transformations with complex numbers. If that is what you have, you can modify your function to take in a vector with the real and imaginary components stacked, and do the complex math within the function - that way the jacobian never sees a complex number.
On
the following:
results in
Unfortunately, passing the second argument as complex128 by calling
jacob(lm, uvw.astype(np.complex128), frequency)
as suggested by https://github.com/HIPS/autograd/issues/27 does not work around this.