def test_backprop_multiple_graphs_non_existing(method): shape = (1, ) dtype = chainerx.float32 with chainerx.backprop_scope('bp1') as backprop_id1, \ chainerx.backprop_scope('bp2') as backprop_id2: xs = ( chainerx.full(shape, 2, dtype).require_grad(backprop_id1), chainerx.full(shape, 5, dtype).require_grad(backprop_id1), ) y = xs[0] * xs[1] if method == 'backward': chainerx.backward(y, backprop_id2) assert xs[0].get_grad(backprop_id1) is None assert xs[1].get_grad(backprop_id1) is None elif method == 'grad': grads = chainerx.grad([y], xs, backprop_id2) assert len(grads) == 2 assert grads[0] is None assert grads[1] is None else: assert False with pytest.raises(chainerx.ChainerxError): xs[0].get_grad(backprop_id2) with pytest.raises(chainerx.ChainerxError): xs[1].get_grad(backprop_id2)
def test_grad_with_retain_grad(): shape = (1, ) backprop_id = None dtype = chainerx.float32 xs = ( chainerx.full(shape, 3, dtype).require_grad(), chainerx.full(shape, 5, dtype).require_grad(), ) expected_gxs = (chainerx.full(shape, 4, dtype), ) # This test can't use _check_grad # because when using a forward function # it is not possible to easily expose the intermediate # values of the graph to verify the gradients a = xs[0] * 2 b = a + xs[1] c = a + b expected_retain = ( chainerx.full(shape, 1, dtype), chainerx.full(shape, 2, dtype), ) gxs = chainerx.grad([c], xs, backprop_id, retain_grad=True) # Check gradients. for gx, expected_gx in zip(gxs, expected_gxs): _assert_arrays_equal(gx, expected_gx) _assert_arrays_equal(expected_retain[0], b.get_grad(backprop_id)) _assert_arrays_equal(expected_retain[1], a.get_grad(backprop_id))
def test_backprop_multiple_graphs_non_existing(method): shape = (1,) dtype = chainerx.float32 with chainerx.backprop_scope('bp1') as backprop_id1, \ chainerx.backprop_scope('bp2') as backprop_id2: xs = ( chainerx.full(shape, 2, dtype).require_grad(backprop_id1), chainerx.full(shape, 5, dtype).require_grad(backprop_id1),) y = xs[0] * xs[1] with pytest.raises(chainerx.ChainerxError): if method == 'backward': chainerx.backward(y, backprop_id2) elif method == 'grad': chainerx.grad([y], xs, backprop_id2) else: assert False
def fprop(x0, x1): assert x0.is_grad_required(bp_x0) h = x0 * (x0 + x1) if method0 == 'backward': chainerx.backward(h, backprop_id=bp_x0) gx0 = x0.get_grad(bp_x0) elif method0 == 'grad': gx0, = chainerx.grad([h], [x0], backprop_id=bp_x0) else: assert False assert not gx0.is_backprop_required(bp_x0) assert gx0.is_backprop_required(bp_x1) return x0 * gx0,
def test_backprop_sole_array_node(method): shape = (1, ) dtype = chainerx.float32 x = chainerx.full(shape, 2, dtype).require_grad() expected_gx = chainerx.full(shape, 1, dtype) if method == 'backward': chainerx.backward(x) gx = x.get_grad() elif method == 'grad': gx, = chainerx.grad([x], [x]) else: assert False _assert_arrays_equal(gx, expected_gx)
def test_backprop_sole_array_node(method): shape = (1,) dtype = chainerx.float32 x = chainerx.full(shape, 2, dtype).require_grad() expected_gx = chainerx.full(shape, 1, dtype) if method == 'backward': chainerx.backward(x) gx = x.get_grad() elif method == 'grad': gx, = chainerx.grad([x], [x]) else: assert False _assert_arrays_equal(gx, expected_gx)
def _check_grad(fprop, xs, expected_gxs, gys=None, backprop_id=None, xs_indices=None, ys_indices=None, grad_outputs=[], set_grad=False, retain_grad=False): # Checks for test validity. assert callable(fprop) assert isinstance(xs, tuple) assert isinstance(expected_gxs, tuple) assert all([isinstance(a, chainerx.ndarray) for a in xs]) assert all( [isinstance(a, chainerx.ndarray) or a is None for a in expected_gxs]) # Forward. ys = fprop(*xs) # Set output gradients. if gys is not None: assert len(gys) == len(ys) for y, gy in zip(ys, gys): assert not y.is_grad_required() y.set_grad(gy, backprop_id) # Backward using grad. initial_gxs = [ x.get_grad(backprop_id) if x.is_grad_required(backprop_id) else chainerx.ChainerxError for x in xs ] if xs_indices is not None: actual_xs = tuple([xs[i] for i in xs_indices]) assert len(actual_xs) == len(expected_gxs) else: actual_xs = xs if ys_indices is not None: actual_ys = tuple([ys[i] for i in ys_indices]) else: actual_ys = ys gxs = chainerx.grad(actual_ys, actual_xs, backprop_id, grad_outputs=grad_outputs, set_grad=set_grad, retain_grad=retain_grad) # Check gradients. for gx, expected_gx in zip(gxs, expected_gxs): _assert_arrays_equal(gx, expected_gx) # Check gradients of output arrays. if gys is None: gys = (None, ) * len(xs) for y, gy in zip(ys, gys): if gy is None: assert not y.is_grad_required(backprop_id) with pytest.raises(chainerx.ChainerxError): y.get_grad(backprop_id) else: assert y.is_grad_required(backprop_id) _assert_arrays_equal(gy, y.get_grad(backprop_id)) if set_grad: for x, gx in zip(xs, gxs): _assert_arrays_equal(gx, x.get_grad(backprop_id)) else: # Check initial gradients of inputs and that they are not modified. for x, initial_gx in zip(xs, initial_gxs): if initial_gx is chainerx.ChainerxError: assert not x.is_grad_required(backprop_id) with pytest.raises(chainerx.ChainerxError): x.get_grad(backprop_id) else: assert x.is_grad_required(backprop_id) _assert_arrays_equal(initial_gx, x.get_grad(backprop_id))
def _check_grad( fprop, xs, expected_gxs, gys=None, backprop_id=None, xs_indices=None, ys_indices=None): # Checks for test validity. assert callable(fprop) assert isinstance(xs, tuple) assert isinstance(expected_gxs, tuple) assert all([isinstance(a, chainerx.ndarray) for a in xs]) assert all([isinstance(a, chainerx.ndarray) or a is None for a in expected_gxs]) # Forward. ys = fprop(*xs) # Set output gradients. if gys is not None: assert len(gys) == len(ys) for y, gy in zip(ys, gys): assert not y.is_grad_required() y.set_grad(gy, backprop_id) # Backward using grad. initial_gxs = [ x.get_grad(backprop_id) if x.is_grad_required(backprop_id) else chainerx.ChainerxError for x in xs] if xs_indices is not None: actual_xs = tuple([xs[i] for i in xs_indices]) assert len(actual_xs) == len(expected_gxs) else: actual_xs = xs if ys_indices is not None: actual_ys = tuple([ys[i] for i in ys_indices]) else: actual_ys = ys gxs = chainerx.grad(actual_ys, actual_xs, backprop_id) # Check gradients. for gx, expected_gx in zip(gxs, expected_gxs): _assert_arrays_equal(gx, expected_gx) # Check gradients of output arrays. if gys is None: gys = (None,) * len(xs) for y, gy in zip(ys, gys): if gy is None: assert not y.is_grad_required(backprop_id) with pytest.raises(chainerx.ChainerxError): y.get_grad(backprop_id) else: assert y.is_grad_required(backprop_id) _assert_arrays_equal(gy, y.get_grad(backprop_id)) # Check initial gradients of inputs and that they are not modified. for x, initial_gx in zip(xs, initial_gxs): if initial_gx is chainerx.ChainerxError: assert not x.is_grad_required(backprop_id) with pytest.raises(chainerx.ChainerxError): x.get_grad(backprop_id) else: assert x.is_grad_required(backprop_id) _assert_arrays_equal(initial_gx, x.get_grad(backprop_id))