"""AI01 lab, step 6: check backprop against finite differences. You write both functions.A gradient check is an autograd engineer's unit test: nudge one input a tinyamount, see how much the output moves, and compare that slope with the gradthat backward() computed."""fromengineimportValuedefnumerical_grad(f,xs,h=1e-6):"""Estimate every partial derivative of f at the point xs. f a function that takes a list of floats and returns a float. xs the point, a list of floats. Must be left unchanged when you return. h the nudge size. Return a list of floats [df/dx0, df/dx1, ...]. Estimate each entry with the central difference (f(x with x_i + h) - f(x with x_i - h)) / (2h), holding every other coordinate fixed. Holding the rest fixed is exactly what "partial derivative" means. """raiseNotImplementedError("Step 6: numerical_grad")defmax_grad_error(f,xs,h=1e-6):"""Largest gap between backprop and numerical_grad for one function. f a function that takes a list of Values and returns one Value, built with your engine. xs the point, a list of floats. 1. Make fresh Values from xs, call f on them, call backward() on the result, and read each input Value's grad. 2. Call numerical_grad on the float version of f, passing h through. The float version is a function that takes a list of floats, wraps each float in a Value, calls f, and returns the output's .data. 3. Return the largest absolute difference between the two lists. """raiseNotImplementedError("Step 6: max_grad_error")