"""AI01 lab tests for gradcheck.py (step 6)."""importunittestfrom_implimportloadengine=load("engine")gradcheck=load("gradcheck")Value=engine.ValueclassStep6GradCheck(unittest.TestCase):deftest_partials_of_the_worked_example(self):# f(x, y) = x^2 y + 3y at (1, 3): df/dx = 2xy = 6, df/dy = x^2 + 3 = 4.f=lambdav:v[0]**2*v[1]+3*v[1]g=gradcheck.numerical_grad(f,[1.0,3.0])self.assertEqual(len(g),2)self.assertAlmostEqual(g[0],6.0,places=6)self.assertAlmostEqual(g[1],4.0,places=6)deftest_uses_the_central_difference(self):# For x^3 at x = 1 with h = 1e-3, the central difference is off by# h^2 = 1e-6, but the forward difference is off by about 3h = 3e-3.g=gradcheck.numerical_grad(lambdav:v[0]**3,[1.0],h=1e-3)self.assertLess(abs(g[0]-3.0),1e-5)deftest_uses_the_h_it_is_given(self):# The central difference of x^3 at 1 is exactly 3 + h^2, so h = 0.1 gives 3.01.g=gradcheck.numerical_grad(lambdav:v[0]**3,[1.0],h=0.1)self.assertAlmostEqual(g[0],3.01,places=9)deftest_leaves_the_point_unchanged(self):xs=[1.0,3.0]gradcheck.numerical_grad(lambdav:v[0]*v[1],xs)self.assertEqual(xs,[1.0,3.0])deftest_other_coordinates_are_held_fixed(self):# f = x*y*z at (2, 3, 4): partials are yz = 12, xz = 8, xy = 6.g=gradcheck.numerical_grad(lambdav:v[0]*v[1]*v[2],[2.0,3.0,4.0])forgot,wantinzip(g,[12.0,8.0,6.0]):self.assertAlmostEqual(got,want,places=5)deftest_max_grad_error_is_tiny_for_a_correct_engine(self):f=lambdav:(v[0]*v[1]+v[1])*v[2]# the running exampleerr=gradcheck.max_grad_error(f,[3.0,-2.0,5.0])self.assertLess(err,1e-5)deftest_max_grad_error_catches_a_broken_gradient(self):defbroken(v):out=v[0]*1.0out._backward=lambda:None# gradient never reaches v[0]returnout+v[1]err=gradcheck.max_grad_error(broken,[2.0,5.0])self.assertAlmostEqual(err,1.0,places=5)deftest_max_grad_error_catches_a_gradient_that_is_too_big(self):defdoubled(v):out=v[0]*1.0def_backward():v[0].grad+=2.0*out.grad# twice the true gradientout._backward=_backwardreturnout+v[1]err=gradcheck.max_grad_error(doubled,[2.0,5.0])self.assertAlmostEqual(err,1.0,places=5)deftest_max_grad_error_passes_h_on(self):# Backprop gives exactly 3 for x^3 at 1; the central difference with h = 0.1 gives 3.01.err=gradcheck.max_grad_error(lambdav:v[0]**3,[1.0],h=0.1)self.assertAlmostEqual(err,0.01,places=9)if__name__=="__main__":unittest.main()