Exemplo n.º 1
0
  def testMap_Scoped(self):
    with self.cached_session() as sess:

      def double_scoped(x):
        """2x with a dummy 2 that is scoped."""
        with variable_scope.variable_scope("body"):
          # Dummy variable, just to check that scoping works as intended.
          two = variable_scope.get_variable(
              "two", [],
              dtype=dtypes.int32,
              initializer=init_ops.constant_initializer(2))
          return math_ops.multiply(x, two)

      with variable_scope.variable_scope("root") as varscope:
        elems = constant_op.constant([1, 2, 3, 4, 5, 6], name="data")
        doubles = np.array([2 * x for x in [1, 2, 3, 4, 5, 6]])

        r = map_fn.map_fn(double_scoped, elems)
        # Check that we have the one variable we asked for here.
        self.assertEqual(len(variables.trainable_variables()), 1)
        self.assertEqual(variables.trainable_variables()[0].name,
                         "root/body/two:0")
        sess.run([variables.global_variables_initializer()])
        self.assertAllEqual(doubles, self.evaluate(r))

        # Now let's reuse our single variable.
        varscope.reuse_variables()
        r = map_fn.map_fn(double_scoped, elems)
        self.assertEqual(len(variables.trainable_variables()), 1)
        self.assertAllEqual(doubles, self.evaluate(r))
Exemplo n.º 2
0
 def testMap_MultiOutputMismatchedDtype(self):
   nums = np.array([1, 2, 3, 4, 5, 6])
   with self.assertRaisesRegexp(
       TypeError, r"two structures don't have the same nested structure"):
     # lambda emits tuple, but dtype is a list
     map_fn.map_fn(
         lambda x: ((x + 3) * 2, -(x + 3) * 2),
         nums,
         dtype=[dtypes.int64, dtypes.int64])
Exemplo n.º 3
0
 def testMapSparseTensor(self):
   with self.cached_session():
     with self.assertRaises(TypeError):
       map_fn.map_fn(
           lambda x: x,
           sparse_tensor.SparseTensor(
               indices=[[0, 0], [0, 1], [1, 0]],
               values=constant_op.constant([0, 1, 2]),
               dense_shape=[2, 2]))
Exemplo n.º 4
0
 def testMap_Simple(self):
   nums = [1, 2, 3, 4, 5, 6]
   elems = constant_op.constant(nums, name="data")
   r = map_fn.map_fn(
       lambda x: math_ops.multiply(math_ops.add(x, 3), 2), elems)
   self.assertAllEqual(
       np.array([(x + 3) * 2 for x in nums]), self.evaluate(r))
Exemplo n.º 5
0
 def compute_activations(elems):
   return map_fn.map_fn(fn=classifier_fn,
                        elems=elems,
                        parallel_iterations=1,
                        back_prop=False,
                        swap_memory=True,
                        name='RunClassifier')
Exemplo n.º 6
0
def ctc_unique_labels(labels, name=None):
  """Get unique labels and indices for batched labels for `tf.nn.ctc_loss`.

  For use with `tf.nn.ctc_loss_v2` optional argument `unique`: This op can be
  used to preprocess labels in input pipeline to for better speed/memory use
  computing the ctc loss on TPU.

  Example:
    ctc_unique_labels([[3, 4, 4, 3]]) ->
      unique labels padded with 0: [[3, 4, 0, 0]]
      indices of original labels in unique: [0, 1, 1, 0]

  Args:
    labels: tensor of shape [batch_size, max_label_length] padded with 0.
    name: A name for this `Op`. Defaults to "ctc_unique_labels".

  Returns:
    tuple of
      - unique labels, tensor of shape `[batch_size, max_label_length]`
      - indices into unique labels, shape `[batch_size, max_label_length]`
  """

  with ops.name_scope(name, "ctc_unique_labels", [labels]):
    labels = ops.convert_to_tensor(labels, name="labels")
    def _unique(x):
      u = array_ops.unique(x)
      y = array_ops.pad(
          u.y, [[0, _get_dim(u.idx, 0) - _get_dim(u.y, 0)]])
      y = math_ops.cast(y, dtypes.int64)
      return [y, u.idx]
    return map_fn.map_fn(
        _unique, labels, dtype=[dtypes.int64, dtypes.int32])
Exemplo n.º 7
0
  def _sample_n(self, n, seed=None):
    n_draws = math_ops.cast(self.total_count, dtype=dtypes.int32)
    k = self.event_shape_tensor()[0]

    # broadcast the total_count and logits to same shape
    n_draws = array_ops.ones_like(
        self.logits[..., 0], dtype=n_draws.dtype) * n_draws
    logits = array_ops.ones_like(
        n_draws[..., array_ops.newaxis], dtype=self.logits.dtype) * self.logits

    # flatten the total_count and logits
    flat_logits = array_ops.reshape(logits, [-1, k])  # [B1B2...Bm, k]
    flat_ndraws = n * array_ops.reshape(n_draws, [-1])  # [B1B2...Bm]

    # computes each total_count and logits situation by map_fn
    def _sample_single(args):
      logits, n_draw = args[0], args[1]  # [K], []
      x = random_ops.multinomial(logits[array_ops.newaxis, ...], n_draw,
                                 seed)  # [1, n*n_draw]
      x = array_ops.reshape(x, shape=[n, -1])  # [n, n_draw]
      x = math_ops.reduce_sum(array_ops.one_hot(x, depth=k), axis=-2)  # [n, k]
      return x

    x = map_fn.map_fn(
        _sample_single, [flat_logits, flat_ndraws],
        dtype=self.dtype)  # [B1B2...Bm, n, k]

    # reshape the results to proper shape
    x = array_ops.transpose(x, perm=[1, 0, 2])
    final_shape = array_ops.concat([[n], self.batch_shape_tensor(), [k]], 0)
    x = array_ops.reshape(x, final_shape)  # [n, B1, B2,..., Bm, k]
    return x
Exemplo n.º 8
0
 def testMap_MultiInputSingleOutput(self):
   nums = np.array([1, 2, 3, 4, 5, 6])
   r = map_fn.map_fn(
       lambda x: x[0] * x[1][0] + x[1][1], (nums, (nums, -nums)),
       dtype=dtypes.int64)
   self.assertEqual((6,), r.get_shape())
   received = self.evaluate(r)
   self.assertAllEqual(nums * nums + (-nums), received)
Exemplo n.º 9
0
 def testWhileAndTensorArray(self):
   param = constant_op.constant(2.0)
   y0 = constant_op.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], name="elems")
   # map_fn uses TensorArray internally.
   r = map_fn.map_fn(lambda x: math_ops.multiply(x, param), y0)
   grad = gradients_impl.gradients(r, param)[0]
   self.assertAllClose([2.0, 4.0, 6.0, 8.0, 10.0, 12.0], self.evaluate(r))
   self.assertAllClose(21.0, self.evaluate(grad))
Exemplo n.º 10
0
  def _verifyLu(self, x, output_idx_type=dtypes.int64):
    # Verify that Px = LU.
    lu, perm = linalg_ops.lu(x, output_idx_type=output_idx_type)

    # Prepare the lower factor of shape num_rows x num_rows
    lu_shape = np.array(lu.shape.as_list())
    batch_shape = lu_shape[:-2]
    num_rows = lu_shape[-2]
    num_cols = lu_shape[-1]

    lower = array_ops.matrix_band_part(lu, -1, 0)

    if num_rows > num_cols:
      eye = linalg_ops.eye(
          num_rows, batch_shape=batch_shape, dtype=lower.dtype)
      lower = array_ops.concat([lower, eye[..., num_cols:]], axis=-1)
    elif num_rows < num_cols:
      lower = lower[..., :num_rows]

    # Fill the diagonal with ones.
    ones_diag = array_ops.ones(
        np.append(batch_shape, num_rows), dtype=lower.dtype)
    lower = array_ops.matrix_set_diag(lower, ones_diag)

    # Prepare the upper factor.
    upper = array_ops.matrix_band_part(lu, 0, -1)

    verification = math_ops.matmul(lower, upper)

    # Permute the rows of product of the Cholesky factors.
    if num_rows > 0:
      # Reshape the product of the triangular factors and permutation indices
      # to a single batch dimension. This makes it easy to apply
      # invert_permutation and gather_nd ops.
      perm_reshaped = array_ops.reshape(perm, [-1, num_rows])
      verification_reshaped = array_ops.reshape(verification,
                                                [-1, num_rows, num_cols])
      # Invert the permutation in each batch.
      inv_perm_reshaped = map_fn.map_fn(array_ops.invert_permutation,
                                        perm_reshaped)
      batch_size = perm_reshaped.shape.as_list()[0]
      # Prepare the batch indices with the same shape as the permutation.
      # The corresponding batch index is paired with each of the `num_rows`
      # permutation indices.
      batch_indices = math_ops.cast(
          array_ops.broadcast_to(
              math_ops.range(batch_size)[:, None], perm_reshaped.shape),
          dtype=output_idx_type)
      permuted_verification_reshaped = array_ops.gather_nd(
          verification_reshaped,
          array_ops.stack([batch_indices, inv_perm_reshaped], axis=-1))

      # Reshape the verification matrix back to the original shape.
      verification = array_ops.reshape(permuted_verification_reshaped,
                                       lu_shape)

    self._verifyLuBase(x, lower, upper, perm, verification,
                       output_idx_type)
Exemplo n.º 11
0
 def testMap_Grad(self):
   with self.cached_session():
     param = constant_op.constant(2.0)
     elems = constant_op.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], name="elems")
     y = map_fn.map_fn(
         lambda x: math_ops.multiply(math_ops.square(x), param), elems)
     r = gradients_impl.gradients(y, param)[0]
     self.assertAllEqual(91.0, self.evaluate(r))
     r = gradients_impl.gradients(y, elems)[0]
     self.assertAllEqual([4.0, 8.0, 12.0, 16.0, 20.0, 24.0], self.evaluate(r))
Exemplo n.º 12
0
  def tensors_to_item(self, keys_to_tensors):
    """See base class."""
    image_buffer = keys_to_tensors[self._image_key]
    image_format = keys_to_tensors[self._format_key]

    if self._repeated:
      return map_fn.map_fn(lambda x: self._decode(x, image_format),
                           image_buffer, dtype=self._dtype)
    else:
      return self._decode(image_buffer, image_format)
Exemplo n.º 13
0
 def input_fn():
   starts = random_ops.random_uniform(
       [batch_size], maxval=(2 * np.pi), seed=seed)
   sin_curves = map_fn.map_fn(
       _sin_fn, (starts,), dtype=dtypes.float32)
   inputs = array_ops.expand_dims(
       array_ops.slice(sin_curves, [0, 0], [batch_size, sequence_length]),
       2)
   labels = array_ops.slice(sin_curves, [0, 1],
                            [batch_size, sequence_length])
   return {'inputs': inputs}, labels
Exemplo n.º 14
0
 def testMap(self):
   if is_compile_on_demand():
     self.skipTest("list_ops are not supported in cpu_ondemand")
   with self.cached_session(), self.test_scope():
     xla_context = control_flow_ops.XLAControlFlowContext()
     xla_context.Enter()
     nums = [1, 2, 3, 4, 5, 6]
     elems = constant_op.constant(nums, name="data")
     r = map_fn.map_fn(lambda x: math_ops.multiply(math_ops.add(x, 3), 2),
                       elems)
     self.assertAllEqual(r, np.array([(x + 3) * 2 for x in nums]))
     xla_context.Exit()
Exemplo n.º 15
0
 def testMap_MultiInputSameStructureOutput(self):
   nums = np.array([1, 2, 3, 4, 5, 6])
   r = map_fn.map_fn(lambda x: (x[1][0], (x[1][1], x[0])),
                     (nums, (2 * nums, -nums)))
   r = [r[0], r[1][0], r[1][1]]
   self.assertEqual((6,), r[0].get_shape())
   self.assertEqual((6,), r[1].get_shape())
   self.assertEqual((6,), r[2].get_shape())
   received = self.evaluate(r)
   self.assertAllEqual(2 * nums, received[0])
   self.assertAllEqual(-nums, received[1])
   self.assertAllEqual(nums, received[2])
Exemplo n.º 16
0
 def testMap_SingleInputMultiOutput(self):
   nums = np.array([1, 2, 3, 4, 5, 6])
   r = map_fn.map_fn(
       lambda x: ((x + 3) * 2, -(x + 3) * 2),
       nums,
       dtype=(dtypes.int64, dtypes.int64))
   self.assertEqual(2, len(r))
   self.assertEqual((6,), r[0].get_shape())
   self.assertEqual((6,), r[1].get_shape())
   received = self.evaluate(r)
   self.assertAllEqual((nums + 3) * 2, received[0])
   self.assertAllEqual(-(nums + 3) * 2, received[1])
Exemplo n.º 17
0
def map_fn(fn, labeled_tensor, name=None):
  """Map on the list of tensors unpacked from labeled_tensor.

  See tf.map_fn.

  Args:
    fn: The function to apply to each unpacked LabeledTensor.
      It should have type LabeledTensor -> LabeledTensor.
    labeled_tensor: The input tensor.
    name: Optional op name.

  Returns:
    A tensor that packs the results of applying fn to the list of tensors
    unpacked from labeled_tensor.
  """
  with ops.name_scope(name, 'lt_map_fn', [labeled_tensor]) as scope:
    labeled_tensor = core.convert_to_labeled_tensor(labeled_tensor)

    unpack_lts = unpack(labeled_tensor)

    # TODO(ericmc): Fix this upstream.
    if labeled_tensor.dtype == dtypes.string:
      # We must construct the full graph here, because map_fn_lib.map_fn
      # doesn't work for string-valued tensors.
      # Constructing the full graph may be slow.
      map_lts = [fn(t) for t in unpack_lts]
      return pack(map_lts, list(labeled_tensor.axes.values())[0], name=scope)
    else:
      # Figure out what the axis labels should be, but use tf.map_fn to
      # construct the graph because it's efficient.
      # It may be slow to construct the full graph, so we infer the labels from
      # the first element.
      # TODO(ericmc): This builds a subgraph which then gets thrown away.
      # Find a more elegant solution.
      first_map_lt = fn(unpack_lts[0])
      final_axes = list(labeled_tensor.axes.values())[:1] + list(
          first_map_lt.axes.values())

      @tc.returns(ops.Tensor)
      @tc.accepts(ops.Tensor)
      def tf_fn(tensor):
        original_axes = list(labeled_tensor.axes.values())[1:]
        tensor_lt = core.LabeledTensor(tensor, original_axes)
        return fn(tensor_lt).tensor

      map_op = map_fn_lib.map_fn(
          tf_fn, labeled_tensor.tensor, dtype=first_map_lt.dtype)
      map_lt = core.LabeledTensor(map_op, final_axes)

      return core.identity(map_lt, name=scope)
Exemplo n.º 18
0
  def benchmark_map_fn(self):
    with ops.Graph().as_default():
      b = 256
      params = 1000
      inp = random_ops.random_normal((b, params))
      fn = lambda x: x * x

      def pfor_map_fn(f, x):
        return pfor_control_flow_ops.pfor(
            lambda i: f(array_ops.gather(x, i)),
            array_ops.shape(x)[0])

      map_output = map_fn.map_fn(fn, inp)
      pfor_output = pfor_map_fn(fn, inp)

      self._run(map_output, 100, name="tf_map_fn")
      self._run(pfor_output, 100, name="pfor_map_fn")
Exemplo n.º 19
0
def classifier_score(images, classifier_fn, num_batches=1):
  """Classifier score for evaluating a conditional generative model.

  This is based on the Inception Score, but for an arbitrary classifier.

  This technique is described in detail in https://arxiv.org/abs/1606.03498. In
  summary, this function calculates

  exp( E[ KL(p(y|x) || p(y)) ] )

  which captures how different the network's classification prediction is from
  the prior distribution over classes.

  NOTE: This function consumes images, computes their logits, and then
  computes the classifier score. If you would like to precompute many logits for
  large batches, use classifier_score_from_logits(), which this method also
  uses.

  Args:
    images: Images to calculate the classifier score for.
    classifier_fn: A function that takes images and produces logits based on a
      classifier.
    num_batches: Number of batches to split `generated_images` in to in order to
      efficiently run them through the classifier network.

  Returns:
    The classifier score. A floating-point scalar of the same type as the output
    of `classifier_fn`.
  """
  generated_images_list = array_ops.split(
      images, num_or_size_splits=num_batches)

  # Compute the classifier splits using the memory-efficient `map_fn`.
  logits = map_fn.map_fn(
      fn=classifier_fn,
      elems=array_ops.stack(generated_images_list),
      parallel_iterations=1,
      back_prop=False,
      swap_memory=True,
      name='RunClassifier')
  logits = array_ops.concat(array_ops.unstack(logits), 0)

  return classifier_score_from_logits(logits)
Exemplo n.º 20
0
  def benchmarkDefunVsMapFn(self):
    """Benchmarks to compare the performance of MapDefun vs tf.map_fn."""

    @function.defun(input_signature=[tensor_spec.TensorSpec([], dtypes.int32)])
    def defun(x):
      return array_ops.identity(x)

    def fn(x):
      return array_ops.identity(x)

    base = math_ops.range(100)
    for input_size in [10, 100, 1000, 10000]:
      num_iters = 100000 // input_size
      map_defun_op = map_defun.map_defun(defun, [base], [dtypes.int32], [()])
      map_fn_op = map_fn.map_fn(fn, base)

      self._run(
          map_defun_op, "with_defun_size_%d" % input_size, num_iters=num_iters)
      self._run(
          map_fn_op, "without_defun_size_%d" % input_size, num_iters=num_iters)
Exemplo n.º 21
0
  def testCaseAndCondInWhileInMap(self):

    def control_map_fn(x, y):

      def multiply():
        return x * 2

      def divide():
        return x // 2

      def defaults_two():
        return control_flow_ops.cond(
            math_ops.equal(math_ops.mod(x, 2), 0),
            multiply,
            divide,
            name="cond_mult")

      pred_fn_pairs = {
          math_ops.logical_or(math_ops.equal(y, 2), math_ops.equal(y, 3)):
              defaults_two,
      }

      return control_flow_ops.case(
          pred_fn_pairs, default=multiply, exclusive=True)

    row = np.arange(6)
    num = 2
    # pylint: disable=g-long-lambda
    dataset = dataset_ops.Dataset.from_tensors(
        row).map(lambda elems: map_fn.map_fn(
            lambda x: control_map_fn(x, num), elems))
    # pylint: enable=g-long-lambda
    get_next = self.getNext(dataset)

    self.assertAllEqual([(x // 2 if x % 2 else x * 2) if
                         (num == 2 or num == 3) else x * 2 for x in row],
                        self.evaluate(get_next()))
    with self.assertRaises(errors.OutOfRangeError):
      self.evaluate(get_next())
    def benchmarkDefunVsMapFn(self):
        """Benchmarks to compare the performance of MapDefun vs tf.map_fn."""
        @function.defun(
            input_signature=[tensor_spec.TensorSpec([], dtypes.int32)])
        def defun(x):
            return array_ops.identity(x)

        def fn(x):
            return array_ops.identity(x)

        base = math_ops.range(100)
        for input_size in [10, 100, 1000, 10000]:
            num_iters = 100000 // input_size
            map_defun_op = map_defun.map_defun(defun, [base], [dtypes.int32],
                                               [()])
            map_fn_op = map_fn.map_fn(fn, base)

            self._run(map_defun_op,
                      "with_defun_size_%d" % input_size,
                      num_iters=num_iters)
            self._run(map_fn_op,
                      "without_defun_size_%d" % input_size,
                      num_iters=num_iters)
Exemplo n.º 23
0
 def testMapEmptyTensor(self):
     with self.cached_session():
         map_return = map_fn.map_fn(lambda x: array_ops.zeros([3, 2]),
                                    constant_op.constant([]))
         self.assertAllEqual([0, 3, 2], map_return.get_shape().dims)
         self.assertAllEqual([0, 3, 2], self.evaluate(map_return).shape)
Exemplo n.º 24
0
 def testMapUnknownShape(self):
     x = array_ops.placeholder(dtypes.float32)
     y = map_fn.map_fn(lambda e: e, x)
     self.assertIs(None, y.get_shape().dims)
Exemplo n.º 25
0
 def testMap_SimpleNotTensor(self):
     nums = np.array([1, 2, 3, 4, 5, 6])
     r = map_fn.map_fn(lambda x: math_ops.multiply(math_ops.add(x, 3), 2),
                       nums)
     self.assertAllEqual(np.array([(x + 3) * 2 for x in nums]),
                         self.evaluate(r))
Exemplo n.º 26
0
def norm(tensor,
         ord='euclidean',
         axis=None,
         keepdims=None,
         name=None,
         keep_dims=None):
    r"""Computes the norm of vectors, matrices, and tensors.

  This function can compute several different vector norms (the 1-norm, the
  Euclidean or 2-norm, the inf-norm, and in general the p-norm for p > 0) and
  matrix norms (Frobenius, 1-norm, 2-norm and inf-norm).

  Args:
    tensor: `Tensor` of types `float32`, `float64`, `complex64`, `complex128`
    ord: Order of the norm. Supported values are 'fro', 'euclidean',
      `1`, `2`, `np.inf` and any positive real number yielding the corresponding
      p-norm. Default is 'euclidean' which is equivalent to Frobenius norm if
      `tensor` is a matrix and equivalent to 2-norm for vectors.
      Some restrictions apply:
        a) The Frobenius norm `fro` is not defined for vectors,
        b) If axis is a 2-tuple (matrix norm), only 'euclidean', 'fro', `1`,
           `2`, `np.inf` are supported.
      See the description of `axis` on how to compute norms for a batch of
      vectors or matrices stored in a tensor.
    axis: If `axis` is `None` (the default), the input is considered a vector
      and a single vector norm is computed over the entire set of values in the
      tensor, i.e. `norm(tensor, ord=ord)` is equivalent to
      `norm(reshape(tensor, [-1]), ord=ord)`.
      If `axis` is a Python integer, the input is considered a batch of vectors,
      and `axis` determines the axis in `tensor` over which to compute vector
      norms.
      If `axis` is a 2-tuple of Python integers it is considered a batch of
      matrices and `axis` determines the axes in `tensor` over which to compute
      a matrix norm.
      Negative indices are supported. Example: If you are passing a tensor that
      can be either a matrix or a batch of matrices at runtime, pass
      `axis=[-2,-1]` instead of `axis=None` to make sure that matrix norms are
      computed.
    keepdims: If True, the axis indicated in `axis` are kept with size 1.
      Otherwise, the dimensions in `axis` are removed from the output shape.
    name: The name of the op.
    keep_dims: Deprecated alias for `keepdims`.

  Returns:
    output: A `Tensor` of the same type as tensor, containing the vector or
      matrix norms. If `keepdims` is True then the rank of output is equal to
      the rank of `tensor`. Otherwise, if `axis` is none the output is a scalar,
      if `axis` is an integer, the rank of `output` is one less than the rank
      of `tensor`, if `axis` is a 2-tuple the rank of `output` is two less
      than the rank of `tensor`.

  Raises:
    ValueError: If `ord` or `axis` is invalid.

  @compatibility(numpy)
  Mostly equivalent to numpy.linalg.norm.
  Not supported: ord <= 0, 2-norm for matrices, nuclear norm.
  Other differences:
    a) If axis is `None`, treats the flattened `tensor` as a vector
     regardless of rank.
    b) Explicitly supports 'euclidean' norm as the default, including for
     higher order tensors.
  @end_compatibility
  """
    keepdims = deprecation.deprecated_argument_lookup('keepdims', keepdims,
                                                      'keep_dims', keep_dims)
    if keepdims is None:
        keepdims = False

    is_matrix_norm = ((isinstance(axis, tuple) or isinstance(axis, list))
                      and len(axis) == 2)
    if is_matrix_norm:
        axis = tuple(axis)
        if (not isinstance(axis[0], int) or not isinstance(axis[1], int)
                or axis[0] == axis[1]):
            raise ValueError(
                "'axis' must be None, an integer, or a tuple of 2 unique integers"
            )
        supported_matrix_norms = ['euclidean', 'fro', 1, 2, np.inf]
        if ord not in supported_matrix_norms:
            raise ValueError(
                "'ord' must be a supported matrix norm in %s, got %s" %
                (supported_matrix_norms, ord))
    else:
        if not (isinstance(axis, int) or axis is None):
            raise ValueError(
                "'axis' must be None, an integer, or a tuple of 2 unique integers"
            )

        supported_vector_norms = ['euclidean', 1, 2, np.inf]
        if (not np.isreal(ord)
                or ord <= 0) and ord not in supported_vector_norms:
            raise ValueError("'ord' must be a supported vector norm, got %s" %
                             ord)
        if axis is not None:
            axis = (axis, )

    with ops.name_scope(name, 'norm', [tensor]):
        tensor = ops.convert_to_tensor(tensor)

        if ord in ['fro', 'euclidean', 2, 2.0]:
            if is_matrix_norm and ord in [2, 2.0]:
                rank = array_ops.rank(tensor)
                positive_axis = map_fn.map_fn(
                    lambda i: control_flow_ops.cond(i >= 0, lambda: i, lambda:
                                                    i + rank),
                    ops.convert_to_tensor(axis))
                axes = math_ops.range(rank)
                perm_before = array_ops.concat([
                    array_ops.setdiff1d(axes, positive_axis)[0], positive_axis
                ],
                                               axis=0)
                perm_after = map_fn.map_fn(
                    lambda i: math_ops.cast(array_ops.squeeze(
                        array_ops.where_v2(math_ops.equal(perm_before, i))),
                                            dtype=dtypes.int32), axes)
                permed = array_ops.transpose(tensor, perm=perm_before)
                matrix_2_norm = array_ops.expand_dims(math_ops.reduce_max(
                    math_ops.abs(
                        gen_linalg_ops.svd(permed, compute_uv=False)[0]),
                    axis=-1,
                    keepdims=True),
                                                      axis=-1)
                result = array_ops.transpose(matrix_2_norm, perm=perm_after)
            else:
                result = math_ops.sqrt(
                    math_ops.reduce_sum(tensor * math_ops.conj(tensor),
                                        axis,
                                        keepdims=True))
                # TODO(rmlarsen): Replace with the following, once gradients are defined
                # result = math_ops.reduce_euclidean_norm(tensor, axis, keepdims=True)
        else:
            result = math_ops.abs(tensor)
            if ord == 1:
                sum_axis = None if axis is None else axis[0]
                result = math_ops.reduce_sum(result, sum_axis, keepdims=True)
                if is_matrix_norm:
                    result = math_ops.reduce_max(result,
                                                 axis[-1],
                                                 keepdims=True)
            elif ord == np.inf:
                if is_matrix_norm:
                    result = math_ops.reduce_sum(result,
                                                 axis[1],
                                                 keepdims=True)
                max_axis = None if axis is None else axis[0]
                result = math_ops.reduce_max(result, max_axis, keepdims=True)
            else:
                # General p-norms (positive p only)
                result = math_ops.pow(
                    math_ops.reduce_sum(math_ops.pow(result, ord),
                                        axis,
                                        keepdims=True), 1.0 / ord)
        if not keepdims:
            result = array_ops.squeeze(result, axis)
        return result
Exemplo n.º 27
0
 def build_dataset(row, num):
     # pylint: disable=g-long-lambda
     dataset = dataset_ops.Dataset.from_tensors(
         row).map(lambda elems: map_fn.map_fn(
             lambda x: control_map_fn(x, num), elems))
     return self.getNext(dataset)
Exemplo n.º 28
0
def lu_reconstruct(lower_upper, perm, validate_args=False, name=None):
    """The reconstruct one or more matrices from their LU decomposition(s).

  Args:
    lower_upper: `lu` as returned by `tf.linalg.lu`, i.e., if `matmul(P,
      matmul(L, U)) = X` then `lower_upper = L + U - eye`.
    perm: `p` as returned by `tf.linag.lu`, i.e., if `matmul(P, matmul(L, U)) =
      X` then `perm = argmax(P)`.
    validate_args: Python `bool` indicating whether arguments should be checked
      for correctness.
      Default value: `False` (i.e., don't validate arguments).
    name: Python `str` name given to ops managed by this object.
      Default value: `None` (i.e., 'lu_reconstruct').

  Returns:
    x: The original input to `tf.linalg.lu`, i.e., `x` as in,
      `lu_reconstruct(*tf.linalg.lu(x))`.

  #### Examples

  ```python
  import numpy as np
  import tensorflow as tf
  import tensorflow_probability as tfp

  x = [[[3., 4], [1, 2]],
       [[7., 8], [3, 4]]]
  x_reconstructed = tf.linalg.lu_reconstruct(*tf.linalg.lu(x))
  tf.assert_near(x, x_reconstructed)
  # ==> True
  ```

  """
    with ops.name_scope(name or 'lu_reconstruct'):
        lower_upper = ops.convert_to_tensor(lower_upper,
                                            dtype_hint=dtypes.float32,
                                            name='lower_upper')
        perm = ops.convert_to_tensor(perm,
                                     dtype_hint=dtypes.int32,
                                     name='perm')

        assertions = lu_reconstruct_assertions(lower_upper, perm,
                                               validate_args)
        if assertions:
            with ops.control_dependencies(assertions):
                lower_upper = array_ops.identity(lower_upper)
                perm = array_ops.identity(perm)

        shape = array_ops.shape(lower_upper)

        lower = set_diag(band_part(lower_upper, num_lower=-1, num_upper=0),
                         array_ops.ones(shape[:-1], dtype=lower_upper.dtype))
        upper = band_part(lower_upper, num_lower=0, num_upper=-1)
        x = math_ops.matmul(lower, upper)

        if (lower_upper.shape is None or lower_upper.shape.rank is None
                or lower_upper.shape.rank != 2):
            # We either don't know the batch rank or there are >0 batch dims.
            batch_size = math_ops.reduce_prod(shape[:-2])
            d = shape[-1]
            x = array_ops.reshape(x, [batch_size, d, d])
            perm = array_ops.reshape(perm, [batch_size, d])
            perm = map_fn.map_fn(array_ops.invert_permutation, perm)
            batch_indices = array_ops.broadcast_to(
                math_ops.range(batch_size)[:, array_ops.newaxis],
                [batch_size, d])
            x = array_ops.gather_nd(
                x, array_ops.stack([batch_indices, perm], axis=-1))
            x = array_ops.reshape(x, shape)
        else:
            x = array_ops.gather(x, array_ops.invert_permutation(perm))

        x.set_shape(lower_upper.shape)
        return x
Exemplo n.º 29
0
 def testMapUnknownShape(self):
   x = array_ops.placeholder(dtypes.float32)
   y = map_fn.map_fn(lambda e: e, x)
   self.assertIs(None, y.get_shape().dims)
Exemplo n.º 30
0
 def build_dataset(row, num):
   # pylint: disable=g-long-lambda
   dataset = dataset_ops.Dataset.from_tensors(
       row).map(lambda elems: map_fn.map_fn(
           lambda x: control_map_fn(x, num), elems))
   return self.getNext(dataset)
Exemplo n.º 31
0
 def testUseStepContainerInMap(self):
   row = np.arange(6)
   dataset = dataset_ops.Dataset.from_tensors(
       row).map(lambda elems: map_fn.map_fn(lambda x: x * x, elems))
   self.assertDatasetProduces(dataset, expected_output=[row**2])
Exemplo n.º 32
0
 def testMapEmptyScalar(self):
   map_return = map_fn.map_fn(lambda x: 1, constant_op.constant([]))
   self.assertAllEqual([0], map_return.get_shape().dims)
   self.assertAllEqual([0], self.evaluate(map_return).shape)
Exemplo n.º 33
0
 def testMapOverScalarErrors(self):
   with self.assertRaisesRegexp(ValueError, "not scalars"):
     map_fn.map_fn(lambda x: x, [1, 2])
   with self.assertRaisesRegexp(ValueError, "not a scalar"):
     map_fn.map_fn(lambda x: x, 1)
Exemplo n.º 34
0
 def testMapOverScalarErrors(self):
     with self.assertRaisesRegexp(ValueError, "not scalars"):
         map_fn.map_fn(lambda x: x, [1, 2])
     with self.assertRaisesRegexp(ValueError, "not a scalar"):
         map_fn.map_fn(lambda x: x, 1)
Exemplo n.º 35
0
def kernel_classifier_distance_and_std_from_activations(real_activations,
                                                        generated_activations,
                                                        max_block_size=1024,
                                                        dtype=None):
  """Kernel "classifier" distance for evaluating a generative model.

  This methods computes the kernel classifier distance from activations of
  real images and generated images. This can be used independently of the
  kernel_classifier_distance() method, especially in the case of using large
  batches during evaluation where we would like to precompute all of the
  activations before computing the classifier distance, or if we want to
  compute multiple metrics based on the same images. It also returns a rough
  estimate of the standard error of the estimator.

  This technique is described in detail in https://arxiv.org/abs/1801.01401.
  Given two distributions P and Q of activations, this function calculates

      E_{X, X' ~ P}[k(X, X')] + E_{Y, Y' ~ Q}[k(Y, Y')]
        - 2 E_{X ~ P, Y ~ Q}[k(X, Y)]

  where k is the polynomial kernel

      k(x, y) = ( x^T y / dimension + 1 )^3.

  This captures how different the distributions of real and generated images'
  visual features are. Like the Frechet distance (and unlike the Inception
  score), this is a true distance and incorporates information about the
  target images. Unlike the Frechet score, this function computes an
  *unbiased* and asymptotically normal estimator, which makes comparing
  estimates across models much more intuitive.

  The estimator used takes time quadratic in max_block_size. Larger values of
  max_block_size will decrease the variance of the estimator but increase the
  computational cost. This differs slightly from the estimator used by the
  original paper; it is the block estimator of https://arxiv.org/abs/1307.1954.
  The estimate of the standard error will also be more reliable when there are
  more blocks, i.e. when max_block_size is smaller.

  NOTE: the blocking code assumes that real_activations and
  generated_activations are both in random order. If either is sorted in a
  meaningful order, the estimator will behave poorly.

  Args:
    real_activations: 2D Tensor containing activations of real data. Shape is
      [batch_size, activation_size].
    generated_activations: 2D Tensor containing activations of generated data.
      Shape is [batch_size, activation_size].
    max_block_size: integer, default 1024. The distance estimator splits samples
      into blocks for computational efficiency. Larger values are more
      computationally expensive but decrease the variance of the distance
      estimate. Having a smaller block size also gives a better estimate of the
      standard error.
    dtype: If not None, coerce activations to this dtype before computations.

  Returns:
   The Kernel Inception Distance. A floating-point scalar of the same type
     as the output of the activations.
   An estimate of the standard error of the distance estimator (a scalar of
     the same type).
  """

  real_activations.shape.assert_has_rank(2)
  generated_activations.shape.assert_has_rank(2)
  real_activations.shape[1].assert_is_compatible_with(
      generated_activations.shape[1])

  if dtype is None:
    dtype = real_activations.dtype
    assert generated_activations.dtype == dtype
  else:
    real_activations = math_ops.cast(real_activations, dtype)
    generated_activations = math_ops.cast(generated_activations, dtype)

  # Figure out how to split the activations into blocks of approximately
  # equal size, with none larger than max_block_size.
  n_r = array_ops.shape(real_activations)[0]
  n_g = array_ops.shape(generated_activations)[0]

  n_bigger = math_ops.maximum(n_r, n_g)
  n_blocks = math_ops.to_int32(math_ops.ceil(n_bigger / max_block_size))

  v_r = n_r // n_blocks
  v_g = n_g // n_blocks

  n_plusone_r = n_r - v_r * n_blocks
  n_plusone_g = n_g - v_g * n_blocks

  sizes_r = array_ops.concat([
      array_ops.fill([n_blocks - n_plusone_r], v_r),
      array_ops.fill([n_plusone_r], v_r + 1),
  ], 0)
  sizes_g = array_ops.concat([
      array_ops.fill([n_blocks - n_plusone_g], v_g),
      array_ops.fill([n_plusone_g], v_g + 1),
  ], 0)

  zero = array_ops.zeros([1], dtype=dtypes.int32)
  inds_r = array_ops.concat([zero, math_ops.cumsum(sizes_r)], 0)
  inds_g = array_ops.concat([zero, math_ops.cumsum(sizes_g)], 0)

  dim = math_ops.cast(real_activations.shape[1], dtype)

  def compute_kid_block(i):
    """Computes the ith block of the KID estimate."""
    r_s = inds_r[i]
    r_e = inds_r[i + 1]
    r = real_activations[r_s:r_e]
    m = math_ops.cast(r_e - r_s, dtype)

    g_s = inds_g[i]
    g_e = inds_g[i + 1]
    g = generated_activations[g_s:g_e]
    n = math_ops.cast(g_e - g_s, dtype)

    k_rr = (math_ops.matmul(r, r, transpose_b=True) / dim + 1)**3
    k_rg = (math_ops.matmul(r, g, transpose_b=True) / dim + 1)**3
    k_gg = (math_ops.matmul(g, g, transpose_b=True) / dim + 1)**3
    return (-2 * math_ops.reduce_mean(k_rg) +
            (math_ops.reduce_sum(k_rr) - math_ops.trace(k_rr)) / (m * (m - 1)) +
            (math_ops.reduce_sum(k_gg) - math_ops.trace(k_gg)) / (n * (n - 1)))

  ests = map_fn.map_fn(
      compute_kid_block, math_ops.range(n_blocks), dtype=dtype, back_prop=False)

  mn = math_ops.reduce_mean(ests)

  # nn_impl.moments doesn't use the Bessel correction, which we want here
  n_blocks_ = math_ops.cast(n_blocks, dtype)
  var = control_flow_ops.cond(
      math_ops.less_equal(n_blocks, 1),
      lambda: array_ops.constant(float('nan'), dtype=dtype),
      lambda: math_ops.reduce_sum(math_ops.square(ests - mn)) / (n_blocks_ - 1))

  return mn, math_ops.sqrt(var / n_blocks_)
Exemplo n.º 36
0
 def testMapEmptyTensor(self):
   with self.cached_session():
     map_return = map_fn.map_fn(lambda x: array_ops.zeros([3, 2]),
                                constant_op.constant([]))
     self.assertAllEqual([0, 3, 2], map_return.get_shape().dims)
     self.assertAllEqual([0, 3, 2], self.evaluate(map_return).shape)
Exemplo n.º 37
0
 def map_call(x):
     return map_fn.map_fn(test_function, x)
Exemplo n.º 38
0
def norm(tensor,
         ord='euclidean',
         axis=None,
         keepdims=None,
         name=None,
         keep_dims=None):
  r"""Computes the norm of vectors, matrices, and tensors.

  This function can compute several different vector norms (the 1-norm, the
  Euclidean or 2-norm, the inf-norm, and in general the p-norm for p > 0) and
  matrix norms (Frobenius, 1-norm, 2-norm and inf-norm).

  Args:
    tensor: `Tensor` of types `float32`, `float64`, `complex64`, `complex128`
    ord: Order of the norm. Supported values are 'fro', 'euclidean',
      `1`, `2`, `np.inf` and any positive real number yielding the corresponding
      p-norm. Default is 'euclidean' which is equivalent to Frobenius norm if
      `tensor` is a matrix and equivalent to 2-norm for vectors.
      Some restrictions apply:
        a) The Frobenius norm `fro` is not defined for vectors,
        b) If axis is a 2-tuple (matrix norm), only 'euclidean', 'fro', `1`,
           `2`, `np.inf` are supported.
      See the description of `axis` on how to compute norms for a batch of
      vectors or matrices stored in a tensor.
    axis: If `axis` is `None` (the default), the input is considered a vector
      and a single vector norm is computed over the entire set of values in the
      tensor, i.e. `norm(tensor, ord=ord)` is equivalent to
      `norm(reshape(tensor, [-1]), ord=ord)`.
      If `axis` is a Python integer, the input is considered a batch of vectors,
      and `axis` determines the axis in `tensor` over which to compute vector
      norms.
      If `axis` is a 2-tuple of Python integers it is considered a batch of
      matrices and `axis` determines the axes in `tensor` over which to compute
      a matrix norm.
      Negative indices are supported. Example: If you are passing a tensor that
      can be either a matrix or a batch of matrices at runtime, pass
      `axis=[-2,-1]` instead of `axis=None` to make sure that matrix norms are
      computed.
    keepdims: If True, the axis indicated in `axis` are kept with size 1.
      Otherwise, the dimensions in `axis` are removed from the output shape.
    name: The name of the op.
    keep_dims: Deprecated alias for `keepdims`.

  Returns:
    output: A `Tensor` of the same type as tensor, containing the vector or
      matrix norms. If `keepdims` is True then the rank of output is equal to
      the rank of `tensor`. Otherwise, if `axis` is none the output is a scalar,
      if `axis` is an integer, the rank of `output` is one less than the rank
      of `tensor`, if `axis` is a 2-tuple the rank of `output` is two less
      than the rank of `tensor`.

  Raises:
    ValueError: If `ord` or `axis` is invalid.

  @compatibility(numpy)
  Mostly equivalent to numpy.linalg.norm.
  Not supported: ord <= 0, 2-norm for matrices, nuclear norm.
  Other differences:
    a) If axis is `None`, treats the flattened `tensor` as a vector
     regardless of rank.
    b) Explicitly supports 'euclidean' norm as the default, including for
     higher order tensors.
  @end_compatibility
  """
  keepdims = deprecation.deprecated_argument_lookup('keepdims', keepdims,
                                                    'keep_dims', keep_dims)
  if keepdims is None:
    keepdims = False

  is_matrix_norm = ((isinstance(axis, tuple) or isinstance(axis, list)) and
                    len(axis) == 2)
  if is_matrix_norm:
    axis = tuple(axis)
    if (not isinstance(axis[0], int) or not isinstance(axis[1], int) or
        axis[0] == axis[1]):
      raise ValueError(
          "'axis' must be None, an integer, or a tuple of 2 unique integers")
    supported_matrix_norms = ['euclidean', 'fro', 1, 2, np.inf]
    if ord not in supported_matrix_norms:
      raise ValueError("'ord' must be a supported matrix norm in %s, got %s" %
                       (supported_matrix_norms, ord))
  else:
    if not (isinstance(axis, int) or axis is None):
      raise ValueError(
          "'axis' must be None, an integer, or a tuple of 2 unique integers")

    supported_vector_norms = ['euclidean', 1, 2, np.inf]
    if (not np.isreal(ord) or ord <= 0) and ord not in supported_vector_norms:
      raise ValueError("'ord' must be a supported vector norm, got %s" % ord)
    if axis is not None:
      axis = (axis,)

  with ops.name_scope(name, 'norm', [tensor]):
    tensor = ops.convert_to_tensor(tensor)

    if ord in ['fro', 'euclidean', 2, 2.0]:
      if is_matrix_norm and ord in [2, 2.0]:
        rank = array_ops.rank(tensor)
        positive_axis = map_fn.map_fn(
            lambda i: control_flow_ops.cond(i >= 0, lambda: i, lambda: i + rank),
            ops.convert_to_tensor(axis))
        axes = math_ops.range(rank)
        perm_before = array_ops.concat(
            [array_ops.setdiff1d(axes, positive_axis)[0], positive_axis],
            axis=0)
        perm_after = map_fn.map_fn(
            lambda i: math_ops.cast(
                array_ops.squeeze(
                    array_ops.where(math_ops.equal(perm_before, i))),
                dtype=dtypes.int32), axes)
        permed = array_ops.transpose(tensor, perm=perm_before)
        matrix_2_norm = array_ops.expand_dims(
            math_ops.reduce_max(
                math_ops.abs(gen_linalg_ops.svd(permed, compute_uv=False)[0]),
                axis=-1,
                keepdims=True),
            axis=-1)
        result = array_ops.transpose(matrix_2_norm, perm=perm_after)
      else:
        result = math_ops.sqrt(
            math_ops.reduce_sum(
                tensor * math_ops.conj(tensor), axis, keepdims=True))
    else:
      result = math_ops.abs(tensor)
      if ord == 1:
        sum_axis = None if axis is None else axis[0]
        result = math_ops.reduce_sum(result, sum_axis, keepdims=True)
        if is_matrix_norm:
          result = math_ops.reduce_max(result, axis[-1], keepdims=True)
      elif ord == np.inf:
        if is_matrix_norm:
          result = math_ops.reduce_sum(result, axis[1], keepdims=True)
        max_axis = None if axis is None else axis[0]
        result = math_ops.reduce_max(result, max_axis, keepdims=True)
      else:
        # General p-norms (positive p only)
        result = math_ops.pow(
            math_ops.reduce_sum(math_ops.pow(result, ord), axis, keepdims=True),
            1.0 / ord)
    if not keepdims:
      result = array_ops.squeeze(result, axis)
    return result
Exemplo n.º 39
0
 def testMapEmptyList(self):
     x = []
     with self.assertRaisesRegex(ValueError, r"elems must be a Tensor or"):
         _ = map_fn.map_fn(lambda e: e, x)
Exemplo n.º 40
0
 def testUseStepContainerInMap(self):
     row = np.arange(6)
     dataset = dataset_ops.Dataset.from_tensors(row).map(
         lambda elems: map_fn.map_fn(lambda x: x * x, elems))
     self.assertDatasetProduces(dataset, expected_output=[row**2])
Exemplo n.º 41
0
    def break_sentences_with_offsets(self, doc):
        """Splits `doc` into sentence fragments, returns text, start & end offsets.

    Example:
                      1                  1         2         3
            012345678901234    01234567890123456789012345678901234567
      doc: 'Hello...foo bar', 'Welcome to the U.S. don't be surprised'

      fragment_text: [
        ['Hello...', 'foo bar'],
        ['Welcome to the U.S.' , 'don't be surprised']
      ]
      start: [[0, 8],[0, 20]]
      end: [[8, 15],[19, 38]]

    Args:
      doc: A string `Tensor` of shape [batch] or [batch, 1].

    Returns:
      A tuple of (fragment_text, start, end) where:

      fragment_text: A string `RaggedTensor` of shape [batch, (num_sentences)]
      with each input broken up into its constituent sentence fragments.
      start: A int64 `RaggedTensor` of shape [batch, (num_sentences)]
        where each entry is the inclusive beginning byte offset of a sentence.
      end: A int64 `RaggedTensor` of shape [batch, (num_sentences)]
        where each entry is the exclusive ending byte offset of a sentence.
    """
        doc = ragged_tensor.convert_to_tensor_or_ragged_tensor(doc)

        if doc.shape.ndims > 1:
            if not ragged_tensor.is_ragged(doc):
                doc = ragged_tensor.RaggedTensor.from_tensor(doc)
            doc_flat = doc.flat_values
        else:
            doc_flat = doc

        # Run sentence fragmenter op v2
        fragment = gen_state_based_sentence_breaker_op.sentence_fragments_v2(
            doc_flat)
        start, end, properties, terminal_punc_token, row_lengths = fragment

        # Pack and create `RaggedTensor`s
        start, end, properties, terminal_punc_token = tuple(
            ragged_tensor.RaggedTensor.from_row_lengths(value, row_lengths)
            for value in [start, end, properties, terminal_punc_token])

        # Helper for use within map_fn (function must only take in one argument)
        def _substring(x):
            s, pos, length = x
            return string_ops.substr(s, pos, length)

        # Extract fragment text using offsets
        fragment_text = map_fn.map_fn(
            _substring, (doc_flat, start, math_ops.subtract(end, start)),
            fn_output_signature=ragged_tensor.RaggedTensorSpec(
                shape=[None], dtype=dtypes.string),
            infer_shape=False,
            dtype=dtypes.string)

        # Repack back into original shape (if necessary)
        if doc.shape.ndims == 1:
            return fragment_text, start, end

        if ragged_tensor.is_ragged(doc):
            fragment_text = ragged_tensor.RaggedTensor.from_row_lengths(
                fragment_text, doc.row_lengths())
            start = ragged_tensor.RaggedTensor.from_row_lengths(
                start, doc.row_lengths())
            end = ragged_tensor.RaggedTensor.from_row_lengths(
                end, doc.row_lengths())
            return fragment_text, start, end
        else:
            fragment_text = ragged_tensor.RaggedTensor.from_uniform_row_length(
                fragment_text, doc.shape[-1])
            start = ragged_tensor.RaggedTensor.from_uniform_row_length(
                start, doc.shape[-1])
            end = ragged_tensor.RaggedTensor.from_uniform_row_length(
                end, doc.shape[-1])
            return fragment_text, start, end
Exemplo n.º 42
0
 def fn(x):
     return map_fn.map_fn(lambda y: y * array_ops.transpose(y),
                          x,
                          parallel_iterations=10)
Exemplo n.º 43
0
def _matmul_3d_with_map_fn(a, b, **kwargs):
  """Multiplies batches of 2D matrices using map_fn.

  `output[n, i, k]` = sum_j (a[n, i, j] * b[n, j, k])` (for all `n`, `i`, `k`).

  Requires that `a[n, i].nrows()` == `b[n].nrows()` (for all `n` and `i`).

  Args:
    a: A 3D Tensor or RaggedTensor with `shape=[B, I, J]`, where dimensions `I`
      and `J` may be ragged.
    b: A 3D Tensor or RaggedTensor with `shape=[B, J, K]`, where dimensions `J`
      and `K` may be ragged.
    **kwargs: Additional arguments for `tf.matmul` (e.g. transpose_a).

  Returns:
    A 3D RaggedTensor with `shape=[B, (I), (K)]`.
  """
  # Determine the ragged rank of the result.  In the normal case, we have:
  #   [B, I, J] * [B, J, K] -> [B, I, K]
  # Or if we're using transpose_b, then we have:
  #   [B, I, J] * [B, K, J] -> [B, I, K]
  # In either case, output_ragged_rank=2 iff the K dimension is ragged.
  if (isinstance(b, ragged_tensor.RaggedTensor) and
      (b.ragged_rank == 2 or kwargs.get('transpose_b') or
       kwargs.get('adjoint_b'))):
    output_ragged_rank = 2
  else:
    output_ragged_rank = 1

  def single_batch_matmul(x):
    out = _matmul_2d(x[0], x[1], **kwargs)
    if output_ragged_rank == 2:
      out = ragged_tensor.RaggedTensor.from_tensor(out)
    return out

  fn_out_shape = None  # Figure out proper shape.
  row_splits_dtype = (
      a.row_splits.dtype
      if isinstance(a, ragged_tensor.RaggedTensor) else b.row_splits.dtype)
  output_type = kwargs['output_type']
  if output_type is None:
    output_type = a.dtype
  spec = ragged_tensor.RaggedTensorSpec(
      shape=fn_out_shape,
      dtype=output_type,
      ragged_rank=output_ragged_rank - 1,
      row_splits_dtype=row_splits_dtype)
  result = map_fn.map_fn(
      single_batch_matmul, elems=(a, b), fn_output_signature=spec)

  # map_fn loses shape information; restore it, where possible.
  # pylint: disable=protected-access
  if kwargs.get('transpose_a') or kwargs.get('adjoint_a'):
    result._set_shape(a.shape[:-2] + a.shape[-1:] + [None])
  else:
    result._set_shape(a.shape[:-2] + a.shape[-2:-1] + [None])
  if kwargs.get('transpose_b') or kwargs.get('adjoint_b'):
    result._set_shape(b.shape[:-2] + [None] + b.shape[-2:-1])
  else:
    result._set_shape(b.shape[:-2] + [None] + b.shape[-1:])

  return result
Exemplo n.º 44
0
 def _predicate(xs):
     squared_xs = map_fn.map_fn(lambda x: x * x, xs)
     summed = math_ops.reduce_sum(squared_xs)
     return math_ops.equal(summed, 1 + 4 + 9)
Exemplo n.º 45
0
def add_stargan_image_summaries(stargan_model,
                                num_images=2,
                                display_diffs=False):
    """Adds image summaries to see StarGAN image results.

  If display_diffs is True, each image result has `2` rows and `num_domains + 1`
  columns.
  The first row looks like:
    [original_image, transformed_to_domain_0, transformed_to_domain_1, ...]
  The second row looks like:
    [no_modification_baseline, transformed_to_domain_0-original_image, ...]
  If display_diffs is False, only the first row is shown.

  IMPORTANT:
    Since the model originally does not transformed the image to every domains,
    we will transform them on-the-fly within this function in parallel.

  Args:
    stargan_model: A StarGANModel tuple.
    num_images: The number of examples/images to be transformed and shown.
    display_diffs: Also display the difference between generated and target.

  Raises:
    ValueError: If input_data is not images.
    ValueError: If input_data_domain_label is not rank 2.
    ValueError: If dimension 2 of input_data_domain_label is not fully defined.
  """

    _assert_is_image(stargan_model.input_data)
    stargan_model.input_data_domain_label.shape.assert_has_rank(2)
    stargan_model.input_data_domain_label.shape[1:].assert_is_fully_defined()

    num_domains = stargan_model.input_data_domain_label.get_shape().as_list(
    )[-1]

    def _build_image(image):
        """Helper function to create a result for each image on the fly."""

        # Expand the first dimension as batch_size = 1.
        images = array_ops.expand_dims(image, axis=0)

        # Tile the image num_domains times, so we can get all transformed together.
        images = array_ops.tile(images, [num_domains, 1, 1, 1])

        # Create the targets to 0, 1, 2, ..., num_domains-1.
        targets = array_ops.one_hot(list(range(num_domains)), num_domains)

        with variable_scope.variable_scope(stargan_model.generator_scope,
                                           reuse=True):

            # Add the original image.
            output_images_list = [image]

            # Generate the image and add to the list.
            gen_images = stargan_model.generator_fn(images, targets)
            gen_images_list = array_ops.split(gen_images, num_domains)
            gen_images_list = [
                array_ops.squeeze(img, axis=0) for img in gen_images_list
            ]
            output_images_list.extend(gen_images_list)

            # Display diffs.
            if display_diffs:
                diff_images = gen_images - images
                diff_images_list = array_ops.split(diff_images, num_domains)
                diff_images_list = [
                    array_ops.squeeze(img, axis=0) for img in diff_images_list
                ]
                output_images_list.append(array_ops.zeros_like(image))
                output_images_list.extend(diff_images_list)

            # Create the final image.
            final_image = eval_utils.image_reshaper(output_images_list,
                                                    num_cols=num_domains + 1)

        # Reduce the first rank.
        return array_ops.squeeze(final_image, axis=0)

    summary.image('stargan_image_generation',
                  map_fn.map_fn(_build_image,
                                stargan_model.input_data[:num_images],
                                parallel_iterations=num_images,
                                back_prop=False,
                                swap_memory=True),
                  max_outputs=num_images)
Exemplo n.º 46
0
 def testMapShape(self):
     x = constant_op.constant([[1, 2, 3], [4, 5, 6]])
     y = map_fn.map_fn(lambda e: e, x)
     self.assertAllEqual(y.get_shape(), self.evaluate(y).shape)
Exemplo n.º 47
0
    def _verifyLu(self, x, output_idx_type=dtypes.int64):
        # Verify that Px = LU.
        with test_util.use_gpu():

            lu, perm = linalg_ops.lu(x, output_idx_type=output_idx_type)

            # Prepare the lower factor of shape num_rows x num_rows
            lu_shape = np.array(lu.shape.as_list())
            batch_shape = lu_shape[:-2]
            num_rows = lu_shape[-2]
            num_cols = lu_shape[-1]

            lower = array_ops.matrix_band_part(lu, -1, 0)

            if num_rows > num_cols:
                eye = linalg_ops.eye(num_rows,
                                     batch_shape=batch_shape,
                                     dtype=lower.dtype)
                lower = array_ops.concat([lower, eye[..., num_cols:]], axis=-1)
            elif num_rows < num_cols:
                lower = lower[..., :num_rows]

            # Fill the diagonal with ones.
            ones_diag = array_ops.ones(np.append(batch_shape, num_rows),
                                       dtype=lower.dtype)
            lower = array_ops.matrix_set_diag(lower, ones_diag)

            # Prepare the upper factor.
            upper = array_ops.matrix_band_part(lu, 0, -1)

            verification = math_ops.matmul(lower, upper)

            # Permute the rows of product of the Cholesky factors.
            if num_rows > 0:
                # Reshape the product of the triangular factors and permutation indices
                # to a single batch dimension. This makes it easy to apply
                # invert_permutation and gather_nd ops.
                perm_reshaped = array_ops.reshape(perm, [-1, num_rows])
                verification_reshaped = array_ops.reshape(
                    verification, [-1, num_rows, num_cols])
                # Invert the permutation in each batch.
                inv_perm_reshaped = map_fn.map_fn(array_ops.invert_permutation,
                                                  perm_reshaped)
                batch_size = perm_reshaped.shape.as_list()[0]
                # Prepare the batch indices with the same shape as the permutation.
                # The corresponding batch index is paired with each of the `num_rows`
                # permutation indices.
                batch_indices = math_ops.cast(array_ops.broadcast_to(
                    math_ops.range(batch_size)[:, None], perm_reshaped.shape),
                                              dtype=output_idx_type)
                permuted_verification_reshaped = array_ops.gather_nd(
                    verification_reshaped,
                    array_ops.stack([batch_indices, inv_perm_reshaped],
                                    axis=-1))

                # Reshape the verification matrix back to the original shape.
                verification = array_ops.reshape(
                    permuted_verification_reshaped, lu_shape)

            self._verifyLuBase(x, lower, upper, perm, verification,
                               output_idx_type)
Exemplo n.º 48
0
 def testMapEmptyScalar(self):
     map_return = map_fn.map_fn(lambda x: 1, constant_op.constant([]))
     self.assertAllEqual([0], map_return.get_shape().dims)
     self.assertAllEqual([0], self.evaluate(map_return).shape)
Exemplo n.º 49
0
 def _logSumExpMap(self, x):
   return map_fn.map_fn(
       lambda i: math_ops.reduce_logsumexp(x[:i + 1]),
       math_ops.range(array_ops.shape(x)[0]),
       dtype=x.dtype)
Exemplo n.º 50
0
 def testMapDtypeEager(self):
     with context.eager_mode():
         dtype = map_fn.map_fn(lambda x: constant_op.constant(""),
                               constant_op.constant([]),
                               dtype=dtypes.string).dtype
         self.assertEqual(dtype, dtypes.string)
Exemplo n.º 51
0
def kernel_classifier_distance_and_std_from_activations(
        real_activations,
        generated_activations,
        max_block_size=1024,
        dtype=None):
    """Kernel "classifier" distance for evaluating a generative model.

  This methods computes the kernel classifier distance from activations of
  real images and generated images. This can be used independently of the
  kernel_classifier_distance() method, especially in the case of using large
  batches during evaluation where we would like to precompute all of the
  activations before computing the classifier distance, or if we want to
  compute multiple metrics based on the same images. It also returns a rough
  estimate of the standard error of the estimator.

  This technique is described in detail in https://arxiv.org/abs/1801.01401.
  Given two distributions P and Q of activations, this function calculates

      E_{X, X' ~ P}[k(X, X')] + E_{Y, Y' ~ Q}[k(Y, Y')]
        - 2 E_{X ~ P, Y ~ Q}[k(X, Y)]

  where k is the polynomial kernel

      k(x, y) = ( x^T y / dimension + 1 )^3.

  This captures how different the distributions of real and generated images'
  visual features are. Like the Frechet distance (and unlike the Inception
  score), this is a true distance and incorporates information about the
  target images. Unlike the Frechet score, this function computes an
  *unbiased* and asymptotically normal estimator, which makes comparing
  estimates across models much more intuitive.

  The estimator used takes time quadratic in max_block_size. Larger values of
  max_block_size will decrease the variance of the estimator but increase the
  computational cost. This differs slightly from the estimator used by the
  original paper; it is the block estimator of https://arxiv.org/abs/1307.1954.
  The estimate of the standard error will also be more reliable when there are
  more blocks, i.e. when max_block_size is smaller.

  NOTE: the blocking code assumes that real_activations and
  generated_activations are both in random order. If either is sorted in a
  meaningful order, the estimator will behave poorly.

  Args:
    real_activations: 2D Tensor containing activations of real data. Shape is
      [batch_size, activation_size].
    generated_activations: 2D Tensor containing activations of generated data.
      Shape is [batch_size, activation_size].
    max_block_size: integer, default 1024. The distance estimator splits samples
      into blocks for computational efficiency. Larger values are more
      computationally expensive but decrease the variance of the distance
      estimate. Having a smaller block size also gives a better estimate of the
      standard error.
    dtype: If not None, coerce activations to this dtype before computations.

  Returns:
   The Kernel Inception Distance. A floating-point scalar of the same type
     as the output of the activations.
   An estimate of the standard error of the distance estimator (a scalar of
     the same type).
  """

    real_activations.shape.assert_has_rank(2)
    generated_activations.shape.assert_has_rank(2)
    real_activations.shape[1].assert_is_compatible_with(
        generated_activations.shape[1])

    if dtype is None:
        dtype = real_activations.dtype
        assert generated_activations.dtype == dtype
    else:
        real_activations = math_ops.cast(real_activations, dtype)
        generated_activations = math_ops.cast(generated_activations, dtype)

    # Figure out how to split the activations into blocks of approximately
    # equal size, with none larger than max_block_size.
    n_r = array_ops.shape(real_activations)[0]
    n_g = array_ops.shape(generated_activations)[0]

    n_bigger = math_ops.maximum(n_r, n_g)
    n_blocks = math_ops.cast(math_ops.ceil(n_bigger / max_block_size),
                             dtypes.int32)

    v_r = n_r // n_blocks
    v_g = n_g // n_blocks

    n_plusone_r = n_r - v_r * n_blocks
    n_plusone_g = n_g - v_g * n_blocks

    sizes_r = array_ops.concat([
        array_ops.fill([n_blocks - n_plusone_r], v_r),
        array_ops.fill([n_plusone_r], v_r + 1),
    ], 0)
    sizes_g = array_ops.concat([
        array_ops.fill([n_blocks - n_plusone_g], v_g),
        array_ops.fill([n_plusone_g], v_g + 1),
    ], 0)

    zero = array_ops.zeros([1], dtype=dtypes.int32)
    inds_r = array_ops.concat([zero, math_ops.cumsum(sizes_r)], 0)
    inds_g = array_ops.concat([zero, math_ops.cumsum(sizes_g)], 0)

    dim = math_ops.cast(real_activations.shape[1], dtype)

    def compute_kid_block(i):
        """Computes the ith block of the KID estimate."""
        r_s = inds_r[i]
        r_e = inds_r[i + 1]
        r = real_activations[r_s:r_e]
        m = math_ops.cast(r_e - r_s, dtype)

        g_s = inds_g[i]
        g_e = inds_g[i + 1]
        g = generated_activations[g_s:g_e]
        n = math_ops.cast(g_e - g_s, dtype)

        k_rr = (math_ops.matmul(r, r, transpose_b=True) / dim + 1)**3
        k_rg = (math_ops.matmul(r, g, transpose_b=True) / dim + 1)**3
        k_gg = (math_ops.matmul(g, g, transpose_b=True) / dim + 1)**3
        return (-2 * math_ops.reduce_mean(k_rg) +
                (math_ops.reduce_sum(k_rr) - math_ops.trace(k_rr)) /
                (m * (m - 1)) +
                (math_ops.reduce_sum(k_gg) - math_ops.trace(k_gg)) / (n *
                                                                      (n - 1)))

    ests = map_fn.map_fn(compute_kid_block,
                         math_ops.range(n_blocks),
                         dtype=dtype,
                         back_prop=False)

    mn = math_ops.reduce_mean(ests)

    # nn_impl.moments doesn't use the Bessel correction, which we want here
    n_blocks_ = math_ops.cast(n_blocks, dtype)
    var = control_flow_ops.cond(
        math_ops.less_equal(n_blocks, 1),
        lambda: array_ops.constant(float('nan'), dtype=dtype),
        lambda: math_ops.reduce_sum(math_ops.square(ests - mn)) /
        (n_blocks_ - 1))

    return mn, math_ops.sqrt(var / n_blocks_)
 def step_fn(example):
     return map_fn.map_fn(embedding_lookup,
                          example,
                          fn_output_signature=dtypes.float32)
Exemplo n.º 53
0
 def testMapDtypeEager(self):
   with context.eager_mode():
     dtype = map_fn.map_fn(lambda x: constant_op.constant(""),
                           constant_op.constant([]),
                           dtype=dtypes.string).dtype
     self.assertEqual(dtype, dtypes.string)