human
Complete this python program:
def check_backward(func, x_data, y_grad, params=(), eps=0.001, atol=1e-05, rtol=0.0001, no_grads=None, dtype=None):
assistant
#Here is the Python code you requested.

    """Test backward procedure of a given function.
    This function automatically check backward-process of given function.
    For example, when you have a :class:`~chainer.Function` class ``MyFunc``,
    that gets two arguments and returns one value, you can make its test like
    this::
    >> def test_my_func(self):
    >>   func = MyFunc()
    >>   x1_data = xp.array(...)
    >>   x2_data = xp.array(...)
    >>   gy_data = xp.array(...)
    >>   check_backward(func, (x1_data, x2_data), gy_data)
    This method creates :class:`~chainer.Variable` objects with ``x_data``
    and calls ``func`` with the :class:`~chainer.Variable` s to get its result
    as :class:`~chainer.Variable`.
    Then, it sets ``y_grad`` array to ``grad`` attribute of the result and
    calls ``backward`` method to get gradients of the inputs.
    To check correctness of the gradients, the function calls
    :func:`numerical_grad` to calculate numerically the gradients and compares
    the types of gradients with :func:`chainer.testing.assert_allclose`.
    If input objects (``x1_data`` or/and ``x2_data`` in this example) represent
    integer variables, their gradients are ignored.
    You can simplify a test when ``MyFunc`` gets only one argument::
    >>   check_backward(func, x1_data, gy_data)
    If ``MyFunc`` is a loss function which returns a zero-dimensional
    array, pass ``None`` to ``gy_data``. In this case, it sets ``1`` to
    ``grad`` attribute of the result::
    >>   check_backward(my_loss_func, (x1_data, x2_data), None)
    If ``MyFunc`` returns multiple outputs, pass all gradients for outputs
    as a tuple::
    >>   gy1_data = xp.array(...)
    >>   gy2_data = xp.array(...)
    >>   check_backward(func, x1_data, (gy1_data, gy2_data))
    You can also test a :class:`~chainer.Link`.
    To check gradients of parameters of the link, set a tuple of the parameters
    to ``params`` arguments::
    >>   check_backward(my_link, (x1_data, x2_data), gy_data,
    >>                  (my_link.W, my_link.b))
    Note that..."""
    x_data = _as_tuple(x_data)
    if (y_grad is not None):
        y_grad = _as_tuple(y_grad)
    params = _as_tuple(params)
    xs = [variable.Variable(x) for x in x_data]
    y = func(*xs)
    y = _as_tuple(y)
    y = identity.Identity().apply(y)
    if (y_grad is not None):
        if (len(y) != len(y_grad)):
            raise ValueError('`y_grad`    must    have    the    same    length    of    output    values')
        for (iy, igy) in six.moves.zip(y, y_grad):
            iy.grad = igy
    else:
        if (len(y) != 1):
            raise ValueError('When    `y_grad`    is    `None`,    the    function    must    return    azero-dimentional    array')
        y_grad = (1,)
    y[0].backward()
    if (dtype is None):
        casted_xs = [variable.Variable(x) for x in x_data]
    else:
        if (numpy.dtype(dtype).kind != 'f'):
            raise ValueError('`dtype`    is    allowed    only    float    type')
        if (len(params) > 0):
            raise ValueError('`dtype`    is    available    only    if    `params`    is    empty')
        casted_xs = [variable.Variable((x.astype(dtype, copy=False) if (x.dtype.kind == 'f') else x)) for x in x_data]
    def f():
        ys = func(*casted_xs)
        ys = _as_tuple(ys)
        return tuple((y.data for y in ys))
    if (no_grads is None):
        no_grads = [(x.dtype.kind != 'f') for x in xs]
    elif (len(no_grads) != len(xs)):
        raise ValueError('Length    of    no_grads    param    and    xs    should    be    same.')
    for (skip, x, cx) in six.moves.zip(no_grads, xs, casted_xs):
        if skip:
            assert (x.grad is None)
            continue
        (gx,) = numerical_grad(f, (cx.data,), y_grad, eps=eps)
        testing.assert_allclose(gx, x.grad, atol=atol, rtol=rtol)
        if (dtype is None):
            assert (gx.dtype == x.grad.dtype)
        else:
            assert ((gx.dtype.kind == 'f') and (gx.dtype == dtype))
    for p in params:
        (gp,) = numerical_grad(f, (p.data,), y_grad, eps=eps)
       ...