Пример #1
0
  def testVariablesAcrossGraphs(self):
    optimizer = momentum_lib.MomentumOptimizer(0.01, 0.5)
    with ops.Graph().as_default():
      var0 = resource_variable_ops.ResourceVariable(
          [1.0, 2.0], dtype=dtypes.float32, name="var0")
      var1 = resource_variable_ops.ResourceVariable(
          [3.0, 4.0], dtype=dtypes.float32, name="var1")
      if context.in_eager_mode():
        loss = lambda: math_ops.reduce_sum(var0 + var1)
      else:
        loss = math_ops.reduce_sum(var0 + var1)
      optimizer.minimize(loss)
      optimizer_variables = optimizer.variables()
      self.assertStartsWith(optimizer_variables[0].name, "var0")
      self.assertStartsWith(optimizer_variables[1].name, "var1")
      self.assertEquals(2, len(optimizer_variables))

    with ops.Graph().as_default():
      var2 = resource_variable_ops.ResourceVariable(
          [1.0, 2.0], dtype=dtypes.float32, name="var2")
      var3 = resource_variable_ops.ResourceVariable(
          [3.0, 4.0], dtype=dtypes.float32, name="var3")
      if context.in_eager_mode():
        loss = lambda: math_ops.reduce_sum(var2 + var3)
      else:
        loss = math_ops.reduce_sum(var2 + var3)
      optimizer.minimize(loss)
      optimizer_variables = optimizer.variables()
      self.assertStartsWith(optimizer_variables[0].name, "var2")
      self.assertStartsWith(optimizer_variables[1].name, "var3")
      self.assertEquals(2, len(optimizer_variables))
Пример #2
0
    def infer_step(recent_output, recent_logits, unused_loss):
      """Inference step."""
      if not context.in_eager_mode():
        recent_output.set_shape([None, None, None, 1])
      padded = tf.pad(recent_output, [[0, 0], [0, 1], [0, 0], [0, 0]])
      features["targets"] = padded
      # This is inefficient in that it generates samples at all timesteps,
      # not just the last one, except if target_modality is pointwise.
      samples, logits, losses = self.sample(features)
      # Concatenate the already-generated recent_output with last timestep
      # of the newly-generated samples.
      if target_modality.top_is_pointwise:
        cur_sample = samples[:, -1, :, :]
      else:
        cur_sample = samples[:,
                             common_layers.shape_list(recent_output)[1], :, :]
      cur_sample = tf.to_int64(tf.expand_dims(cur_sample, axis=1))
      samples = tf.concat([recent_output, cur_sample], axis=1)
      if not context.in_eager_mode():
        samples.set_shape([None, None, None, 1])

      # Assuming we have one shard for logits.
      logits = tf.concat([recent_logits, logits[:, -1:]], 1)
      loss = sum([l for l in losses.values() if l is not None])
      return samples, logits, loss
Пример #3
0
 def add_variable(self, name, shape=None, dtype=None, initializer=None):
   """***Only for use by descendants of Metric***."""
   if self._built:
     raise RuntimeError("Can't call add_variable() except in build().")
   if context.in_eager_mode():
     collections = None
   else:
     if self._use_global_variables:
       collections = [ops.GraphKeys.GLOBAL_VARIABLES]
     else:
       collections = [ops.GraphKeys.LOCAL_VARIABLES]
     collections += [ops.GraphKeys.METRIC_VARIABLES]
   # Variables are Checkpointable dependencies of Metrics regardless of the
   # global/local distinction. Users can avoid saving variables by not adding a
   # dependency on the Metric.
   v = self._add_variable_with_custom_getter(
       name=name,
       shape=shape,
       dtype=dtype,
       initializer=initializer,
       trainable=False,
       collections=collections,
       use_resource=True,
       getter=variable_scope.get_variable,
       # Raise duplicate variable exceptions from get_variable rather than
       # Checkpointable.
       overwrite=True)
   self._vars.append(v)
   if context.in_eager_mode():
     self._initial_values[v] = v.value()
   return v
Пример #4
0
  def test_zero_padding_1d(self):
    num_samples = 2
    input_dim = 2
    num_steps = 5
    shape = (num_samples, num_steps, input_dim)
    inputs = np.ones(shape)

    # basic test
    with self.test_session(use_gpu=True):
      testing_utils.layer_test(
          keras.layers.ZeroPadding1D,
          kwargs={'padding': 2},
          input_shape=inputs.shape)
      testing_utils.layer_test(
          keras.layers.ZeroPadding1D,
          kwargs={'padding': (1, 2)},
          input_shape=inputs.shape)

    # correctness test
    with self.test_session(use_gpu=True):
      layer = keras.layers.ZeroPadding1D(padding=2)
      layer.build(shape)
      output = layer(keras.backend.variable(inputs))
      if context.in_eager_mode():
        np_output = output.numpy()
      else:
        np_output = keras.backend.eval(output)
      for offset in [0, 1, -1, -2]:
        np.testing.assert_allclose(np_output[:, offset, :], 0.)
      np.testing.assert_allclose(np_output[:, 2:-2, :], 1.)

      layer = keras.layers.ZeroPadding1D(padding=(1, 2))
      layer.build(shape)
      output = layer(keras.backend.variable(inputs))
      if context.in_eager_mode():
        np_output = output.numpy()
      else:
        np_output = keras.backend.eval(output)
      for left_offset in [0]:
        np.testing.assert_allclose(np_output[:, left_offset, :], 0.)
      for right_offset in [-1, -2]:
        np.testing.assert_allclose(np_output[:, right_offset, :], 0.)
      np.testing.assert_allclose(np_output[:, 1:-2, :], 1.)
      layer.get_config()

    # test incorrect use
    with self.assertRaises(ValueError):
      keras.layers.ZeroPadding1D(padding=(1, 1, 1))
    with self.assertRaises(ValueError):
      keras.layers.ZeroPadding1D(padding=None)
Пример #5
0
def _defun_internal(name, func, args, kwds):
  """Defines and returns graph-mode version of func."""
  graph_key = ops.get_default_graph()._graph_key  # pylint: disable=protected-access
  with context.graph_mode():
    captures = {}
    tmp_graph = CapturingGraph(captures)
    # Inherit the graph key, since this is used for matching variables in
    # optimizers.
    tmp_graph._graph_key = graph_key  # pylint: disable=protected-access
    # Copy the graph collections to ensure summaries and other things work. This
    # lets the function access (but not mutate) collections of the containing
    # graph, such as the global step and the summary writer collections.
    curr_graph = ops.get_default_graph()
    for collection in curr_graph.collections:
      tmp_graph.get_collection_ref(collection)[:] = curr_graph.get_collection(
          collection)
    with tmp_graph.as_default():
      func_inputs = _get_defun_inputs(args)

      with capture_tensors(captures):
        this_tape = tape.push_new_tape()
        try:
          func_outputs = func(*func_inputs, **kwds)
        finally:
          tape.pop_tape(this_tape)
        variables = this_tape.watched_variables()

        # Returning a closed-over tensor as an output does not trigger a
        # call to convert_to_tensor, so we manually capture all such tensors.
        outputs_list = _flatten(func_outputs)
        func_def_outputs = [
            _convert_to_graph_tensor(x) for x in outputs_list if x is not None
        ]

      ids = list(sorted(captures.keys()))
      if ids:
        extra_inputs, extra_placeholders = zip(* [captures[x] for x in ids])
      else:
        extra_inputs = []
        extra_placeholders = []
      output_shapes = tuple(
          x.shape if isinstance(x, ops.Tensor) else None
          for x in outputs_list)

  flat_inputs = [x for x in nest.flatten(func_inputs)
                 if isinstance(x, ops.Tensor)]
  all_inputs = flat_inputs + list(extra_placeholders)
  all_ignored_ops = frozenset(x.op for x in all_inputs)
  fname = _inference_name(name)
  operations = tuple(x for x in tmp_graph.get_operations()
                     if x not in all_ignored_ops)
  # Register any other functions defined in the graph
  # TODO(ashankar): Oh lord, forgive me for this lint travesty.
  if context.in_eager_mode():
    for f in tmp_graph._functions.values():  # pylint: disable=protected-access
      # TODO(ashankar): What about the gradient registry?
      _register(f._c_func)  # pylint: disable=protected-access
  return GraphModeFunction(
      fname, all_inputs, extra_inputs, tmp_graph, operations, func_def_outputs,
      func_outputs, output_shapes, variables)
Пример #6
0
  def start_queue_runners(self, sess, queue_runners=None):
    """Start threads for `QueueRunners`.

    Note that the queue runners collected in the graph key `QUEUE_RUNNERS`
    are already started automatically when you create a session with the
    supervisor, so unless you have non-collected queue runners to start
    you do not need to call this explicitly.

    Args:
      sess: A `Session`.
      queue_runners: A list of `QueueRunners`. If not specified, we'll use the
        list of queue runners gathered in the graph under the key
        `GraphKeys.QUEUE_RUNNERS`.

    Returns:
      The list of threads started for the `QueueRunners`.

    Raises:
      RuntimeError: If called with eager execution enabled.

    @compatibility(eager)
    Queues are not compatible with eager execution. To ingest data when eager
    execution is enabled, use the `tf.data` API.
    @end_compatibility
    """
    if context.in_eager_mode():
      raise RuntimeError("Queues are not compatible with eager execution.")
    if queue_runners is None:
      queue_runners = self._graph.get_collection(ops.GraphKeys.QUEUE_RUNNERS)
    threads = []
    for qr in queue_runners:
      threads.extend(qr.create_threads(sess, coord=self._coord, daemon=True,
                                       start=True))
    return threads
Пример #7
0
  def zero_state(self, batch_size, dtype):
    """Return zero-filled state tensor(s).

    Args:
      batch_size: int, float, or unit Tensor representing the batch size.
      dtype: the data type to use for the state.

    Returns:
      If `state_size` is an int or TensorShape, then the return value is a
      `N-D` tensor of shape `[batch_size, state_size]` filled with zeros.

      If `state_size` is a nested list or tuple, then the return value is
      a nested list or tuple (of the same structure) of `2-D` tensors with
      the shapes `[batch_size, s]` for each s in `state_size`.
    """
    # Try to use the last cached zero_state. This is done to avoid recreating
    # zeros, especially when eager execution is enabled.
    state_size = self.state_size
    is_eager = context.in_eager_mode()
    if is_eager and hasattr(self, "_last_zero_state"):
      (last_state_size, last_batch_size, last_dtype,
       last_output) = getattr(self, "_last_zero_state")
      if (last_batch_size == batch_size and
          last_dtype == dtype and
          last_state_size == state_size):
        return last_output
    with ops.name_scope(type(self).__name__ + "ZeroState", values=[batch_size]):
      output = _zero_state_tensors(state_size, batch_size, dtype)
    if is_eager:
      self._last_zero_state = (state_size, batch_size, dtype, output)
    return output
Пример #8
0
  def losses(self):
    """Retrieve the network's losses.

    Will only include losses that are either
    unconditional, or conditional on inputs to this model
    (e.g. will not include losses that depend on tensors
    that aren't inputs to this model).

    Returns:
        A list of loss tensors.
    """
    losses = []
    if context.in_eager_mode():
      for layer in self.layers:
        losses += layer.losses
      return losses

    for layer in self.layers:
      losses += layer.losses

    relevant_inputs = []
    for i in range(len(self._inbound_nodes)):
      inputs = self.get_input_at(i)
      if isinstance(inputs, list):
        relevant_inputs += inputs
      else:
        relevant_inputs.append(inputs)
    reachable = layers_util.get_reachable_from_inputs(relevant_inputs, losses)
    relevant_conditional_losses = [x for x in losses if x in reachable]
    unconditional_losses = [
        x for x in losses if x._unconditional_loss]  # pylint: disable=protected-access
    return list(set(
        relevant_conditional_losses + unconditional_losses + self._losses))
Пример #9
0
  def losses(self):
    """Retrieve the network's losses.

    Will only include losses that are either
    unconditional, or conditional on inputs to this model
    (e.g. will not include losses that depend on tensors
    that aren't inputs to this model).

    Returns:
        A list of loss tensors.
    """
    losses = []
    if context.in_eager_mode():
      for layer in self.layers:
        losses += layer.losses
      return losses

    # Retrieve losses for all internal layers.
    for layer in self.layers:
      if hasattr(layer, 'losses'):
        # Collect losses that are dependent on inputs
        # that are part of the model.
        for node_index, node in enumerate(layer._inbound_nodes):  # pylint: disable=protected-access
          node_key = _make_node_key(layer.name, node_index)
          if node_key in self._network_nodes:
            # The model owns this layer node.
            inputs = node.input_tensors
            losses += layer.get_losses_for(inputs)
        # Collect unconditional losses.
        losses += layer.get_losses_for(None)
    # Add any potential unconditional model-level loss.
    losses += self.get_losses_for(None)
    return losses
Пример #10
0
  def _get_weights(self, hidden_dim=None):
    """Create or get concatenated embedding or softmax variable.

    Args:
      hidden_dim: dim of the variable. Defaults to self._body_input_depth

    Returns:
       a list of self._num_shards Tensors.
    """
    if hidden_dim is None:
      hidden_dim = self._body_input_depth
    num_shards = self._model_hparams.symbol_modality_num_shards
    shards = []
    for i in xrange(num_shards):
      shard_size = (self._vocab_size // num_shards) + (
          1 if i < self._vocab_size % num_shards else 0)
      var_name = "weights_%d" % i
      shards.append(
          tf.get_variable(
              var_name, [shard_size, hidden_dim],
              initializer=tf.random_normal_initializer(0.0, hidden_dim**-0.5)))
    if num_shards == 1:
      ret = shards[0]
    else:
      ret = tf.concat(shards, 0)
    # Convert ret to tensor.
    if not context.in_eager_mode():
      ret = eu.convert_gradient_to_tensor(ret)
    return ret
  def to_proto(self, export_scope=None):
    """Converts a `ResourceVariable` to a `VariableDef` protocol buffer.

    Args:
      export_scope: Optional `string`. Name scope to remove.

    Raises:
      RuntimeError: If run in EAGER mode.

    Returns:
      A `VariableDef` protocol buffer, or `None` if the `Variable` is not
      in the specified name scope.
    """
    if context.in_eager_mode():
      raise RuntimeError("to_proto not supported in EAGER mode.")
    if export_scope is None or self.handle.name.startswith(export_scope):
      var_def = variable_pb2.VariableDef()
      var_def.variable_name = ops.strip_name_scope(self.handle.name,
                                                   export_scope)
      var_def.initializer_name = ops.strip_name_scope(self.initializer.name,
                                                      export_scope)
      if self._cached_value is not None:
        var_def.snapshot_name = ops.strip_name_scope(self._cached_value.name,
                                                     export_scope)
      var_def.is_resource = True
      if self._save_slice_info:
        var_def.save_slice_info_def.MergeFrom(
            self._save_slice_info.to_proto(export_scope=export_scope))
      return var_def
    else:
      return None
Пример #12
0
def merge_all(key=_ops.GraphKeys.SUMMARIES, scope=None):
  """Merges all summaries collected in the default graph.

  Args:
    key: `GraphKey` used to collect the summaries.  Defaults to
      `GraphKeys.SUMMARIES`.
    scope: Optional scope used to filter the summary ops, using `re.match`

  Returns:
    If no summaries were collected, returns None.  Otherwise returns a scalar
    `Tensor` of type `string` containing the serialized `Summary` protocol
    buffer resulting from the merging.

  Raises:
    RuntimeError: If called with eager execution enabled.

  @compatibility(eager)
  Not compatible with eager execution. To write TensorBoard
  summaries under eager execution, use `tf.contrib.summary` instead.
  @end_compatbility
  """
  if _context.in_eager_mode():
    raise RuntimeError(
        'Merging tf.summary.* ops is not compatible with eager execution. '
        'Use tf.contrib.summary instead.')
  summary_ops = _ops.get_collection(key, scope=scope)
  if not summary_ops:
    return None
  else:
    return merge(summary_ops)
Пример #13
0
def assert_integer(x, message=None, name=None):
  """Assert that `x` is of integer dtype.

  Example of adding a dependency to an operation:

  ```python
  with tf.control_dependencies([tf.assert_integer(x)]):
    output = tf.reduce_sum(x)
  ```

  Args:
    x: `Tensor` whose basetype is integer and is not quantized.
    message: A string to prefix to the default message.
    name: A name for this operation (optional).  Defaults to "assert_integer".

  Raises:
    TypeError:  If `x.dtype` is anything other than non-quantized integer.

  Returns:
    A `no_op` that does nothing.  Type can be determined statically.
  """
  message = message or ''
  with ops.name_scope(name, 'assert_integer', [x]):
    x = ops.convert_to_tensor(x, name='x')
    if not x.dtype.is_integer:
      if context.in_eager_mode():
        name = 'tensor'
      else:
        name = x.name
      err_msg = (
          '%s  Expected "x" to be integer type.  Found: %s of dtype %s'
          % (message, name, x.dtype))
      raise TypeError(err_msg)

    return control_flow_ops.no_op('statically_determined_was_integer')
Пример #14
0
 def run_restore_ops(self, session=None):
   """Run operations to restore objects in the dependency graph."""
   if context.in_eager_mode():
     return  # Run eagerly
   if session is None:
     session = ops.get_default_session()
   session.run(self._checkpoint.restore_ops, feed_dict=self._feed_dict)
Пример #15
0
def _convert_to_graph_tensor(value, dtype=None, name=None, as_ref=False):
  """Captures a Tensor while building a graph mode function.

  Arguments:
    value: A Tensor object.
    dtype: The datatype of the value produced by the node in the graph.
    name:  Name of the node in the graph.
    as_ref: Ignored (required by register_tensor_conversion_function).

  Returns:
    Returns a constant (the current value of the tensor) if capturing
    is not enabled. A placeholder which will have the value of the
    tensor at runtime otherwise.
  """
  if context.in_eager_mode():
    return value
  _ = as_ref
  tensor_map = _scoped_captures.tensors
  if tensor_map is None:
    # Capturing is not enabled.
    return constant_op.constant(value.numpy())
  captured_value = tensor_map.get(ops.tensor_id(value), None)
  if captured_value is None:
    captured_value = graph_placeholder(
        dtype=dtype or value.dtype, shape=value.shape, name=name)
    if captured_value.dtype == dtypes.resource:
      captured_value._handle_data = value._handle_data  # pylint: disable=protected-access
    tensor_map[ops.tensor_id(value)] = (value, captured_value)
  else:
    captured_value = captured_value[1]
  tape.record_operation("captured_value", [captured_value], [value], [],
                        lambda x: x)
  return captured_value
Пример #16
0
def _safe_div(numerator, denominator, name="value"):
  """Computes a safe divide which returns 0 if the denominator is zero.

  Note that the function contains an additional conditional check that is
  necessary for avoiding situations where the loss is zero causing NaNs to
  creep into the gradient computation.

  Args:
    numerator: An arbitrary `Tensor`.
    denominator: `Tensor` whose shape matches `numerator` and whose values are
      assumed to be non-negative.
    name: An optional name for the returned op.

  Returns:
    The element-wise value of the numerator divided by the denominator.
  """
  if isinstance(denominator, float):
    if math_ops.equal(denominator, 0.0):
      return ops.convert_to_tensor(0.0, dtype=numerator.dtype)
    return math_ops.div(numerator, denominator)
  if context.in_eager_mode() and denominator._rank() == 0:  # pylint: disable=protected-access
    if math_ops.equal(denominator, 0.0):
      return ops.convert_to_tensor(0.0, dtype=numerator.dtype)
    return math_ops.div(numerator, denominator)
  return array_ops.where(
      math_ops.greater(denominator, 0),
      math_ops.div(numerator, array_ops.where(
          math_ops.equal(denominator, 0),
          array_ops.ones_like(denominator), denominator)),
      array_ops.zeros_like(numerator),
      name=name)
Пример #17
0
  def run_evaluation(init_op, call_op, results_op, sess=None):
    """Convenience method for running the ops returned by evaluate_on_dataset.

    Args:
      init_op: An op that initializes/resets evaluation state.
      call_op: An op that updates evaluation state on a mini-batch of examples.
        Must generate an tf.errors.OutOfRangeError when done.
      results_op: A dictionary of tensors that compute the final evaluation
        results from the evaluation state.
      sess: The Session to run the evaluation in. Defaults to the default
        Session.

    Returns:
      A dictionary of values, parallel to results_op.

    Raises:
      RuntimeError: if eager execution is enabled.

    @compatibility(eager)
    Only for graph execution.
    @end_compatibility
    """
    if context.in_eager_mode():
      raise RuntimeError("Evaluator.run_evaluation() not supported when "
                         "eager execution is enabled.")
    sess = sess or ops.get_default_session()
    sess.run(init_op)
    try:
      while True:
        sess.run(call_op)
    except errors_impl.OutOfRangeError:
      pass
    return sess.run(results_op)
Пример #18
0
  def test_averagepooling_2d(self):
    testing_utils.layer_test(
        keras.layers.AveragePooling2D,
        kwargs={'strides': (2, 2),
                'padding': 'same',
                'pool_size': (2, 2)},
        input_shape=(3, 5, 6, 4))
    testing_utils.layer_test(
        keras.layers.AveragePooling2D,
        kwargs={'strides': (2, 2),
                'padding': 'valid',
                'pool_size': (3, 3)},
        input_shape=(3, 5, 6, 4))

    # This part of the test can only run on GPU but doesn't appear
    # to be properly assigned to a GPU when running in eager mode.
    if not context.in_eager_mode():
      # Only runs on GPU with CUDA, channels_first is not supported on CPU.
      # TODO(b/62340061): Support channels_first on CPU.
      if test.is_gpu_available(cuda_only=True):
        testing_utils.layer_test(
            keras.layers.AveragePooling2D,
            kwargs={
                'strides': (1, 1),
                'padding': 'valid',
                'pool_size': (2, 2),
                'data_format': 'channels_first'
            },
            input_shape=(3, 4, 5, 6))
Пример #19
0
  def variables(self):
    """A list of variables which encode the current state of `Optimizer`.

    Includes slot variables and additional global variables created by the
    optimizer in the current default graph.

    Returns:
      A list of variables.
    """
    executing_eagerly = context.in_eager_mode()
    current_graph = ops.get_default_graph()

    def _from_current_graph(variable):
      if executing_eagerly:
        # No variable.op in eager mode. We don't expect lots of eager graphs,
        # but behavior should be consistent with graph mode.
        return variable._container_prefix == current_graph._container_prefix  # pylint: disable=protected-access
      else:
        return variable.op.graph is current_graph

    optimizer_variables = [v for v in self._non_slot_variables()
                           if _from_current_graph(v)]
    for _, variable_dict in self._slots.items():
      for _, slot_for_variable in variable_dict.items():
        if _from_current_graph(slot_for_variable):
          optimizer_variables.append(slot_for_variable)
    # Sort variables by name so that the return is deterministic.
    return sorted(optimizer_variables, key=lambda v: v.name)
Пример #20
0
  def __init__(self,
               logdir,
               max_queue=10,
               flush_secs=120,
               filename_suffix=""):
    """Summary writer for TensorBoard, compatible with eager execution.

    If necessary, multiple instances of `SummaryWriter` can be created, with
    distinct `logdir`s and `name`s. Each `SummaryWriter` instance will retain
    its independent `global_step` counter and data writing destination.

    Example:
    ```python
    writer = tfe.SummaryWriter("my_model")

    # ... Code that sets up the model and data batches ...

    for _ in xrange(train_iters):
      loss = model.train_batch(batch)
      writer.scalar("loss", loss)
      writer.step()
    ```

    Args:
      logdir: Directory in which summary files will be written.
      max_queue: Number of summary items to buffer before flushing to
        filesystem. If 0, summaries will be flushed immediately.
      flush_secs: Number of secondsbetween forced commits to disk.
      filename_suffix: Suffix of the event protobuf files in which the summary
        data are stored.

    Raises:
      ValueError: If this constructor is called not under eager execution.
    """
    # TODO(apassos, ashankar): Make this class and the underlying
    # contrib.summary_ops compatible with graph model and remove this check.
    if not context.in_eager_mode():
      raise ValueError(
          "Use of SummaryWriter is currently supported only with eager "
          "execution enabled. File an issue at "
          "https://github.com/tensorflow/tensorflow/issues/new to express "
          "interest in fixing this.")

    # TODO(cais): Consider adding name keyword argument, which if None or empty,
    # will register the global global_step that training_util.get_global_step()
    # can find.
    with context.device(self._CPU_DEVICE):
      self._name = uuid.uuid4().hex
      self._global_step = 0
      self._global_step_tensor = variable_scope.get_variable(
          "global_step/summary_writer/" + self._name,
          shape=[], dtype=dtypes.int64,
          initializer=init_ops.zeros_initializer())
      self._global_step_dirty = False
      self._resource = gen_summary_ops.summary_writer(shared_name=self._name)
      gen_summary_ops.create_summary_file_writer(
          self._resource, logdir, max_queue, flush_secs, filename_suffix)
      # Delete the resource when this object is deleted
      self._resource_deleter = resource_variable_ops.EagerResourceDeleter(
          handle=self._resource, handle_device=self._CPU_DEVICE)
Пример #21
0
def _convert_to_graph_constant(value, dtype=None, name=None, as_ref=False):
  """Captures a tfe Tensor while building a graph mode function.

  Creates a placeholder to pass the tensor as an argument.

  Arguments:
    value: A tfe.Tensor object
    dtype: The datatype of the value produced by the node in the graph.
    name:  Name of the node in the graph.
    as_ref: Ignored (required by register_tensor_conversion_function).

  Returns:
    A placeholder which will, at runtime, have the value of this tensor.

  Raises:
    ValueError: if called outside a defun context.
  """
  if context.in_eager_mode():
    return value
  _ = as_ref
  tensor_map = _scoped_captures.tensors
  if tensor_map is None:
    raise ValueError(
        "Trying to use tfe.Tensor objects in a graph outside graph mode. "
        "To build a graph use tfe.defun or tfe.make_template.")
  captured_value = tensor_map.get(ops.tensor_id(value), None)
  if captured_value is None:
    captured_value = graph_placeholder(
        dtype=dtype or value.dtype, shape=value.shape, name=name)
    if captured_value.dtype == dtypes.resource:
      captured_value._handle_data = value._handle_data  # pylint: disable=protected-access
    tensor_map[ops.tensor_id(value)] = (value, captured_value)
  else:
    captured_value = captured_value[1]
  return captured_value
Пример #22
0
def summary_writer_initializer_op():
  """Graph-mode only. Returns the list of ops to create all summary writers."""
  if context.in_eager_mode():
    raise RuntimeError(
        "tf.contrib.summary.summary_writer_initializer_op is only "
        "supported in graph mode.")
  return ops.get_collection(_SUMMARY_WRITER_INIT_COLLECTION_NAME)
Пример #23
0
def global_step(sess, global_step_tensor):
  """Small helper to get the global step.

  ```python
  # Creates a variable to hold the global_step.
  global_step_tensor = tf.Variable(10, trainable=False, name='global_step')
  # Creates a session.
  sess = tf.Session()
  # Initializes the variable.
  print('global_step: %s' % tf.train.global_step(sess, global_step_tensor))

  global_step: 10
  ```

  Args:
    sess: A TensorFlow `Session` object.
    global_step_tensor:  `Tensor` or the `name` of the operation that contains
      the global step.

  Returns:
    The global step value.
  """
  if context.in_eager_mode():
    return int(global_step_tensor.numpy())
  return int(sess.run(global_step_tensor))
Пример #24
0
  def testMultiIONetworkbuilding(self):
    input_a = network_layers.Input(shape=(32,))
    input_b = network_layers.Input(shape=(16,))
    a = core_layers.Dense(16)(input_a)

    class AddLayer(base_layers.Layer):

      def call(self, inputs):
        return inputs[0] + inputs[1]

      def compute_output_shape(self, input_shape):
        return input_shape[0]

    c = AddLayer()([a, input_b])  # pylint: disable=not-callable
    c = core_layers.Dense(2)(c)

    network = network_layers.GraphNetwork([input_a, input_b], [a, c])
    if context.in_eager_mode():
      a_val = constant_op.constant(
          np.random.random((10, 32)).astype('float32'))
      b_val = constant_op.constant(
          np.random.random((10, 16)).astype('float32'))
      outputs = network([a_val, b_val])
      self.assertEqual(len(outputs), 2)
      self.assertEqual(outputs[0].shape.as_list(), [10, 16])
      self.assertEqual(outputs[1].shape.as_list(), [10, 2])
Пример #25
0
  def __init__(self, dataset):
    """Creates a new iterator over the given dataset.

    For example:
    ```python
    dataset = tf.contrib.data.Dataset.range(4)
    for x in Iterator(dataset):
      print(x)
    ```

    Args:
      dataset: A `tf.contrib.data.Dataset` object.

    Raises:
      RuntimeError: When invoked without eager execution enabled.
    """

    if not context.in_eager_mode():
      raise RuntimeError(
          "{} objects only make sense when eager execution is enabled".format(
              type(self)))
    ds_variant = dataset._as_variant_tensor()  # pylint: disable=protected-access
    self._output_types = dataset.output_types
    self._flat_output_types = nest.flatten(dataset.output_types)
    self._flat_output_shapes = nest.flatten(dataset.output_shapes)
    self._resource = gen_dataset_ops.iterator(
        container="",
        shared_name=_iterator_shared_name(),
        output_types=self._flat_output_types,
        output_shapes=self._flat_output_shapes)
    gen_dataset_ops.make_iterator(ds_variant, self._resource)
Пример #26
0
def _convert_to_graph_tensor(value, dtype=None, name=None, as_ref=False):
  """Captures a Tensor while building a graph mode function.

  Arguments:
    value: A Tensor object.
    dtype: The datatype of the value produced by the node in the graph.
    name:  str, Name of the node in the graph.
    as_ref: Ignored (required by register_tensor_conversion_function).

  Returns:
    Returns a constant (the current value of the tensor) if capturing
    is not enabled. A placeholder which will have the value of the
    tensor at runtime otherwise.
  """
  del as_ref  # Unused.

  if context.in_eager_mode():
    return value

  default_graph = ops.get_default_graph()
  if not default_graph.building_function:
    return value

  tensor_map = _scoped_captures.tensors
  if tensor_map is None:
    # Capturing is not enabled.
    return constant_op.constant(value.numpy())
  if type(value) == ops.Tensor and value.graph is default_graph:
    # The tensor has already been converted and captured. The type check
    # is intentional: we are checking that value is a Tensor and not an
    # EagerTensor.
    return value
  return capture_value(tensor_map, value, dtype, name)
Пример #27
0
 def decorator(hp_fn, registration_name=None):
   """Registers & returns hp_fn with registration_name or default name."""
   hp_name = registration_name or default_name(hp_fn)
   if hp_name in _HPARAMS and not context.in_eager_mode():
     raise LookupError("HParams set %s already registered." % hp_name)
   _HPARAMS[hp_name] = hp_fn
   return hp_fn
Пример #28
0
  def testBasic(self):
    for i, dtype in enumerate([dtypes.half, dtypes.float32, dtypes.float64]):
      # Note that we name the variables uniquely here since the variables don't
      # seem to be getting deleted at the end of the loop.
      var0 = resource_variable_ops.ResourceVariable([1.0, 2.0], dtype=dtype,
                                                    name='a_%d' % i)
      var1 = resource_variable_ops.ResourceVariable([3.0, 4.0], dtype=dtype,
                                                    name='b_%d' % i)
      def loss(v0, v1):
        return 5 * v0 + 3 * v1
      # Note that for eager execution, minimize expects a function instead of a
      # Tensor.
      cost = loss if context.in_eager_mode() else loss(var0, var1)
      global_step = resource_variable_ops.ResourceVariable(
          array_ops.zeros([], dtypes.int64), name='global_step_%d' % i)
      sgd_op = gradient_descent.GradientDescentOptimizer(3.0)

      self.evaluate(variables.global_variables_initializer())
      # Fetch params to validate initial values
      self.assertAllClose([1.0, 2.0], self.evaluate(var0))
      self.assertAllClose([3.0, 4.0], self.evaluate(var1))
      # Run 1 step of sgd through optimizer
      opt_op = sgd_op.minimize(cost, global_step, [var0, var1])
      self.evaluate(opt_op)
      # Validate updated params
      self.assertAllClose([-14., -13.], self.evaluate(var0))
      self.assertAllClose([-6., -5.], self.evaluate(var1))
Пример #29
0
def assert_rank_in(
    x, ranks, data=None, summarize=None, message=None, name=None):
  """Assert `x` has rank in `ranks`.

  Example of adding a dependency to an operation:

  ```python
  with tf.control_dependencies([tf.assert_rank_in(x, (2, 4))]):
    output = tf.reduce_sum(x)
  ```

  Args:
    x:  Numeric `Tensor`.
    ranks:  Iterable of scalar `Tensor` objects.
    data:  The tensors to print out if the condition is False.  Defaults to
      error message and first few entries of `x`.
    summarize: Print this many entries of each tensor.
    message: A string to prefix to the default message.
    name: A name for this operation (optional).
      Defaults to "assert_rank_in".

  Returns:
    Op raising `InvalidArgumentError` unless rank of `x` is in `ranks`.
    If static checks determine `x` has matching rank, a `no_op` is returned.

  Raises:
    ValueError:  If static checks determine `x` has mismatched rank.
  """
  with ops.name_scope(
      name, 'assert_rank_in', (x,) + tuple(ranks) + tuple(data or [])):
    x = ops.convert_to_tensor(x, name='x')
    ranks = tuple([ops.convert_to_tensor(rank, name='rank') for rank in ranks])
    message = message or ''

    if context.in_eager_mode():
      name = ''
    else:
      name = x.name

    if data is None:
      data = [
          message, 'Tensor %s must have rank in' % name
      ] + list(ranks) + [
          'Received shape: ', array_ops.shape(x)
      ]

    try:
      assert_op = _assert_ranks_condition(x, ranks, _static_rank_in,
                                          _dynamic_rank_in, data, summarize)

    except ValueError as e:
      if e.args[0] == 'Static rank condition failed':
        raise ValueError(
            '%s.  Tensor %s must have rank in %s.  Received rank %d, '
            'shape %s' % (message, name, e.args[2], e.args[1], x.get_shape()))
      else:
        raise

  return assert_op
Пример #30
0
def assert_rank(x, rank, data=None, summarize=None, message=None, name=None):
  """Assert `x` has rank equal to `rank`.

  Example of adding a dependency to an operation:

  ```python
  with tf.control_dependencies([tf.assert_rank(x, 2)]):
    output = tf.reduce_sum(x)
  ```

  Args:
    x:  Numeric `Tensor`.
    rank:  Scalar integer `Tensor`.
    data:  The tensors to print out if the condition is False.  Defaults to
      error message and first few entries of `x`.
    summarize: Print this many entries of each tensor.
    message: A string to prefix to the default message.
    name: A name for this operation (optional).  Defaults to "assert_rank".

  Returns:
    Op raising `InvalidArgumentError` unless `x` has specified rank.
    If static checks determine `x` has correct rank, a `no_op` is returned.

  Raises:
    ValueError:  If static checks determine `x` has wrong rank.
  """
  with ops.name_scope(name, 'assert_rank', (x, rank) + tuple(data or [])):
    x = ops.convert_to_tensor(x, name='x')
    rank = ops.convert_to_tensor(rank, name='rank')
    message = message or ''

    static_condition = lambda actual_rank, given_rank: actual_rank == given_rank
    dynamic_condition = math_ops.equal

    if context.in_eager_mode():
      name = ''
    else:
      name = x.name

    if data is None:
      data = [
          message,
          'Tensor %s must have rank' % name, rank, 'Received shape: ',
          array_ops.shape(x)
      ]

    try:
      assert_op = _assert_rank_condition(x, rank, static_condition,
                                         dynamic_condition, data, summarize)

    except ValueError as e:
      if e.args[0] == 'Static rank condition failed':
        raise ValueError(
            '%s.  Tensor %s must have rank %d.  Received rank %d, shape %s' %
            (message, name, e.args[2], e.args[1], x.get_shape()))
      else:
        raise

  return assert_op
Пример #31
0
def _num_present(losses, weights, per_batch=False):
    """Computes the number of elements in the loss function induced by `weights`.

  A given weights tensor induces different numbers of usable elements in the
  `losses` tensor. The `weights` tensor is broadcast across `losses` for all
  possible dimensions. For example, if `losses` is a tensor of dimension
  `[4, 5, 6, 3]` and `weights` is a tensor of shape `[4, 5]`, then `weights` is,
  in effect, tiled to match the shape of `losses`. Following this effective
  tile, the total number of present elements is the number of non-zero weights.

  Args:
    losses: `Tensor` of shape `[batch_size, d1, ... dN]`.
    weights: `Tensor` of shape `[]`, `[batch_size]` or
      `[batch_size, d1, ... dK]`, where K < N.
    per_batch: Whether to return the number of elements per batch or as a sum
      total.

  Returns:
    The number of present (non-zero) elements in the losses tensor. If
      `per_batch` is `True`, the value is returned as a tensor of size
      `[batch_size]`. Otherwise, a single scalar tensor is returned.
  """
    if ((isinstance(weights, float) and weights != 0.0)
            or (context.in_eager_mode() and weights._rank() == 0  # pylint: disable=protected-access
                and not math_ops.equal(weights, 0.0))):
        return _num_elements(losses)
    with ops.name_scope(None, "num_present", (losses, weights)) as scope:
        weights = math_ops.to_float(weights)
        present = array_ops.where(math_ops.equal(weights, 0.0),
                                  array_ops.zeros_like(weights),
                                  array_ops.ones_like(weights))
        present = weights_broadcast_ops.broadcast_weights(present, losses)
        if per_batch:
            return math_ops.reduce_sum(present,
                                       axis=math_ops.range(
                                           1, array_ops.rank(present)),
                                       keepdims=True,
                                       name=scope)
        return math_ops.reduce_sum(present, name=scope)
Пример #32
0
def _convert_to_graph_tensor(value, dtype=None, name=None, as_ref=False):
    """Captures a Tensor while building a graph mode function.

  Arguments:
    value: A Tensor object.
    dtype: The datatype of the value produced by the node in the graph.
    name:  Name of the node in the graph.
    as_ref: Ignored (required by register_tensor_conversion_function).

  Returns:
    Returns a constant (the current value of the tensor) if capturing
    is not enabled. A placeholder which will have the value of the
    tensor at runtime otherwise.
  """
    if context.in_eager_mode():
        return value
    _ = as_ref
    tensor_map = _scoped_captures.tensors
    if tensor_map is None:
        # Capturing is not enabled.
        return constant_op.constant(value.numpy())
    return capture_value(tensor_map, value, dtype, name)
Пример #33
0
def assert_non_negative(x, data=None, summarize=None, message=None, name=None):
  """Assert the condition `x >= 0` holds element-wise.

  Example of adding a dependency to an operation:

  ```python
  with tf.control_dependencies([tf.assert_non_negative(x)]):
    output = tf.reduce_sum(x)
  ```

  Non-negative means, for every element `x[i]` of `x`, we have `x[i] >= 0`.
  If `x` is empty this is trivially satisfied.

  Args:
    x:  Numeric `Tensor`.
    data:  The tensors to print out if the condition is False.  Defaults to
      error message and first few entries of `x`.
    summarize: Print this many entries of each tensor.
    message: A string to prefix to the default message.
    name: A name for this operation (optional).
      Defaults to "assert_non_negative".

  Returns:
    Op raising `InvalidArgumentError` unless `x` is all non-negative.
  """
  message = message or ''
  with ops.name_scope(name, 'assert_non_negative', [x, data]):
    x = ops.convert_to_tensor(x, name='x')
    if data is None:
      if context.in_eager_mode():
        name = _shape_and_dtype_str(x)
      else:
        name = x.name
      data = [
          message,
          'Condition x >= 0 did not hold element-wise:',
          'x (%s) = ' % name, x]
    zero = ops.convert_to_tensor(0, dtype=x.dtype)
    return assert_less_equal(zero, x, data=data, summarize=summarize)
Пример #34
0
    def start_queue_runners(self, sess, queue_runners=None):
        """Start threads for `QueueRunners`.

    Note that the queue runners collected in the graph key `QUEUE_RUNNERS`
    are already started automatically when you create a session with the
    supervisor, so unless you have non-collected queue runners to start
    you do not need to call this explicitly.

    Args:
      sess: A `Session`.
      queue_runners: A list of `QueueRunners`. If not specified, we'll use the
        list of queue runners gathered in the graph under the key
        `GraphKeys.QUEUE_RUNNERS`.

    Returns:
      The list of threads started for the `QueueRunners`.

    Raises:
      RuntimeError: If called with eager execution enabled.

    @compatibility(eager)
    Queues are not compatible with eager execution. To ingest data when eager
    execution is enabled, use the `tf.data` API.
    @end_compatibility
    """
        if context.in_eager_mode():
            raise RuntimeError(
                "Queues are not compatible with eager execution.")
        if queue_runners is None:
            queue_runners = self._graph.get_collection(
                ops.GraphKeys.QUEUE_RUNNERS)
        threads = []
        for qr in queue_runners:
            threads.extend(
                qr.create_threads(sess,
                                  coord=self._coord,
                                  daemon=True,
                                  start=True))
        return threads
Пример #35
0
def create_global_step(graph=None):
    """Create global step tensor in graph.

  Args:
    graph: The graph in which to create the global step tensor. If missing,
      use default graph.

  Returns:
    Global step tensor.

  Raises:
    ValueError: if global step tensor is already defined.
  """
    graph = graph or ops.get_default_graph()
    if get_global_step(graph) is not None:
        raise ValueError('"global_step" already exists.')
    # Create in proper graph and base name_scope.
    with graph.as_default() as g, g.name_scope(None):
        if context.in_eager_mode():
            with ops.device('cpu:0'):
                return variable_scope.get_variable(
                    ops.GraphKeys.GLOBAL_STEP,
                    shape=[],
                    dtype=dtypes.int64,
                    initializer=init_ops.zeros_initializer(),
                    trainable=False,
                    collections=[
                        ops.GraphKeys.GLOBAL_VARIABLES,
                        ops.GraphKeys.GLOBAL_STEP
                    ])
        return variable_scope.get_variable(
            ops.GraphKeys.GLOBAL_STEP,
            shape=[],
            dtype=dtypes.int64,
            initializer=init_ops.zeros_initializer(),
            trainable=False,
            collections=[
                ops.GraphKeys.GLOBAL_VARIABLES, ops.GraphKeys.GLOBAL_STEP
            ])
Пример #36
0
 def _set_restore_on_create(self, save_path, map_func, user_map_func,
                            existing_variables_by_checkpoint_name):
   """If necessary, request deferred restorations of variables."""
   checkpoint_reader = checkpoint_utils.load_checkpoint(save_path)
   checkpointed_variables_to_restore = {}
   for checkpoint_name, _ in checkpoint_utils.list_variables(save_path):
     if checkpoint_name in existing_variables_by_checkpoint_name:
       # This variable was already created and restored.
       continue
     # Save the variable for later restoration in a custom getter.
     checkpointed_variables_to_restore[checkpoint_name] = (
         checkpoint_reader.get_tensor(checkpoint_name))
   # Only set a deferred restoration if there are checkpoint variables which
   # have not been assigned to existing variables. Note that this loses out on
   # some opportunity for error checking, but avoids creating
   # _DeferredRestoration objects once a Network has been built (so that
   # restoring in a loop does not take increasing amounts of memory).
   if checkpointed_variables_to_restore:
     if context.in_eager_mode():
       sess = None
     else:
       sess = ops.get_default_session()
     # We need a name for error messages. If we haven't been added to another
     # Network yet, we're top-level.
     self._finalize_name(False)
     self._set_scope()
     # Save a record of this restoration for use in the custom getter.
     deferred_restoration = _DeferredRestoration(
         map_func=map_func,
         map_func_is_user=(user_map_func is not None),
         checkpointed_variables_to_restore=checkpointed_variables_to_restore,
         restored_variables={},
         session=sess,
         network_name=self.name,
         network_scope_name=self.scope_name)
     self._deferred_restorations.append(deferred_restoration)
     # Add the deferred registration to non-Network children, and request that
     # Networks propagate the request to their children.
     self._add_deferred_restoration(deferred_restoration)
Пример #37
0
    def model_fn_body_sharded(self, sharded_features):
        """Mixture-of-experts models will override this function.

    Compute model body on all datashards.

    Args:
      sharded_features: map from string to list of Tensors each with shape
         [batch, ?, ?, body_input_size]

    Returns:
      sharded_body_output:
          a list of Tensors, each with shape [batch, O, P, body_output_size]
      extra_loss: a Scalar.
    """
        with tf.name_scope("model"):
            datashard_to_features = [{
                k: v[d]
                for k, v in six.iteritems(sharded_features)
            } for d in xrange(self._num_datashards)]
            output = self._data_parallelism(
                _with_timing(self.model_fn_body,
                             "model_fn_body",
                             silent=context.in_eager_mode()),
                datashard_to_features)
            if isinstance(output, tuple):
                losses_sharded = output[1]
                if isinstance(losses_sharded[0], dict):
                    loss = {}
                    for k in losses_sharded[0].keys():
                        k_loss_sharded = [
                            losses[k] for losses in losses_sharded
                        ]
                        loss[k] = tf.reduce_mean(k_loss_sharded)
                else:
                    loss = {"extra": tf.reduce_mean(losses_sharded)}
                output = output[0]
            else:
                loss = {"extra": 0.0}
            return output, loss
Пример #38
0
    def __init__(self, dataset):
        """Creates a new iterator over the given dataset.

    For example:
    ```python
    dataset = tf.data.Dataset.range(4)
    for x in Iterator(dataset):
      print(x)
    ```

    Tensors produced will be placed on the device on which this iterator object
    was created.

    Args:
      dataset: A `tf.data.Dataset` object.

    Raises:
      RuntimeError: When invoked without eager execution enabled.
    """

        if not context.in_eager_mode():
            raise RuntimeError(
                "{} objects can only be used when eager execution is enabled, use "
                "tf.data.Dataset.make_iterator or "
                "tf.data.Dataset.make_one_shot_iterator for graph construction"
                .format(type(self)))
        with ops.device("/device:CPU:0"):
            ds_variant = dataset._as_variant_tensor()  # pylint: disable=protected-access
            self._output_types = dataset.output_types
            self._flat_output_types = nest.flatten(dataset.output_types)
            self._flat_output_shapes = nest.flatten(dataset.output_shapes)
            self._resource = gen_dataset_ops.iterator(
                container="",
                shared_name=_iterator_shared_name(),
                output_types=self._flat_output_types,
                output_shapes=self._flat_output_shapes)
            gen_dataset_ops.make_iterator(ds_variant, self._resource)
        self._device = context.context().device_name
Пример #39
0
def initialize(
        graph=None,  # pylint: disable=redefined-outer-name
        session=None):
    """Initializes summary writing for graph execution mode.

  This helper method provides a higher-level alternative to using
  @{tf.contrib.summary.summary_writer_initializer_op} and
  @{tf.contrib.summary.graph}.

  Most users will also want to call @{tf.train.create_global_step}
  which can happen before or after this function is called.

  Args:
    graph: A @{tf.Graph} or @{tf.GraphDef} to output to the writer.
      This function will not write the default graph by default. When
      writing to an event log file, the associated step will be zero.
    session: So this method can call @{tf.Session.run}. This defaults
      to @{tf.get_default_session}.

  Raises:
    RuntimeError: If  the current thread has no default
      @{tf.contrib.summary.SummaryWriter}.
    ValueError: If session wasn't passed and no default session.
  """
    if context.in_eager_mode():
        return
    if context.context().summary_writer_resource is None:
        raise RuntimeError("No default tf.contrib.summary.SummaryWriter found")
    if session is None:
        session = ops.get_default_session()
        if session is None:
            raise ValueError(
                "session must be passed if no default session exists")
    session.run(summary_writer_initializer_op())
    if graph is not None:
        data = _serialize_graph(graph)
        x = array_ops.placeholder(dtypes.string)
        session.run(_graph(x, 0), feed_dict={x: data})
Пример #40
0
    def testMinimizeSparseResourceVariable(self):
        for dtype in [dtypes.half, dtypes.float32, dtypes.float64]:
            var0 = resource_variable_ops.ResourceVariable([[1.0, 2.0]],
                                                          dtype=dtype)

            # pylint: disable=cell-var-from-loop
            def loss():
                x = constant_op.constant([[4.0], [5.0]], dtype=dtype)
                pred = math_ops.matmul(
                    embedding_ops.embedding_lookup([var0], [0]), x)
                return pred * pred

            # pylint: enable=cell-var-from-loop

            opt = momentum_lib.MomentumOptimizer(learning_rate=1.0,
                                                 momentum=0.0)
            sgd_op = opt.minimize(loss if context.in_eager_mode() else loss())
            self.evaluate(variables.global_variables_initializer())
            # Run 1 step of sgd
            self.evaluate(sgd_op)
            # Validate updated params
            self.assertAllCloseAccordingToType([[-111, -138]],
                                               self.evaluate(var0))
Пример #41
0
def _GatherGrad(op, grad):
  """Gradient for gather op."""
  # Build appropriately shaped IndexedSlices
  # Walk graph back until the original handle is found.
  # TODO(apassos): more robust way of getting the shape.
  # TODO(apassos): implement this for EAGER mode.
  if context.in_eager_mode():
    dense_shape = gen_resource_variable_ops.variable_shape(op.inputs[0])
    return (ops.IndexedSlices(grad,
                              op.inputs[1],
                              dense_shape=dense_shape),
            None)
  handle = op.inputs[0]
  while handle.op.type != "VarHandleOp":
    handle = handle.op.inputs[0]
  params_shape = ops.convert_to_tensor(
      tensor_shape.TensorShape(handle.op.get_attr("shape")))
  indices = op.inputs[1]
  size = array_ops.expand_dims(array_ops.size(indices), 0)
  values_shape = array_ops.concat([size, params_shape[1:]], 0)
  values = array_ops.reshape(grad, values_shape)
  indices = array_ops.reshape(indices, size)
  return [ops.IndexedSlices(values, indices, params_shape), None]
Пример #42
0
    def test_global_variables(self):
        # Make sure global_variables are created.
        with variable_scope.variable_scope("foo"):
            # Create two templates with the same name, ensure scopes are made unique.
            ta = template.make_template("bar", variable_scoped_function, True)
            if context.in_eager_mode():
                tb = template.make_template("s",
                                            function_with_side_create,
                                            trainable=False)
            else:
                tb = template.make_template("s",
                                            function_with_create,
                                            trainable=False)

        # Initially there are not variables created.
        self.assertEqual([], list(ta.global_variables))
        self.assertEqual([], list(tb.global_variables))
        # After calling there are variables created.
        ta()
        tb()
        # Ensure we can get the scopes before either template is actually called.
        self.assertEqual(1, len(ta.global_variables))
        self.assertEqual(2, len(tb.global_variables))
Пример #43
0
    def to_proto(self, export_scope=None):
        """Converts a `ResourceVariable` to a `VariableDef` protocol buffer.

    Args:
      export_scope: Optional `string`. Name scope to remove.

    Raises:
      RuntimeError: If run in EAGER mode.

    Returns:
      A `VariableDef` protocol buffer, or `None` if the `Variable` is not
      in the specified name scope.
    """
        if context.in_eager_mode():
            raise RuntimeError("to_proto not supported in EAGER mode.")
        if export_scope is None or self.handle.name.startswith(export_scope):
            var_def = variable_pb2.VariableDef()
            var_def.variable_name = ops.strip_name_scope(
                self.handle.name, export_scope)
            if self._initial_value is not None:
                # This is inside an if-statement for backwards compatibility, since
                # self._initial_value might be None for variables constructed from old
                # protos.
                var_def.initial_value_name = ops.strip_name_scope(
                    self._initial_value.name, export_scope)
            var_def.initializer_name = ops.strip_name_scope(
                self.initializer.name, export_scope)
            if self._cached_value is not None:
                var_def.snapshot_name = ops.strip_name_scope(
                    self._cached_value.name, export_scope)
            var_def.is_resource = True
            if self._save_slice_info:
                var_def.save_slice_info_def.MergeFrom(
                    self._save_slice_info.to_proto(export_scope=export_scope))
            return var_def
        else:
            return None
Пример #44
0
    def all_metric_results(self, summary_logdir=None):
        """Computes results for all contained metrics.

    Args:
      summary_logdir: An optional string. If specified, metric results
        will be written as summaries to this directory.

    Returns:
      A `dict` mapping string names to tensors.
    """
        if summary_logdir is None:
            with summary_ops.never_record_summaries():
                return self._all_metric_results()
        else:

            def f():
                with summary_ops.create_file_writer(summary_logdir).as_default(
                ), summary_ops.always_record_summaries():
                    return self._all_metric_results()

            if context.in_eager_mode():
                return f()
            else:
                return function.defun(f)()
Пример #45
0
def _convert_to_graph_constant(value, dtype=None, name=None, as_ref=False):
    """Captures a tfe Tensor while building a graph mode function.

  Creates a placeholder to pass the tensor as an argument.

  Arguments:
    value: A tfe.Tensor object
    dtype: The datatype of the value produced by the node in the graph.
    name:  Name of the node in the graph.
    as_ref: Ignored (required by register_tensor_conversion_function).

  Returns:
    A placeholder which will, at runtime, have the value of this tensor.

  Raises:
    ValueError: if called outside a defun context.
  """
    if context.in_eager_mode():
        return value
    _ = as_ref
    tensor_map = _scoped_captures.tensors
    if tensor_map is None:
        raise ValueError(
            "Trying to use tfe.Tensor objects in a graph outside graph mode. "
            "To build a graph use tfe.defun or tfe.make_template.")
    captured_value = tensor_map.get(ops.tensor_id(value), None)
    if captured_value is None:
        captured_value = graph_placeholder(dtype=dtype or value.dtype,
                                           shape=value.shape,
                                           name=name)
        if captured_value.dtype == dtypes.resource:
            captured_value._handle_data = value._handle_data  # pylint: disable=protected-access
        tensor_map[ops.tensor_id(value)] = (value, captured_value)
    else:
        captured_value = captured_value[1]
    return captured_value
Пример #46
0
    def test_zero_padding_3d(self):
        num_samples = 2
        stack_size = 2
        input_len_dim1 = 4
        input_len_dim2 = 5
        input_len_dim3 = 3

        inputs = np.ones((num_samples, input_len_dim1, input_len_dim2,
                          input_len_dim3, stack_size))

        # basic test
        with self.test_session(use_gpu=True):
            testing_utils.layer_test(keras.layers.ZeroPadding3D,
                                     kwargs={'padding': (2, 2, 2)},
                                     input_shape=inputs.shape)

        # correctness test
        with self.test_session(use_gpu=True):
            layer = keras.layers.ZeroPadding3D(padding=(2, 2, 2))
            layer.build(inputs.shape)
            output = layer(keras.backend.variable(inputs))
            if context.in_eager_mode():
                np_output = output.numpy()
            else:
                np_output = keras.backend.eval(output)
            for offset in [0, 1, -1, -2]:
                np.testing.assert_allclose(np_output[:, offset, :, :, :], 0.)
                np.testing.assert_allclose(np_output[:, :, offset, :, :], 0.)
                np.testing.assert_allclose(np_output[:, :, :, offset, :], 0.)
            np.testing.assert_allclose(np_output[:, 2:-2, 2:-2, 2:-2, :], 1.)

        # test incorrect use
        with self.assertRaises(ValueError):
            keras.layers.ZeroPadding3D(padding=(1, 1))
        with self.assertRaises(ValueError):
            keras.layers.ZeroPadding3D(padding=None)
Пример #47
0
 def testNamingWithOptimizer(self):
   input_value = constant_op.constant([[3.]])
   network = MyNetwork()
   # A nuisance Network using the same optimizer. Its slot variables should not
   # go in the checkpoint, since it is never depended on.
   other_network = MyNetwork()
   optimizer = CheckpointableAdam(0.001)
   root_checkpointable = Root(optimizer=optimizer, network=network)
   if context.in_eager_mode():
     optimizer.minimize(
         lambda: network(input_value),
         global_step=root_checkpointable.global_step)
     optimizer.minimize(
         lambda: other_network(input_value),
         global_step=root_checkpointable.global_step)
   else:
     train_op = optimizer.minimize(
         network(input_value), global_step=root_checkpointable.global_step)
     optimizer.minimize(
         other_network(input_value),
         global_step=root_checkpointable.global_step)
     self.evaluate(variables.global_variables_initializer())
     self.evaluate(train_op)
   named_variables, serialized_graph = checkpointable._serialize_object_graph(
       root_checkpointable)
   expected_checkpoint_names = (
       # Created in the root node, so no prefix.
       "global_step",
       # No name provided to track_checkpointable(), so the position (1, after
       # the named track_checkpointable() which is 0) is used instead.
       "network/_1/kernel",
       # track_checkpointable() with a name provided, so that's used
       "network/named_dense/kernel",
       "network/named_dense/bias",
       # The optimizer creates two non-slot variables
       "optimizer/beta1_power",
       "optimizer/beta2_power",
       # Slot variables
       "network/_1/kernel/_OPTIMIZER_SLOT/optimizer/m",
       "network/_1/kernel/_OPTIMIZER_SLOT/optimizer/v",
       "network/named_dense/kernel/_OPTIMIZER_SLOT/optimizer/m",
       "network/named_dense/kernel/_OPTIMIZER_SLOT/optimizer/v",
       "network/named_dense/bias/_OPTIMIZER_SLOT/optimizer/m",
       "network/named_dense/bias/_OPTIMIZER_SLOT/optimizer/v",
   )
   six.assertCountEqual(self, expected_checkpoint_names,
                        named_variables.keys())
   # Check that we've mapped to the right variable objects (not exhaustive)
   self.assertEqual("global_step:0", named_variables["global_step"].name)
   self.assertEqual("my_network/checkpointable_dense_layer_1/kernel:0",
                    named_variables["network/_1/kernel"].name)
   self.assertEqual("my_network/checkpointable_dense_layer/kernel:0",
                    named_variables["network/named_dense/kernel"].name)
   self.assertEqual("beta1_power:0",
                    named_variables["optimizer/beta1_power"].name)
   self.assertEqual("beta2_power:0",
                    named_variables["optimizer/beta2_power"].name)
   # Spot check the generated protocol buffers.
   self.assertEqual(0, serialized_graph.nodes[0].children[0].local_uid)
   self.assertEqual("optimizer",
                    serialized_graph.nodes[0].children[0].local_name)
   optimizer_node = serialized_graph.nodes[serialized_graph.nodes[0].children[
       0].node_id]
   self.assertEqual("beta1_power", optimizer_node.variables[0].local_name)
   self.assertEqual("beta1_power", optimizer_node.variables[0].full_name)
   self.assertEqual(
       "kernel", optimizer_node.slot_variables[0].original_variable_local_name)
   original_variable_owner = serialized_graph.nodes[
       optimizer_node.slot_variables[0].original_variable_node_id]
   self.assertEqual("kernel", original_variable_owner.variables[0].local_name)
   self.assertEqual("m", optimizer_node.slot_variables[0].slot_name)
   # We strip off the :0 suffix, as variable.name-based saving does.
   self.assertEqual("my_network/checkpointable_dense_layer/kernel/Adam",
                    optimizer_node.slot_variables[0].full_name)
   self.assertEqual("my_network/checkpointable_dense_layer/kernel/Adam:0",
                    optimizer.get_slot(
                        var=named_variables["network/named_dense/kernel"],
                        name="m").name)
Пример #48
0
    def _fast_decode(self,
                     features,
                     decode_length,
                     beam_size=1,
                     top_beams=1,
                     alpha=1.0):
        """
		Fast decoding.
		Implements both greedy and beam search decoding, uses beam search iff
		beam_size > 1, otherwise beam search related arguments are ignored.
		Args:
			features: a map of string to model  features.
			decode_length: an integer.  How many additional timesteps to decode.
			beam_size: number of beams.
			top_beams: an integer. How many of the beams to return.
			alpha: Float that controls the length penalty. larger the alpha, stronger
			the preference for slonger translations.
		Returns:
			 samples: an integer `Tensor`. Top samples from the beam search
		Raises:
			NotImplementedError: If there are multiple data shards.
		"""
        if self._num_datashards != 1:
            raise NotImplementedError(
                "Fast decoding only supports a single shard.")
        dp = self._data_parallelism
        hparams = self._hparams

        inputs = features["inputs"]
        batch_size = common_layers.shape_list(inputs)[0]
        target_modality = self._problem_hparams.target_modality
        if target_modality.is_class_modality:
            decode_length = 1
        else:
            decode_length = common_layers.shape_list(inputs)[1] + decode_length

        # TODO(llion): Clean up this reshaping logic.
        inputs = tf.expand_dims(inputs, axis=1)
        if len(inputs.shape) < 5:
            inputs = tf.expand_dims(inputs, axis=4)
        s = common_layers.shape_list(inputs)
        inputs = tf.reshape(inputs, [s[0] * s[1], s[2], s[3], s[4]])
        # _shard_features called to ensure that the variable names match
        inputs = self._shard_features({"inputs": inputs})["inputs"]
        input_modality = self._problem_hparams.input_modality["inputs"]
        with tf.variable_scope(input_modality.name):
            inputs = input_modality.bottom_sharded(inputs, dp)
        with tf.variable_scope("body"):
            encoder_output, encoder_decoder_attention_bias = dp(
                self.encode,
                inputs,
                features["target_space_id"],
                hparams,
                features=features)
        encoder_output = encoder_output[0]
        encoder_decoder_attention_bias = encoder_decoder_attention_bias[0]

        if hparams.pos == "timing":
            timing_signal = common_attention.get_timing_signal_1d(
                decode_length + 1, hparams.hidden_size)

        def preprocess_targets(targets, i):
            """Performs preprocessing steps on the targets to prepare for the decoder.
			This includes:
			- Embedding the ids.
			- Flattening to 3D tensor.
			- Optionally adding timing signals.
			Args:
			targets: inputs ids to the decoder. [batch_size, 1]
			i: scalar, Step number of the decoding loop.
			Returns:
			Processed targets [batch_size, 1, hidden_dim]
			"""
            # _shard_features called to ensure that the variable names match
            targets = self._shard_features({"targets": targets})["targets"]
            with tf.variable_scope(target_modality.name):
                targets = target_modality.targets_bottom_sharded(targets,
                                                                 dp)[0]
            targets = common_layers.flatten4d3d(targets)

            # TODO(llion): Explain! Is this even needed?
            targets = tf.cond(tf.equal(i, 0), lambda: tf.zeros_like(targets),
                              lambda: targets)

            if hparams.pos == "timing":
                targets += timing_signal[:, i:i + 1]
            return targets

        decoder_self_attention_bias = (
            common_attention.attention_bias_lower_triangle(decode_length))
        if hparams.proximity_bias:
            decoder_self_attention_bias += common_attention.attention_bias_proximal(
                decode_length)

        def symbols_to_logits_fn(ids, i, cache):
            """Go from ids to logits for next symbol."""
            ids = ids[:, -1:]
            targets = tf.expand_dims(tf.expand_dims(ids, axis=2), axis=3)
            targets = preprocess_targets(targets, i)

            bias = decoder_self_attention_bias[:, :, i:i + 1, :i + 1]

            with tf.variable_scope("body"):
                body_outputs = dp(
                    self.decode,
                    targets,
                    cache["encoder_output"],
                    cache["encoder_decoder_attention_bias"],
                    bias,
                    hparams,
                    cache,
                    nonpadding=transformer._features_to_nonpadding(
                        features, "targets"))

            with tf.variable_scope(target_modality.name):
                logits = target_modality.top_sharded(body_outputs, None, dp)[0]

            return tf.squeeze(logits, axis=[1, 2, 3]), cache

        key_channels = hparams.attention_key_channels or hparams.hidden_size
        value_channels = hparams.attention_value_channels or hparams.hidden_size
        num_layers = hparams.num_decoder_layers or hparams.num_hidden_layers

        cache = {
            "layer_%d" % layer: {
                "k": tf.zeros([batch_size, 0, key_channels]),
                "v": tf.zeros([batch_size, 0, value_channels]),
            }
            for layer in range(num_layers)
        }

        # Set 2nd dim to None since it's not invariant in the tf.while_loop
        # Note: Tensor.set_shape() does not work here since it merges shape info.
        # TODO(llion); Find a more robust solution.
        # pylint: disable=protected-access
        if not context.in_eager_mode():
            for layer in cache:
                cache[layer]["k"]._shape = tf.TensorShape(
                    [None, None, key_channels])
                cache[layer]["v"]._shape = tf.TensorShape(
                    [None, None, value_channels])
        # pylint: enable=protected-access
        cache["encoder_output"] = encoder_output
        cache[
            "encoder_decoder_attention_bias"] = encoder_decoder_attention_bias

        if beam_size > 1:  # Beam Search
            target_modality = (
                self._hparams.problems[self._problem_idx].target_modality)
            vocab_size = target_modality.top_dimensionality
            initial_ids = tf.zeros([batch_size], dtype=tf.int32)
            decoded_ids, scores = beam_search.beam_search(
                symbols_to_logits_fn,
                initial_ids,
                beam_size,
                decode_length,
                vocab_size,
                alpha,
                states=cache,
                stop_early=(top_beams == 1))

            decoded_ids = decoded_ids[:, :, 1:]

            # do roulette wheel selection or inverse roulette wheel selection
            if self._hparams.roulette == "Normal" or self._hparams.roulette == "Inverse":
                if self._hparams.roulette == "Normal":
                    probabilities = tf.pow(tf.constant(2.0), scores)
                    start = 0
                else:
                    probabilities = tf.subtract(
                        tf.constant(1.0), tf.pow(tf.constant(2.0), scores))
                    start = beam_size - self._hparams.roulette_beam_size

                summ = tf.reduce_sum(probabilities)
                ex_probs = tf.divide(probabilities, summ)
                #ex_probs=tf.nn.softmax(probabilities)

                # sample a number between 0 and 1
                wheel = tf.random_uniform([1])
                upper_bound = tf.constant(0.0)

                # change this as well if using inverse
                for i in range(start, self._hparams.roulette_beam_size):
                    upper_bound = tf.add(ex_probs[:, i], upper_bound)
                    truthValue = tf.squeeze(
                        tf.logical_and(wheel >= upper_bound - ex_probs[:, i],
                                       wheel <= upper_bound))
                    decoded_ids, scores, i = tf.cond(
                        truthValue, lambda:
                        (decoded_ids[:, i, :], scores[:, i], beam_size),
                        lambda: (decoded_ids, scores, i))

        else:  # Greedy

            def inner_loop(i, next_id, decoded_ids, cache):
                logits, cache = symbols_to_logits_fn(next_id, i, cache)
                temperature = (0.0 if hparams.sampling_method == "argmax" else
                               hparams.sampling_temp)
                next_id = tf.expand_dims(common_layers.sample_with_temperature(
                    logits, temperature),
                                         axis=1)
                decoded_ids = tf.concat([decoded_ids, next_id], axis=1)
                return i + 1, next_id, decoded_ids, cache

            decoded_ids = tf.zeros([batch_size, 0], dtype=tf.int64)
            scores = None
            next_id = tf.zeros([batch_size, 1], dtype=tf.int64)
            _, _, decoded_ids, _ = tf.while_loop(
                # TODO(llion): Early stopping.
                lambda i, *_: tf.less(i, decode_length),
                inner_loop,
                [tf.constant(0), next_id, decoded_ids, cache],
                shape_invariants=[
                    tf.TensorShape([]),
                    tf.TensorShape([None, None]),
                    tf.TensorShape([None, None]),
                    nest.map_structure(lambda t: tf.TensorShape(t.shape),
                                       cache),
                ])

        return decoded_ids, scores
Пример #49
0
 def from_proto(variable_def, import_scope=None):
     if context.in_eager_mode():
         raise RuntimeError("from_proto not supported in EAGER mode.")
     return ResourceVariable(variable_def=variable_def,
                             import_scope=import_scope)
Пример #50
0
def constant_value_as_shape(tensor):  # pylint: disable=invalid-name
    """A version of `constant_value()` that returns a `TensorShape`.

  This version should be used when a constant tensor value is
  interpreted as a (possibly partial) shape, e.g. in the shape
  function for `tf.reshape()`. By explicitly requesting a
  `TensorShape` as the return value, it is possible to represent
  unknown dimensions; by contrast, `constant_value()` is
  all-or-nothing.

  Args:
    tensor: The rank-1 Tensor to be evaluated.

  Returns:
    A `TensorShape` based on the constant value of the given `tensor`.
  """
    if context.in_eager_mode():
        return tensor_shape.as_shape(
            [dim if dim != -1 else None for dim in tensor.numpy()])

    shape = tensor.get_shape().with_rank(1)
    if tensor.get_shape() == [0]:
        return tensor_shape.scalar()
    elif tensor.op.type == "Shape":
        return tensor.op.inputs[0].get_shape()
    elif tensor.op.type == "Pack":
        ret = tensor_shape.scalar()  # Empty list.
        # Since we expect rank 1 inputs, Pack's axis must be zero, otherwise it
        # would not be rank 1.
        assert tensor.op.get_attr("axis") == 0
        for pack_input in tensor.op.inputs:
            # `pack_input` must be a scalar. Attempt to evaluate it, and append it
            # to `ret`.
            pack_input_val = constant_value(pack_input)
            if pack_input_val is None or pack_input_val < 0:
                new_dim = tensor_shape.Dimension(None)
            else:
                new_dim = tensor_shape.Dimension(pack_input_val)
            ret = ret.concatenate([new_dim])
        return ret
    elif tensor.op.type == "Concat":
        # We assume that `tensor.op.inputs[0]` evaluates to 0, as this is
        # the only legal value when concatenating vectors, and it will
        # have been checked by a previous shape function.
        ret = tensor_shape.scalar()  # Empty list.
        for concat_input in tensor.op.inputs[1:]:
            # `concat_input` must be a vector. Attempt to evaluate it as a shape,
            # and concatenate it with `ret`.
            ret = ret.concatenate(constant_value_as_shape(concat_input))
        return ret
    elif tensor.op.type == "ConcatV2":
        # We assume that `tensor.op.inputs[-1]` evaluates to 0, as this is
        # the only legal value when concatenating vectors, and it will
        # have been checked by a previous shape function.
        ret = tensor_shape.scalar()  # Empty list.
        for concat_input in tensor.op.inputs[:-1]:
            # `concat_input` must be a vector. Attempt to evaluate it as a shape,
            # and concatenate it with `ret`.
            ret = ret.concatenate(constant_value_as_shape(concat_input))
        return ret
    elif tensor.op.type == "StridedSlice":
        try:
            begin = constant_value(tensor.op.inputs[1])
            end = constant_value(tensor.op.inputs[2])
            strides = constant_value(tensor.op.inputs[3])
            if begin is not None and end is not None and strides is not None:
                begin = begin[0]
                end = end[0]
                strides = strides[0]
                begin_mask = tensor.op.get_attr("begin_mask")
                if begin_mask == 1:
                    begin = None
                end_mask = tensor.op.get_attr("end_mask")
                if end_mask == 1:
                    end = None

                ellipsis_mask = tensor.op.get_attr("ellipsis_mask")
                new_axis_mask = tensor.op.get_attr("new_axis_mask")
                shrink_axis_mask = tensor.op.get_attr("shrink_axis_mask")
                valid_attributes = (not ellipsis_mask and not new_axis_mask
                                    and not shrink_axis_mask
                                    and (not begin_mask or (begin_mask == 1))
                                    and (not end_mask or (end_mask == 1)))
                if valid_attributes:  # additional inputs not supported
                    prev = constant_value_as_shape(tensor.op.inputs[0])
                    prev = prev[begin:end:strides]
                    ret = tensor_shape.TensorShape(prev)
                    return ret

        except ValueError:  # Could come from get_attr or slicing prev.
            pass
        except TypeError:  # Could come from slicing prev.
            pass

    ret = tensor_shape.unknown_shape(shape[0].value)
    value = constant_value(tensor)
    if value is not None:
        ret = ret.merge_with(
            tensor_shape.TensorShape([d if d >= 0 else None for d in value]))
    return ret
Пример #51
0
 def eval(self, session=None):
     """Evaluates and returns the value of this variable."""
     if context.in_eager_mode():
         raise RuntimeError("Trying to eval in EAGER mode")
     return self._graph_element.eval(session=session)
Пример #52
0
 def initial_value(self):
     """Returns the Tensor used as the initial value for the variable."""
     if context.in_eager_mode():
         raise RuntimeError("initial_value not supported in EAGER mode.")
     return self._initial_value
Пример #53
0
def gradients(ys,
              xs,
              grad_ys=None,
              name="gradients",
              colocate_gradients_with_ops=False,
              gate_gradients=False,
              aggregation_method=None,
              stop_gradients=None):
    """Constructs symbolic derivatives of sum of `ys` w.r.t. x in `xs`.

  `ys` and `xs` are each a `Tensor` or a list of tensors.  `grad_ys`
  is a list of `Tensor`, holding the gradients received by the
  `ys`. The list must be the same length as `ys`.

  `gradients()` adds ops to the graph to output the derivatives of `ys` with
  respect to `xs`.  It returns a list of `Tensor` of length `len(xs)` where
  each tensor is the `sum(dy/dx)` for y in `ys`.

  `grad_ys` is a list of tensors of the same length as `ys` that holds
  the initial gradients for each y in `ys`.  When `grad_ys` is None,
  we fill in a tensor of '1's of the shape of y for each y in `ys`.  A
  user can provide their own initial `grad_ys` to compute the
  derivatives using a different initial gradient for each y (e.g., if
  one wanted to weight the gradient differently for each value in
  each y).

  `stop_gradients` is a `Tensor` or a list of tensors to be considered constant
  with respect to all `xs`. These tensors will not be backpropagated through,
  as though they had been explicitly disconnected using `stop_gradient`.  Among
  other things, this allows computation of partial derivatives as opposed to
  total derivatives. For example:

  ```python
  a = tf.constant(0.)
  b = 2 * a
  g = tf.gradients(a + b, [a, b], stop_gradients=[a, b])
  ```

  Here the partial derivatives `g` evaluate to `[1.0, 1.0]`, compared to the
  total derivatives `tf.gradients(a + b, [a, b])`, which take into account the
  influence of `a` on `b` and evaluate to `[3.0, 1.0]`.  Note that the above is
  equivalent to:

  ```python
  a = tf.stop_gradient(tf.constant(0.))
  b = tf.stop_gradient(2 * a)
  g = tf.gradients(a + b, [a, b])
  ```

  `stop_gradients` provides a way of stopping gradient after the graph has
  already been constructed, as compared to `tf.stop_gradient` which is used
  during graph construction.  When the two approaches are combined,
  backpropagation stops at both `tf.stop_gradient` nodes and nodes in
  `stop_gradients`, whichever is encountered first.

  Args:
    ys: A `Tensor` or list of tensors to be differentiated.
    xs: A `Tensor` or list of tensors to be used for differentiation.
    grad_ys: Optional. A `Tensor` or list of tensors the same size as
      `ys` and holding the gradients computed for each y in `ys`.
    name: Optional name to use for grouping all the gradient ops together.
      defaults to 'gradients'.
    colocate_gradients_with_ops: If True, try colocating gradients with
      the corresponding op.
    gate_gradients: If True, add a tuple around the gradients returned
      for an operations.  This avoids some race conditions.
    aggregation_method: Specifies the method used to combine gradient terms.
      Accepted values are constants defined in the class `AggregationMethod`.
    stop_gradients: Optional. A `Tensor` or list of tensors not to differentiate
      through.

  Returns:
    A list of `sum(dy/dx)` for each x in `xs`.

  Raises:
    LookupError: if one of the operations between `x` and `y` does not
      have a registered gradient function.
    ValueError: if the arguments are invalid.
    RuntimeError: if called in Eager mode.

  """
    if context.in_eager_mode():
        raise RuntimeError("tf.gradients not supported in EAGER mode. Use "
                           "functions in tf.contrib.eager.backprop instead.")
    ys = _AsList(ys)
    xs = _AsList(xs)
    stop_gradients = [] if stop_gradients is None else _AsList(stop_gradients)
    if grad_ys is None:
        grad_ys = [None] * len(ys)
    else:
        grad_ys = _AsList(grad_ys)

    with ops.name_scope(
            name, "gradients",
            list(ys) + list(xs) + list(stop_gradients) +
            list(grad_ys)) as grad_scope:
        ys = ops.convert_n_to_tensor_or_indexed_slices(ys, name="y")
        xs = [
            x.handle
            if isinstance(x, resource_variable_ops.ResourceVariable) else x
            for x in xs
        ]
        xs = ops.internal_convert_n_to_tensor_or_indexed_slices(xs,
                                                                name="x",
                                                                as_ref=True)
        grad_ys = _DefaultGradYs(grad_ys, ys, colocate_gradients_with_ops)

        # The approach we take here is as follows: Create a list of all ops in the
        # subgraph between the ys and xs.  Visit these ops in reverse order of ids
        # to ensure that when we visit an op the gradients w.r.t its outputs have
        # been collected.  Then aggregate these gradients if needed, call the op's
        # gradient function, and add the generated gradients to the gradients for
        # its input.

        # Initialize the pending count for ops in the connected subgraph from ys
        # to the xs.
        if len(ys) > 1:
            ys = [array_ops.identity(y) if y.consumers() else y for y in ys]
        to_ops = [t.op for t in ys]
        from_ops = [t.op for t in xs]
        stop_gradient_ops = [t.op for t in stop_gradients]
        pending_count, loop_state = _PendingCount(ops.get_default_graph(),
                                                  to_ops, from_ops,
                                                  colocate_gradients_with_ops)

        # Iterate over the collected ops.
        #
        # grads: op => list of gradients received on each output endpoint of the
        # op.  The gradients for each endpoint are initially collected as a list.
        # When it is time to call the op's gradient function, for each endpoint we
        # aggregate the list of received gradients into a Add() Operation if there
        # is more than one.
        grads = {}

        # Add the initial gradients for the ys.
        for y, grad_y in zip(ys, grad_ys):
            _SetGrad(grads, y, grad_y)

        # Initialize queue with to_ops.
        queue = collections.deque()
        # Add the ops in 'to_ops' into the queue.
        to_ops_set = set()
        for op in to_ops:
            # 'ready' handles the case where one output gradient relies on
            # another output's gradient.
            # pylint: disable=protected-access
            ready = (pending_count[op._id] == 0)
            if ready and op._id not in to_ops_set:
                to_ops_set.add(op._id)
                queue.append(op)
            # pylint: enable=protected-access

        if loop_state:
            loop_exits = loop_state.ProcessUnusedLoopExits(
                pending_count, to_ops_set)
            for y in loop_exits:
                if _IsTrainable(y):
                    _SetGrad(grads, y, loop_state.ZerosLikeForExit(y))
                    queue.append(y.op)

        stop_ops = _StopOps(from_ops, stop_gradient_ops, pending_count)
        while queue:
            # generate gradient subgraph for op.
            op = queue.popleft()
            with _maybe_colocate_with(op, colocate_gradients_with_ops):
                if loop_state:
                    loop_state.EnterGradWhileContext(op, before=True)
                out_grads = _AggregatedGrads(grads, op, loop_state,
                                             aggregation_method)
                if loop_state:
                    loop_state.ExitGradWhileContext(op, before=True)

                grad_fn = None
                # pylint: disable=protected-access
                func_call = None
                is_func_call = ops.get_default_graph()._is_function(op.type)
                has_out_grads = any(
                    isinstance(g, ops.Tensor) or g for g in out_grads)
                if has_out_grads and (op._id not in stop_ops):
                    if is_func_call:
                        func_call = ops.get_default_graph()._get_function(
                            op.type)
                        grad_fn = func_call.python_grad_func
                        # pylint: enable=protected-access
                    else:
                        # A grad_fn must be defined, either as a function or as None
                        # for ops that do not have gradients.
                        try:
                            grad_fn = ops.get_gradient_function(op)
                        except LookupError:
                            raise LookupError(
                                "No gradient defined for operation '%s' (op type: %s)"
                                % (op.name, op.type))
                if loop_state:
                    loop_state.EnterGradWhileContext(op, before=False)
                if (grad_fn or is_func_call) and has_out_grads:
                    # NOTE: If _AggregatedGrads didn't compute a value for the i'th id:3537 gh:3538
                    # output, it means that the cost does not depend on output[i],
                    # therefore dC/doutput[i] is 0.
                    for i, out_grad in enumerate(out_grads):
                        if (not isinstance(out_grad, ops.Tensor)
                                and not out_grad) and (
                                    (not grad_fn and is_func_call)
                                    or _IsTrainable(op.outputs[i])):
                            # Only trainable outputs or outputs for a function call that
                            # will use SymbolicGradient get a zero gradient. Gradient
                            # functions should ignore the gradient for other outputs.
                            # TODO (apassos) gradients of resource handles might be an id:3152 gh:3153
                            # issue here because of zeros.
                            if loop_state:
                                out_grads[i] = loop_state.ZerosLike(op, i)
                            else:
                                out_grads[
                                    i] = control_flow_ops.ZerosLikeOutsideLoop(
                                        op, i)
                    with ops.name_scope(op.name + "_grad"):
                        # pylint: disable=protected-access
                        with ops.get_default_graph()._original_op(op):
                            # pylint: enable=protected-access
                            if grad_fn:
                                # If grad_fn was found, do not use SymbolicGradient even for
                                # functions.
                                in_grads = _MaybeCompile(
                                    grad_scope, op, func_call,
                                    lambda: grad_fn(op, *out_grads))
                            else:
                                # For function call ops, we add a 'SymbolicGradient'
                                # node to the graph to compute gradients.
                                in_grads = _MaybeCompile(
                                    grad_scope, op, func_call,
                                    lambda: _SymGrad(op, out_grads))
                            in_grads = _AsList(in_grads)
                            _VerifyGeneratedGradients(in_grads, op)
                            if gate_gradients and len(
                                [x for x in in_grads if x is not None]) > 1:
                                with ops.device(None):
                                    with ops.colocate_with(
                                            None, ignore_existing=True):
                                        in_grads = control_flow_ops.tuple(
                                            in_grads)
                    _LogOpGradients(op, out_grads, in_grads)
                else:
                    # If no grad_fn is defined or none of out_grads is available,
                    # just propagate a list of None backwards.
                    in_grads = [None] * len(op.inputs)
                for i, (t_in, in_grad) in enumerate(zip(op.inputs, in_grads)):
                    if in_grad is not None:
                        if (isinstance(in_grad, ops.Tensor)
                                and t_in.dtype != dtypes.resource):
                            try:
                                in_grad.set_shape(t_in.get_shape())
                            except ValueError:
                                raise ValueError(
                                    "Incompatible shapes between op input and calculated "
                                    "input gradient.  Forward operation: %s.  Input index: %d. "
                                    "Original input shape: %s.  "
                                    "Calculated input gradient shape: %s" %
                                    (op.name, i, t_in.shape, in_grad.shape))
                        _SetGrad(grads, t_in, in_grad)
                if loop_state:
                    loop_state.ExitGradWhileContext(op, before=False)

            # Update pending count for the inputs of op and enqueue ready ops.
            _UpdatePendingAndEnqueueReady(grads, op, queue, pending_count,
                                          loop_state)

    if loop_state:
        loop_state.PostProcessing()
    return [_GetGrad(grads, x) for x in xs]
Пример #54
0
def accumulate_n_v2(inputs, shape=None, tensor_dtype=None, name=None):
    """Returns the element-wise sum of a list of tensors.

  Optionally, pass `shape` and `tensor_dtype` for shape and type checking,
  otherwise, these are inferred.

  `tf.accumulate_n_v2` performs the same operation as `tf.add_n`, but does not
  wait for all of its inputs to be ready before beginning to sum. This can
  save memory if inputs are ready at different times, since minimum temporary
  storage is proportional to the output size rather than the inputs size.

  Unlike the original `accumulate_n`, `accumulate_n_v2` is differentiable.

  For example:

  ```python
  a = tf.constant([[1, 2], [3, 4]])
  b = tf.constant([[5, 0], [0, 6]])
  tf.accumulate_n_v2([a, b, a])  # [[7, 4], [6, 14]]

  # Explicitly pass shape and type
  tf.accumulate_n_v2([a, b, a], shape=[2, 2], tensor_dtype=tf.int32)
                                                                   # [[7,  4],
                                                                   #  [6, 14]]
  ```

  Args:
    inputs: A list of `Tensor` objects, each with same shape and type.
    shape: Shape of elements of `inputs`.
    tensor_dtype: The type of `inputs`.
    name: A name for the operation (optional).

  Returns:
    A `Tensor` of same shape and type as the elements of `inputs`.

  Raises:
    ValueError: If `inputs` don't all have same shape and dtype or the shape
    cannot be inferred.
  """
    _INPUTS_ERR_MSG = ValueError("inputs must be a list of at least one Tensor"
                                 "with the same dtype and shape")
    if not inputs or not isinstance(inputs, (list, tuple)):
        raise _INPUTS_ERR_MSG
    inputs = ops.convert_n_to_tensor_or_indexed_slices(inputs)
    if not all(isinstance(x, ops.Tensor) for x in inputs):
        raise _INPUTS_ERR_MSG
    if not all(x.dtype == inputs[0].dtype for x in inputs):
        raise _INPUTS_ERR_MSG
    if shape is not None:
        shape = tensor_shape.as_shape(shape)
    else:
        shape = tensor_shape.unknown_shape()
    for input_tensor in inputs:
        if isinstance(input_tensor, ops.Tensor):
            shape = shape.merge_with(input_tensor.get_shape())

    # tensor_dtype is for safety only; operator's output type computed in C++
    if tensor_dtype is not None and tensor_dtype != inputs[0].dtype:
        raise TypeError("tensor_dtype is {}, but input is of type {}".format(
            tensor_dtype, inputs[0].dtype))

    if len(inputs) == 1 and name is None:
        return inputs[0]
    elif len(inputs) == 1 and name is not None:
        return array_ops.identity(inputs[0], name=name)
    elif context.in_eager_mode():
        # TemporaryVariable not currently supported in eager mode; fall back
        # onto AddN for now.
        # TODO(frreiss) remove this once the lifetime of eager variables gets
        # addressed
        return math_ops.add_n(inputs, name=name)
    else:
        return gen_math_ops._accumulate_nv2(inputs, name=name, shape=shape)
Пример #55
0
def _defun_internal(name, func, args, kwds):
    """Defines and returns graph-mode version of func."""
    container_prefix = ops.get_default_graph()._container_prefix  # pylint: disable=protected-access
    with context.graph_mode():
        captures = {}
        tmp_graph = CapturingGraph(captures)
        # Inherit the container prefix, since this is used for error checking when
        # isolating eager execution (the container prefix at creation must match the
        # container prefix when used, and variables accessed in the defun will be
        # used in the outside context).
        tmp_graph._container_prefix = container_prefix  # pylint: disable=protected-access
        # Copy the graph collections to ensure summaries and other things work. This
        # lets the function access (but not mutate) collections of the containing
        # graph, such as the global step and the summary writer collections.
        curr_graph = ops.get_default_graph()
        for collection in curr_graph.collections:
            tmp_graph.get_collection_ref(
                collection)[:] = curr_graph.get_collection(collection)
        with tmp_graph.as_default():
            func_inputs = _get_defun_inputs(args)

            with capture_tensors(captures):
                this_tape = tape.push_new_tape()
                try:
                    func_outputs = func(*func_inputs, **kwds)
                finally:
                    tape.pop_tape(this_tape)
                variables = this_tape.watched_variables()

                # Returning a closed-over tensor as an output does not trigger a
                # call to convert_to_tensor, so we manually capture all such tensors.
                outputs_list = nest.flatten(func_outputs)
                func_def_outputs = [
                    _convert_to_graph_tensor(x) for x in outputs_list
                    if x is not None
                ]

            ids = list(sorted(captures.keys()))
            if ids:
                extra_inputs, extra_placeholders = zip(
                    *[captures[x] for x in ids])
            else:
                extra_inputs = []
                extra_placeholders = []
            output_shapes = tuple(
                x.shape if isinstance(x, ops.Tensor) else None
                for x in outputs_list)

    flat_inputs = [
        x for x in nest.flatten(func_inputs) if isinstance(x, ops.Tensor)
    ]
    all_inputs = flat_inputs + list(extra_placeholders)
    all_ignored_ops = frozenset(x.op for x in all_inputs)
    fname = _inference_name(name)
    operations = tuple(x for x in tmp_graph.get_operations()
                       if x not in all_ignored_ops)
    # Register any other functions defined in the graph
    # TODO(ashankar): Oh lord, forgive me for this lint travesty.
    if context.in_eager_mode():
        for f in tmp_graph._functions.values():  # pylint: disable=protected-access
            # TODO(ashankar): What about the gradient registry?
            _register(f._c_func)  # pylint: disable=protected-access
    return GraphModeFunction(fname, all_inputs, extra_inputs, tmp_graph,
                             operations, func_def_outputs, func_outputs,
                             output_shapes, variables)
Пример #56
0
    def compute_gradients(self,
                          loss,
                          var_list=None,
                          gate_gradients=GATE_OP,
                          aggregation_method=None,
                          colocate_gradients_with_ops=False,
                          grad_loss=None):
        """Compute gradients of `loss` for the variables in `var_list`.

    This is the first part of `minimize()`.  It returns a list
    of (gradient, variable) pairs where "gradient" is the gradient
    for "variable".  Note that "gradient" can be a `Tensor`, an
    `IndexedSlices`, or `None` if there is no gradient for the
    given variable.

    Args:
      loss: A Tensor containing the value to minimize.
      var_list: Optional list or tuple of `tf.Variable` to update to minimize
        `loss`.  Defaults to the list of variables collected in the graph
        under the key `GraphKeys.TRAINABLE_VARIABLES`.
      gate_gradients: How to gate the computation of gradients.  Can be
        `GATE_NONE`, `GATE_OP`, or `GATE_GRAPH`.
      aggregation_method: Specifies the method used to combine gradient terms.
        Valid values are defined in the class `AggregationMethod`.
      colocate_gradients_with_ops: If True, try colocating gradients with
        the corresponding op.
      grad_loss: Optional. A `Tensor` holding the gradient computed for `loss`.

    Returns:
      A list of (gradient, variable) pairs. Variable is always present, but
      gradient can be `None`.

    Raises:
      TypeError: If `var_list` contains anything else than `Variable` objects.
      ValueError: If some arguments are invalid.
      RuntimeError: If called with eager execution enabled and if `grad_loss`
        is not `None` or `loss` is not callable.

    @compatibility(eager)
    When eager execution is enabled, `loss` should be a Python function that
    takes elements of `var_list` as arguments and computes the value to be
    minimized. If `var_list` is None, `loss` should take no arguments.
    Gradient computation is done with respect to the elements of `var_list` if
    not None, else with respect to any trainable variables created during the
    execution of the `loss` function.
    `gate_gradients`, `aggregation_method`, `colocate_gradients_with_ops` and
    `grad_loss` are ignored when eager execution is enabled.
    @end_compatibility
    """
        if context.in_eager_mode():
            if grad_loss is not None:
                raise RuntimeError(
                    "`grad_loss` argument to Optimizer.compute_gradients "
                    "not supported when eager execution is enabled.")
            if not callable(loss):
                raise RuntimeError(
                    "`loss` passed to Optimizer.compute_gradients should "
                    "be a function when eager execution is enabled.")
            # TODO (agarwal): consider passing parameters to the `loss` function. id:2636 gh:2637
            if var_list is None:
                return backprop.implicit_grad(loss)()
            else:
                var_list = nest.flatten(var_list)
                grads = backprop.gradients_function(loss)(*var_list)
                grads_and_vars = list(zip(grads, var_list))
                return grads_and_vars
        if gate_gradients not in [
                Optimizer.GATE_NONE, Optimizer.GATE_OP, Optimizer.GATE_GRAPH
        ]:
            raise ValueError(
                "gate_gradients must be one of: Optimizer.GATE_NONE, "
                "Optimizer.GATE_OP, Optimizer.GATE_GRAPH.  Not %s" %
                gate_gradients)
        self._assert_valid_dtypes([loss])
        if grad_loss is not None:
            self._assert_valid_dtypes([grad_loss])
        if var_list is None:
            var_list = (
                variables.trainable_variables() +
                ops.get_collection(ops.GraphKeys.TRAINABLE_RESOURCE_VARIABLES))
        else:
            var_list = nest.flatten(var_list)
        # pylint: disable=protected-access
        var_list += ops.get_collection(ops.GraphKeys._STREAMING_MODEL_PORTS)
        # pylint: enable=protected-access
        processors = [_get_processor(v) for v in var_list]
        if not var_list:
            raise ValueError("No variables to optimize.")
        var_refs = [p.target() for p in processors]
        grads = gradients.gradients(
            loss,
            var_refs,
            grad_ys=grad_loss,
            gate_gradients=(gate_gradients == Optimizer.GATE_OP),
            aggregation_method=aggregation_method,
            colocate_gradients_with_ops=colocate_gradients_with_ops)
        if gate_gradients == Optimizer.GATE_GRAPH:
            grads = control_flow_ops.tuple(grads)
        grads_and_vars = list(zip(grads, var_list))
        self._assert_valid_dtypes([
            v for g, v in grads_and_vars
            if g is not None and v.dtype != dtypes.resource
        ])
        return grads_and_vars
Пример #57
0
def make_template(name_, func_, create_scope_now_=False, unique_name_=None,
                  custom_getter_=None, **kwargs):
  """Given an arbitrary function, wrap it so that it does variable sharing.

  This wraps `func_` in a Template and partially evaluates it. Templates are
  functions that create variables the first time they are called and reuse them
  thereafter. In order for `func_` to be compatible with a `Template` it must
  have the following properties:

  * The function should create all trainable variables and any variables that
     should be reused by calling `tf.get_variable`. If a trainable variable is
     created using `tf.Variable`, then a ValueError will be thrown. Variables
     that are intended to be locals can be created by specifying
     `tf.Variable(..., trainable=false)`.
  * The function may use variable scopes and other templates internally to
      create and reuse variables, but it shouldn't use `tf.global_variables` to
      capture variables that are defined outside of the scope of the function.
  * Internal scopes and variable names should not depend on any arguments that
      are not supplied to `make_template`. In general you will get a ValueError
      telling you that you are trying to reuse a variable that doesn't exist
      if you make a mistake.

  In the following example, both `z` and `w` will be scaled by the same `y`. It
  is important to note that if we didn't assign `scalar_name` and used a
  different name for z and w that a `ValueError` would be thrown because it
  couldn't reuse the variable.

  ```python
  def my_op(x, scalar_name):
    var1 = tf.get_variable(scalar_name,
                           shape=[],
                           initializer=tf.constant_initializer(1))
    return x * var1

  scale_by_y = tf.make_template('scale_by_y', my_op, scalar_name='y')

  z = scale_by_y(input1)
  w = scale_by_y(input2)
  ```

  As a safe-guard, the returned function will raise a `ValueError` after the
  first call if trainable variables are created by calling `tf.Variable`.

  If all of these are true, then 2 properties are enforced by the template:

  1. Calling the same template multiple times will share all non-local
      variables.
  2. Two different templates are guaranteed to be unique, unless you reenter the
      same variable scope as the initial definition of a template and redefine
      it. An examples of this exception:

  ```python
  def my_op(x, scalar_name):
    var1 = tf.get_variable(scalar_name,
                           shape=[],
                           initializer=tf.constant_initializer(1))
    return x * var1

  with tf.variable_scope('scope') as vs:
    scale_by_y = tf.make_template('scale_by_y', my_op, scalar_name='y')
    z = scale_by_y(input1)
    w = scale_by_y(input2)

  # Creates a template that reuses the variables above.
  with tf.variable_scope(vs, reuse=True):
    scale_by_y2 = tf.make_template('scale_by_y', my_op, scalar_name='y')
    z2 = scale_by_y2(input1)
    w2 = scale_by_y2(input2)
  ```

  Depending on the value of `create_scope_now_`, the full variable scope may be
  captured either at the time of first call or at the time of construction. If
  this option is set to True, then all Tensors created by repeated calls to the
  template will have an extra trailing _N+1 to their name, as the first time the
  scope is entered in the Template constructor no Tensors are created.

  Note: `name_`, `func_` and `create_scope_now_` have a trailing underscore to
  reduce the likelihood of collisions with kwargs.

  Args:
    name_: A name for the scope created by this template. If necessary, the name
      will be made unique by appending `_N` to the name.
    func_: The function to wrap.
    create_scope_now_: Boolean controlling whether the scope should be created
      when the template is constructed or when the template is called. Default
      is False, meaning the scope is created when the template is called.
    unique_name_: When used, it overrides name_ and is not made unique. If a
      template of the same scope/unique_name already exists and reuse is false,
      an error is raised. Defaults to None.
    custom_getter_: Optional custom getter for variables used in `func_`. See
      the @{tf.get_variable} `custom_getter` documentation for
      more information.
    **kwargs: Keyword arguments to apply to `func_`.

  Returns:
    A function to encapsulate a set of variables which should be created once
    and reused. An enclosing scope will be created either when `make_template`
    is called or when the result is called, depending on the value of
    `create_scope_now_`. Regardless of the value, the first time the template
    is called it will enter the scope with no reuse, and call `func_` to create
    variables, which are guaranteed to be unique. All subsequent calls will
    re-enter the scope and reuse those variables.

  Raises:
    ValueError: if the name is None.
  """
  if kwargs:
    func_ = functools.partial(func_, **kwargs)
  if context.in_eager_mode():
    return EagerTemplate(
        name_, func_, create_scope_now=create_scope_now_,
        unique_name=unique_name_, custom_getter=custom_getter_)
  return Template(
      name_, func_, create_scope_now=create_scope_now_,
      unique_name=unique_name_, custom_getter=custom_getter_)
Пример #58
0
    def _add_variable_with_custom_getter(self,
                                         name,
                                         shape=None,
                                         dtype=dtypes.float32,
                                         initializer=None,
                                         getter=None,
                                         **kwargs_for_getter):
        """Restore-on-create for a variable be saved with this `Checkpointable`.

    If the user has requested that this object or another `Checkpointable` which
    depends on this object be restored from a checkpoint (deferred loading
    before variable object creation), `initializer` may be ignored and the value
    from the checkpoint used instead.

    Args:
      name: A name for the variable. Must be unique within this object.
      shape: The shape of the variable.
      dtype: The data type of the variable.

      initializer: The initializer to use. Ignored if there is a deferred
        restoration left over from a call to
        `_restore_from_checkpoint_position`.

      getter: The getter to wrap which actually fetches the variable.
      **kwargs_for_getter: Passed to the getter.

    Returns:
      The new variable object.

    Raises:
      ValueError: If the variable name is not unique.
    """
        self._maybe_initialize_checkpointable()
        if name in self._dependency_names:
            raise ValueError((
                "A variable named '%s' already exists in this Checkpointable, but "
                "Checkpointable._add_variable called to create another with "
                "that name. Variable names must be unique within a Checkpointable "
                "object.") % (name, ))
        if context.in_eager_mode():
            # If this is a variable with a single Tensor stored in the checkpoint, we
            # can set that value as an initializer rather than initializing and then
            # assigning (when executing eagerly). This call returns None if there is
            # nothing to restore.
            checkpoint_initializer = self._preload_simple_restoration(
                name=name, shape=shape)
        else:
            checkpoint_initializer = None
        if (checkpoint_initializer is not None
                and not (isinstance(initializer, CheckpointInitialValue)
                         and initializer.restore_uid >
                         checkpoint_initializer.restore_uid)):
            # If multiple Checkpointable objects are "creating" the same variable via
            # the magic of custom getters, the one with the highest restore UID (the
            # one called last) has to make the final initializer. If another custom
            # getter interrupts this process by overwriting the initializer, then
            # we'll catch that when we call _track_checkpointable. So this is "best
            # effort" to set the initializer with the highest restore UID.
            initializer = checkpoint_initializer
            shape = None

        new_variable = getter(name=name,
                              shape=shape,
                              dtype=dtype,
                              initializer=initializer,
                              **kwargs_for_getter)

        # If we set an initializer and the variable processed it, tracking will not
        # assign again. It will add this variable to our dependencies, and if there
        # is a non-trivial restoration queued, it will handle that. This also
        # handles slot variables.
        return self._track_checkpointable(new_variable, name=name)
Пример #59
0
def _var_key(var):
    if context.in_eager_mode():
        return var._shared_name  # pylint: disable=protected-access
    return (var.op.graph, var.op.name)
Пример #60
0
def _executing_eagerly():
    """Returns true if eager execution is supported and enabled."""
    return _has_eager and context.in_eager_mode()