human
Complete this python program:
def check_numeric_gradient(sym, location, aux_states=None, numeric_eps=0.001, rtol=0.01, atol=None, grad_nodes=None, use_forward_train=True, ctx=None):
assistant
#Here is the Python code you requested.

    """Verify an operation by checking backward pass via finite difference method.
    Based on Theano\s `theano.gradient.verify_grad` [1]
    Parameters
    sym : Symbol
    Symbol containing op to test
    location : list or tuple or dict
    Argument values used as location to compute gradient
    - if type is list of numpy.ndarray
    inner elements should have the same order as mxnet.sym.list_arguments().
    - if type is dict of str -> numpy.ndarray
    maps the name of arguments to the corresponding numpy.ndarray.
    *In either case, value of all the arguments must be provided.*
    aux_states : ist or tuple or dict, optional
    The auxiliary states required when generating the executor for the symbol.
    numeric_eps : float, optional
    Delta for the finite difference method that approximates the gradient.
    check_eps : float, optional
    relative error eps used when comparing numeric grad to symbolic grad.
    grad_nodes : None or list or tuple or dict, optional
    Names of the nodes to check gradient on
    use_forward_train : bool
    Whether to use is_train=True when computing the finite-difference.
    ctx : Context, optional
    Check the gradient computation on the specified device.
    References
    ..[1] https://github.com/Theano/Theano/blob/master/theano/gradient.py
    """
    if (ctx is None):
        ctx = default_context()
    def random_projection(shape):
        'Get    a    random    weight    matrix    with    not    too    small    elements\n\n                                Parameters\n                                ----------\n                                shape    :    list    or    tuple\n                                '
        plain = (_rng.rand(*shape) + 0.1)
        return plain
    location = _parse_location(sym=sym, location=location, ctx=ctx)
    location_npy = {k: v.asnumpy() for (k, v) in location.items()}
    aux_states = _parse_aux_states(sym=sym, aux_states=aux_states, ctx=ctx)
    if (aux_states is not None):
        aux_states_npy = {k: v.asnumpy() for (k, v) in aux_states.items()}
    else:
        aux_states_npy = None
    if (grad_nodes is None):
        grad_nodes = sym.list_arguments()
        grad_req = {k: 'write' for k in grad_nodes}
    elif isinstance(grad_nodes, (list, tuple)):
        grad_nodes = list(grad_nodes)
        grad_req = {k: 'write' for k in grad_nodes}
    elif isinstance(grad_nodes, dict):
        grad_req = grad_nodes.copy()
        grad_nodes = grad_nodes.keys()
    else:
        raise ValueError
    input_shape = {k: v.shape for (k, v) in location.items()}
    (_, out_shape, _) = sym.infer_shape(**input_shape)
    proj = mx.sym.Variable('__random_proj')
    out = (sym * proj)
    out = mx.sym.MakeLoss(out)
    location = dict((list(location.items()) + [('__random_proj', mx.nd.array(random_projection(out_shape[0]), ctx=ctx))]))
    args_grad_npy = dict(([(k, _rng.normal(0, 0.01, size=location[k].shape)) for k in grad_nodes] + [('__random_proj', _rng.normal(0, 0.01, size=out_shape[0]))]))
    args_grad = {k: mx.nd.array(v, ctx=ctx) for (k, v) in args_grad_npy.items()}
    executor = out.bind(ctx, grad_req=grad_req, args=location, args_grad=args_grad, aux_states=aux_states)
    inps = executor.arg_arrays
    if (len(inps) != len(location)):
        raise ValueError(('Executor    arg_arrays    and    and    location    len ...