diff options
author | Akshay Modi <nareshmodi@google.com> | 2018-09-05 22:34:52 -0700 |
---|---|---|
committer | TensorFlower Gardener <gardener@tensorflow.org> | 2018-09-05 22:43:35 -0700 |
commit | e23d522e943309cefae368a11c21ae37b6986165 (patch) | |
tree | 959f83e6128e87734b837082164fb88dc3803ca9 /tensorflow/python/eager/backprop_test.py | |
parent | 5393c8f0dc57857c93482bff67f1134aae9af594 (diff) |
Allow creating a py EagerTensor that shares the underlying TensorHandle.
This is so that gradients with respect to scalars pass (see the test added in
backprop_test.py).
A micro benchmark just calling constant_op.constant slows down a bit - this is
inevitable as we are creating a new python object.
After: walltime: ~2.1
Before: walltime: ~1.47
Linear regression benchmark is pretty much unchanged.
PiperOrigin-RevId: 211753801
Diffstat (limited to 'tensorflow/python/eager/backprop_test.py')
-rw-r--r-- | tensorflow/python/eager/backprop_test.py | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/tensorflow/python/eager/backprop_test.py b/tensorflow/python/eager/backprop_test.py index 6673178ee7..3319b440b4 100644 --- a/tensorflow/python/eager/backprop_test.py +++ b/tensorflow/python/eager/backprop_test.py @@ -957,5 +957,45 @@ class BackpropTest(test.TestCase): self.assertAllEqual(grad1, grad2) + @test_util.run_in_graph_and_eager_modes + def testDifferentiatingScalarCache(self): + # In the following test, if x2 = x1 (i.e the objects are the exact same), + # then y is essentially, 2*x1, and dy/dx1 = 2. + # When we had a pure scalar cache in eager, this would be the case. This + # test prevents us from going back to that case. + with backprop.GradientTape(persistent=False) as g: + x1 = constant_op.constant(3.0) + x2 = constant_op.constant(3.0) + g.watch(x1) + g.watch(x2) + y = x1 + x2 + grad = g.gradient(target=y, sources=[x1]) + self.assertEqual(self.evaluate(grad), [1.0]) + + def testVariablesAndConstantsProduceTheSameGradients(self): + + # In the following test, differentiating [y, z] against [a, b] gives: + # (dy/da + dz/da, dy/db + dz/db). + # If a and b are the same constant, dz/da will not be 0 (which it should + # be). + # This is solved by using variable since doing a read_value on a tensor will + # produce a new tensor and corresponding TensorHandle, and not reuse the + # same tensor (which would happen if we are using a cache and reusing + # EagerTensor objects). + def get_grads(a, b): + with backprop.GradientTape() as tape: + tape.watch([a, b]) + y = a**3 + z = b**2 + return tape.gradient([y, z], [a, b]) + + gradients_constants = get_grads( + constant_op.constant(2.0), constant_op.constant(2.0)) + gradients_variables = get_grads( + resource_variable_ops.ResourceVariable(2.0), + resource_variable_ops.ResourceVariable(2.0)) + self.assertAllEqual(gradients_constants, gradients_variables) + + if __name__ == '__main__': test.main() |