Example #1
0
 def testJVPFunctionUsedByAccumulatorForOps(self):
     previous_fn = forwardprop._jvp_dispatch
     try:
         x = constant_op.constant(1.)
         with forwardprop.ForwardAccumulator(x, 2.) as acc:
             y = x + x
             pywrap_tensorflow.TFE_Py_RegisterJVPFunction(
                 lambda *args, **kwargs: [constant_op.constant(-15.)])
             z = x + x
         self.assertAllClose(4., acc.jvp(y))
         self.assertAllClose(-15., acc.jvp(z))
     finally:
         pywrap_tensorflow.TFE_Py_RegisterJVPFunction(previous_fn)
Example #2
0
_TRACE_COUNT_LIMIT = 32


def _jvp_dispatch(op_name, attr_tuple, inputs, outputs, tangents):
    """Determine which forwardprop function to call."""
    # Note that this _TRACE_COUNT read races with writes. That's fine, it just
    # means we may trace a few more exact shapes before moving on to relaxation.
    if _TRACE_COUNT.get(op_name, 0) < _TRACE_COUNT_LIMIT:
        return _jvp_exact_shapes(op_name, attr_tuple, inputs, outputs,
                                 tangents)
    else:
        return _jvp_relaxed_shapes(op_name, attr_tuple, inputs, outputs,
                                   tangents)


pywrap_tensorflow.TFE_Py_RegisterJVPFunction(_jvp_dispatch)


@tf_export("autodiff.ForwardAccumulator", v1=[])
class ForwardAccumulator(object):
    """Computes Jacobian-vector products ("JVP"s) using forward-mode autodiff.

  Compare to `tf.GradientTape` which computes vector-Jacobian products ("VJP"s)
  using reverse-mode autodiff (backprop). Reverse mode is more attractive when
  computing gradients of a scalar-valued function with respect to many inputs
  (e.g. a neural network with many parameters and a scalar loss). Forward mode
  works best on functions with many outputs and few inputs. Since it does not
  hold on to intermediate activations, it is much more memory efficient than
  backprop where it is applicable.

  Consider a simple linear regression: