def unary_nd(f, x, eps=EPS): if isinstance(x, array_types): if np.iscomplexobj(x): nd_grad = np.zeros(x.shape) + 0j elif isinstance(x, garray_obj): nd_grad = np.array(np.zeros(x.shape), dtype=np.gpu_float32) else: nd_grad = np.zeros(x.shape) for dims in it.product(*list(map(range, x.shape))): nd_grad[dims] = unary_nd(indexed_function(f, x, dims), x[dims]) return nd_grad elif isinstance(x, tuple): return tuple([ unary_nd(indexed_function(f, tuple(x), i), x[i]) for i in range(len(x)) ]) elif isinstance(x, dict): return { k: unary_nd(indexed_function(f, x, k), v) for k, v in six.iteritems(x) } elif isinstance(x, list): return [ unary_nd(indexed_function(f, x, i), v) for i, v in enumerate(x) ] elif np.iscomplexobj(x): result = (f(x + eps/2) - f(x - eps/2)) / eps \ - 1j*(f(x + 1j*eps/2) - f(x - 1j*eps/2)) / eps return type(safe_type(x))(result) else: return type(safe_type(x))((f(x + eps / 2) - f(x - eps / 2)) / eps)
def vjp(g): ge, gu = g ge = _matrix_diag(ge) f = 1/(e[..., anp.newaxis, :] - e[..., :, anp.newaxis] + 1.e-20) f -= _diag(f) ut = anp.swapaxes(u, -1, -2) r1 = f * _dot(ut, gu) r2 = -f * (_dot(_dot(ut, anp.conj(u)), anp.real(_dot(ut, gu)) * anp.eye(n))) r = _dot(_dot(anp.linalg.inv(ut), ge + r1 + r2), ut) if not anp.iscomplexobj(x): r = anp.real(r) # the derivative is still complex for real input (imaginary delta is allowed), real output # but the derivative should be real in real input case when imaginary delta is forbidden return r
def unary_nd(f, x, eps=EPS): if isinstance(x, array_types): if np.iscomplexobj(x): nd_grad = np.zeros(x.shape) + 0j elif isinstance(x, garray_obj): nd_grad = np.array(np.zeros(x.shape), dtype=np.gpu_float32) else: nd_grad = np.zeros(x.shape) for dims in it.product(*list(map(range, x.shape))): nd_grad[dims] = unary_nd(indexed_function(f, x, dims), x[dims]) return nd_grad elif isinstance(x, tuple): return tuple([unary_nd(indexed_function(f, tuple(x), i), x[i]) for i in range(len(x))]) elif isinstance(x, dict): return {k : unary_nd(indexed_function(f, x, k), v) for k, v in six.iteritems(x)} elif isinstance(x, list): return [unary_nd(indexed_function(f, x, i), v) for i, v in enumerate(x)] elif np.iscomplexobj(x): result = (f(x + eps/2) - f(x - eps/2)) / eps \ - 1j*(f(x + 1j*eps/2) - f(x - 1j*eps/2)) / eps return type(safe_type(x))(result) else: return type(safe_type(x))((f(x + eps/2) - f(x - eps/2)) / eps)
def _flip(a, trans): if anp.iscomplexobj(a): return 'H' if trans in ('N', 0) else 'N' else: return 'T' if trans in ('N', 0) else 'N'
def _flip(a, trans): if anp.iscomplexobj(a): return "H" if trans in ("N", 0) else "N" else: return "T" if trans in ("N", 0) else "N"
def test_real_type(): fun = lambda x: np.sum(np.real(x)) df = grad(fun) assert np.isrealobj(df(2.0)) assert np.iscomplexobj(df(1.0j))