コード例 #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 = functional_ops.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 = functional_ops.map_fn(double_scoped, elems)
        self.assertEqual(len(variables.trainable_variables()), 1)
        self.assertAllEqual(doubles, self.evaluate(r))
コード例 #2
0
 def testMapSparseTensor(self):
   with self.cached_session():
     with self.assertRaises(TypeError):
       functional_ops.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]))
コード例 #3
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
     functional_ops.map_fn(
         lambda x: ((x + 3) * 2, -(x + 3) * 2),
         nums,
         dtype=[dtypes.int64, dtypes.int64])
コード例 #4
0
 def compute_activations(elems):
   return functional_ops.map_fn(fn=classifier_fn,
                                elems=elems,
                                parallel_iterations=1,
                                back_prop=False,
                                swap_memory=True,
                                name='RunClassifier')
コード例 #5
0
 def testMap_SimpleNotTensor(self):
   with self.test_session():
     nums = np.array([1, 2, 3, 4, 5, 6])
     r = functional_ops.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))
コード例 #6
0
ファイル: multinomial.py プロジェクト: AndrewTwinz/tensorflow
  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 = functional_ops.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
コード例 #7
0
 def testMap_Simple(self):
   nums = [1, 2, 3, 4, 5, 6]
   elems = constant_op.constant(nums, name="data")
   r = functional_ops.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))
コード例 #8
0
ファイル: ctc_ops.py プロジェクト: JonathanRaiman/tensorflow
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 functional_ops.map_fn(
        _unique, labels, dtype=[dtypes.int64, dtypes.int32])
コード例 #9
0
ファイル: boolean_mask.py プロジェクト: 363158858/tensorflow
def sparse_boolean_mask(sparse_tensor, mask, name="sparse_boolean_mask"):
  """Boolean mask for `SparseTensor`s.

  Args:
    sparse_tensor: a `SparseTensor`.
    mask: a 1D boolean dense`Tensor` whose length is equal to the 0th dimension
      of `sparse_tensor`.
    name: optional name for this operation.
  Returns:
    A `SparseTensor` that contains row `k` of `sparse_tensor` iff `mask[k]` is
    `True`.
  """
  # TODO(jamieas): consider mask dimension > 1 for symmetry with `boolean_mask`.
  with ops.op_scope([sparse_tensor, mask], name):
    mask = ops.convert_to_tensor(mask)
    mask_rows = array_ops.where(mask)
    first_indices = array_ops.squeeze(array_ops.slice(sparse_tensor.indices,
                                                      [0, 0], [-1, 1]))

    # Identify indices corresponding to the rows identified by mask_rows.
    sparse_entry_matches = functional_ops.map_fn(
        lambda x: math_ops.equal(first_indices, x),
        mask_rows,
        dtype=dtypes.bool)
    # Combine the rows of index_matches to form a mask for the sparse indices
    # and values.
    to_retain = array_ops.reshape(
        functional_ops.foldl(math_ops.logical_or, sparse_entry_matches), [-1])

    return sparse_ops.sparse_retain(sparse_tensor, to_retain)
コード例 #10
0
  def compress(self, inputs):
    """Compress inputs and store their binary representations into strings.

    Args:
      inputs: `Tensor` with values to be compressed.

    Returns:
      String `Tensor` vector containing the compressed representation of each
      batch element of `inputs`.
    """
    with ops.name_scope(self._name_scope()):
      inputs = ops.convert_to_tensor(inputs)
      if not self.built:
        # Check input assumptions set before layer building, e.g. input rank.
        self._assert_input_compatibility(inputs)
        if self.dtype is None:
          self._dtype = inputs.dtype.base_dtype.name
        self.build(inputs.shape)

      # Check input assumptions set after layer building, e.g. input shape.
      if not context.executing_eagerly():
        self._assert_input_compatibility(inputs)

      ndim = self.input_spec.ndim
      channel_axis = self._channel_axis(ndim)
      # Tuple of slices for expanding dimensions of tensors below.
      slices = ndim * [None] + [slice(None)]
      slices[channel_axis] = slice(None)
      slices = tuple(slices)

      # Expand dimensions of CDF to input dimensions, keeping the channels along
      # the right dimension.
      cdf = self._quantized_cdf[slices[1:]]
      num_levels = array_ops.shape(cdf)[-1] - 1

      # Bring inputs to the right range by centering the range on the medians.
      half = constant_op.constant(.5, dtype=self.dtype)
      medians = array_ops.squeeze(self._medians, [1, 2])
      offsets = (math_ops.cast(num_levels // 2, self.dtype) + half) - medians
      # Expand offsets to input dimensions and add to inputs.
      values = inputs + offsets[slices[:-1]]

      # Clip to range and cast to integers. Because we have added .5 above, and
      # all values are positive, the cast effectively implements rounding.
      values = math_ops.maximum(values, half)
      values = math_ops.minimum(
          values, math_ops.cast(num_levels, self.dtype) - half)
      values = math_ops.cast(values, dtypes.int16)

      def loop_body(tensor):
        return coder_ops.range_encode(
            tensor, cdf, precision=self.range_coder_precision)
      strings = functional_ops.map_fn(
          loop_body, values, dtype=dtypes.string, back_prop=False)

      if not context.executing_eagerly():
        strings.set_shape(inputs.shape[:1])

      return strings
コード例 #11
0
 def testMap_MultiInputSingleOutput(self):
   nums = np.array([1, 2, 3, 4, 5, 6])
   r = functional_ops.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)
コード例 #12
0
 def testWhileAndTensorArray(self):
   with self.cached_session() as sess:
     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 = functional_ops.map_fn(lambda x: math_ops.multiply(x, param), y0)
     self.assertAllClose([2.0, 4.0, 6.0, 8.0, 10.0, 12.0], self.evaluate(r))
     r = gradients_impl.gradients(r, param)[0]
     self.assertAllClose(21.0, self.evaluate(r))
コード例 #13
0
ファイル: map_test.py プロジェクト: aeverall/tensorflow
 def build_dataset(row, num):
   # pylint: disable=g-long-lambda
   iterator = dataset_ops.make_initializable_iterator(
       dataset_ops.Dataset.from_tensors(row).map(
           lambda elems: functional_ops.map_fn(
               lambda x: control_map_fn(x, num), elems)))
   init_op = iterator.initializer
   get_next = iterator.get_next()
   return init_op, get_next
コード例 #14
0
def loop():
  random_seed.set_random_seed(0)
  x1 = random_ops.truncated_normal([1, 784], seed=0)
  x2 = random_ops.truncated_normal([1, 784], seed=0)
  x3 = random_ops.truncated_normal([1, 784], seed=0)
  x4 = random_ops.truncated_normal([1, 784], seed=0)
  elems = (x1, x2, x3, x4)
  outputs = functional_ops.map_fn(two_layer_model, elems, dtype=dtypes.float32)
  return outputs
コード例 #15
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 functional_ops.map_fn(lambda x: self._decode(x, image_format),
                                   image_buffer, dtype=self._dtype)
    else:
      return self._decode(image_buffer, image_format)
コード例 #16
0
def _loop_with_vec_and_4d():
  random_seed.set_random_seed(0)
  x1 = random_ops.truncated_normal([1, 784], seed=0)
  x2 = random_ops.truncated_normal([1, 784], seed=0)
  x3 = random_ops.truncated_normal([1, 784], seed=0)
  x4 = random_ops.truncated_normal([1, 784], seed=0)
  elems = (x1, x2, x3, x4)
  outputs = functional_ops.map_fn(
      _model_with_vec_and_4d, elems, dtype=dtypes.float32)
  return outputs
コード例 #17
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 = functional_ops.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))
コード例 #18
0
 def input_fn():
   starts = random_ops.random_uniform(
       [batch_size], maxval=(2 * np.pi), seed=seed)
   sin_curves = functional_ops.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
コード例 #19
0
 def testMap_SingleInputMultiOutput(self):
   nums = np.array([1, 2, 3, 4, 5, 6])
   r = functional_ops.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])
コード例 #20
0
 def testMap_MultiInputSameStructureOutput(self):
   nums = np.array([1, 2, 3, 4, 5, 6])
   r = functional_ops.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])
コード例 #21
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.

  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.
  """
  generated_images_list = array_ops.split(
      images, num_or_size_splits=num_batches)

  # Compute the classifier splits using the memory-efficient `map_fn`.
  logits = functional_ops.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)
  logits.shape.assert_has_rank(2)

  # Use maximum precision for best results.
  logits_dtype = logits.dtype
  if logits_dtype != dtypes.float64:
    logits = math_ops.cast(logits, dtypes.float64)

  p = nn_ops.softmax(logits)
  q = math_ops.reduce_mean(p, axis=0)
  kl = _kl_divergence(p, logits, q)
  kl.shape.assert_has_rank(1)
  log_score = math_ops.reduce_mean(kl)
  final_score = math_ops.exp(log_score)

  if logits_dtype != dtypes.float64:
    final_score = math_ops.cast(final_score, dtypes.float64)
  return final_score
コード例 #22
0
ファイル: map_test.py プロジェクト: aeverall/tensorflow
  def testUseStepContainerInMap(self):
    row = np.arange(6)
    iterator = dataset_ops.make_initializable_iterator(
        dataset_ops.Dataset.from_tensors(row)
        .map(lambda elems: functional_ops.map_fn(lambda x: x * x, elems)))
    init_op = iterator.initializer
    get_next = iterator.get_next()

    with self.cached_session() as sess:
      sess.run(init_op)
      self.assertAllEqual(row**2, sess.run(get_next))
      with self.assertRaises(errors.OutOfRangeError):
        sess.run(get_next)
コード例 #23
0
ファイル: ops.py プロジェクト: Ajaycs99/tensorflow
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 functional_ops.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 = functional_ops.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)
コード例 #24
0
  def benchmark_map_fn(self):
    with ops.Graph().as_default():
      b = 256
      params = 1000
      inp = random_ops.random_normal((b, params))
      map_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 = functional_ops.map_fn(map_fn, inp)
      pfor_output = pfor_map_fn(map_fn, inp)

      self._run(map_output, 100, name="tf_map_fn")
      self._run(pfor_output, 100, name="pfor_map_fn")
コード例 #25
0
ファイル: map_test.py プロジェクト: bunbutter/tensorflow
  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
    iterator = (
        dataset_ops.Dataset.from_tensors(row).map(
            lambda elems: functional_ops.map_fn(lambda x:
                                                control_map_fn(x, num), elems)
            ).make_initializable_iterator())
    # pylint: enable=g-long-lambda
    init_op = iterator.initializer
    get_next = iterator.get_next()

    with self.cached_session() as sess:
      sess.run(init_op)
      self.assertAllEqual([(x // 2 if x % 2 else x * 2) if
                           (num == 2 or num == 3) else x * 2 for x in row],
                          sess.run(get_next))
      with self.assertRaises(errors.OutOfRangeError):
        sess.run(get_next)
コード例 #26
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 clasifier_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 = functional_ops.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)
コード例 #27
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 map_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 = functional_ops.map_fn(map_fn, base)

      self._run(
          map_defun_op,
          "benchmarkMapDefun_size_%d" % input_size,
          num_iters=num_iters)
      self._run(
          map_fn_op, "benchmarkMapFn_size_%d" % input_size, num_iters=num_iters)
コード例 #28
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 = functional_ops.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 = functional_ops.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
コード例 #29
0
def kernel_classifier_distance_and_std_from_activations(
        real_activations,
        generated_activations,
        max_block_size=1024,
        dtype=None):
    # pylint: disable=no-member
    """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):
        'Compute 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 = functional_ops.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_)
コード例 #30
0
 def testUseStepContainerInMap(self):
     row = np.arange(6)
     dataset = dataset_ops.Dataset.from_tensors(row).map(
         lambda elems: functional_ops.map_fn(lambda x: x * x, elems))
     self.assertDatasetProduces(dataset, expected_output=[row**2])
コード例 #31
0
def frechet_classifier_distance(real_images,
                                generated_images,
                                classifier_fn,
                                num_batches=1):
    """Classifier distance for evaluating a conditional generative model.

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

  This technique is described in detail in https://arxiv.org/abs/1706.08500.
  Given two Gaussian distribution with means m and m_w and covariance matrices
  C and C_w, this function calcuates

  |m - m_w|^2 + Tr(C + C_w - 2(C * C_w)^(1/2))

  which captures how different the distributions of real images and generated
  images (or more accurately, their visual features) are. Note that unlike the
  Inception score, this is a true distance and utilizes information about real
  world images.

  Args:
    real_images: Real images to use to compute Frechet Inception distance.
    generated_images: Generated images to use to compute Frechet Inception
      distance.
    classifier_fn: A function that takes images and produces activations
      based on a classifier.
    num_batches: Number of batches to split images in to in order to
      efficiently run them through the classifier network.

  Returns:
    The Frechet Inception distance. A floating-point scalar.
  """

    real_images_list = array_ops.split(real_images,
                                       num_or_size_splits=num_batches)
    generated_images_list = array_ops.split(generated_images,
                                            num_or_size_splits=num_batches)

    imgs = array_ops.stack(real_images_list + generated_images_list)

    # Compute the activations using the memory-efficient `map_fn`.
    activations = functional_ops.map_fn(fn=classifier_fn,
                                        elems=imgs,
                                        parallel_iterations=1,
                                        back_prop=False,
                                        swap_memory=True,
                                        name='RunClassifier')

    # Split the activations by the real and generated images.
    real_a, gen_a = array_ops.split(activations, [num_batches, num_batches], 0)

    # Ensure the activations have the right shapes.
    real_a = array_ops.concat(array_ops.unstack(real_a), 0)
    gen_a = array_ops.concat(array_ops.unstack(gen_a), 0)
    real_a.shape.assert_has_rank(2)
    gen_a.shape.assert_has_rank(2)

    # Compute mean and covariance matrices of activations.
    m = math_ops.reduce_mean(real_a, 0)
    m_v = math_ops.reduce_mean(gen_a, 0)
    dim = math_ops.to_float(array_ops.shape(m)[0])
    sigma = math_ops.matmul(real_a - m, real_a - m, transpose_b=True) / dim
    sigma_v = math_ops.matmul(gen_a - m, gen_a - m, transpose_b=True) / dim

    # Take matrix square root of the product of covariance matrices.
    sqcc = _matrix_square_root(math_ops.matmul(sigma, sigma_v))

    # Compute the two components of FID.
    trace = math_ops.trace(sigma + sigma_v - 2.0 * sqcc)
    mean = math_ops.square(linalg_ops.norm(m - m_v))  # This uses the L2 norm.
    fid = trace + mean

    return fid
コード例 #32
0
 def _predicate(xs):
   squared_xs = functional_ops.map_fn(lambda x: x * x, xs)
   summed = math_ops.reduce_sum(squared_xs)
   return math_ops.equal(summed, 1 + 4 + 9)
コード例 #33
0
 def testMapEmptyScalar(self):
   map_return = functional_ops.map_fn(lambda x: 1, constant_op.constant([]))
   self.assertAllEqual([0], map_return.get_shape().dims)
   self.assertAllEqual([0], self.evaluate(map_return).shape)
コード例 #34
0
 def testMapShape(self):
   x = constant_op.constant([[1, 2, 3], [4, 5, 6]])
   y = functional_ops.map_fn(lambda e: e, x)
   self.assertAllEqual(y.get_shape(), self.evaluate(y).shape)
コード例 #35
0
 def _predicate(xs):
     squared_xs = functional_ops.map_fn(lambda x: x * x, xs)
     summed = math_ops.reduce_sum(squared_xs)
     return math_ops.equal(summed, 1 + 4 + 9)
コード例 #36
0
    def compress(self, inputs):
        """Compress inputs and store their binary representations into strings.

    Args:
      inputs: `Tensor` with values to be compressed.

    Returns:
      String `Tensor` vector containing the compressed representation of each
      batch element of `inputs`.
    """
        with ops.name_scope(self._name_scope()):
            inputs = ops.convert_to_tensor(inputs)
            if not self.built:
                # Check input assumptions set before layer building, e.g. input rank.
                input_spec.assert_input_compatibility(self.input_spec, inputs,
                                                      self.name)
                if self.dtype is None:
                    self._dtype = inputs.dtype.base_dtype.name
                self.build(inputs.shape)

            # Check input assumptions set after layer building, e.g. input shape.
            if not context.executing_eagerly():
                input_spec.assert_input_compatibility(self.input_spec, inputs,
                                                      self.name)

            ndim = self.input_spec.ndim
            channel_axis = self._channel_axis(ndim)
            # Tuple of slices for expanding dimensions of tensors below.
            slices = ndim * [None] + [slice(None)]
            slices[channel_axis] = slice(None)
            slices = tuple(slices)

            # Expand dimensions of CDF to input dimensions, keeping the channels along
            # the right dimension.
            cdf = self._quantized_cdf[slices[1:]]
            num_levels = array_ops.shape(cdf)[-1] - 1

            # Bring inputs to the right range by centering the range on the medians.
            half = constant_op.constant(.5, dtype=self.dtype)
            medians = array_ops.squeeze(self._medians, [1, 2])
            offsets = (math_ops.cast(num_levels // 2, self.dtype) +
                       half) - medians
            # Expand offsets to input dimensions and add to inputs.
            values = inputs + offsets[slices[:-1]]

            # Clip to range and cast to integers. Because we have added .5 above, and
            # all values are positive, the cast effectively implements rounding.
            values = math_ops.maximum(values, half)
            values = math_ops.minimum(
                values,
                math_ops.cast(num_levels, self.dtype) - half)
            values = math_ops.cast(values, dtypes.int16)

            def loop_body(tensor):
                return coder_ops.range_encode(
                    tensor, cdf, precision=self.range_coder_precision)

            strings = functional_ops.map_fn(loop_body,
                                            values,
                                            dtype=dtypes.string,
                                            back_prop=False)

            if not context.executing_eagerly():
                strings.set_shape(inputs.shape[:1])

            return strings
コード例 #37
0
 def testMapEmptyTensor(self):
     with self.test_session():
         map_return = functional_ops.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], map_return.eval().shape)
コード例 #38
0
            ])

            # FID TEST
            def resize_and_classify(x):
                INCEPTION_FINAL_POOL = 'pool_3:0'
                x = tf.image.resize_bilinear(x, [299, 299])
                return tf.contrib.gan.eval.run_inception(x, output_tensor=INCEPTION_FINAL_POOL)

            fid_real_final = x_50k
            fid_z_final = tf.constant(np.random.randn(50000, 128), dtype='float32')
            fid_z_final_list = array_ops.split(fid_z_final, num_or_size_splits=50000 // 100)
            fid_z_final_batches = array_ops.stack(fid_z_final_list)
            fid_gen_final = functional_ops.map_fn(
                fn=partial(generator, reuse=True),
                elems=fid_z_final_batches,
                parallel_iterations=1,
                back_prop=False,
                swap_memory=True,
                name='RunGenerator'
            )
            fid_gen_final = array_ops.concat(array_ops.unstack(fid_gen_final), 0)
            fid_final = tf.contrib.gan.eval.frechet_classifier_distance(
                fid_real_final,
                fid_gen_final,
                classifier_fn=resize_and_classify,
                num_batches=50000 // 100
            )

            fid_summary_final = tf.summary.merge([
                tf.summary.scalar('fid_final', fid_final)
            ])
コード例 #39
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',
                  functional_ops.map_fn(_build_image,
                                        stargan_model.input_data[:num_images],
                                        parallel_iterations=num_images,
                                        back_prop=False,
                                        swap_memory=True),
                  max_outputs=num_images)
コード例 #40
0
 def testMapOverScalarErrors(self):
     with self.assertRaisesRegexp(ValueError, "not scalars"):
         functional_ops.map_fn(lambda x: x, [1, 2])
     with self.assertRaisesRegexp(ValueError, "not a scalar"):
         functional_ops.map_fn(lambda x: x, 1)
コード例 #41
0
def frechet_classifier_distance(real_images,
                                generated_images,
                                classifier_fn,
                                num_batches=1):
    """Classifier distance for evaluating a generative model.

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

  This technique is described in detail in https://arxiv.org/abs/1706.08500.
  Given two Gaussian distribution with means m and m_w and covariance matrices
  C and C_w, this function calculates

  |m - m_w|^2 + Tr(C + C_w - 2(C * C_w)^(1/2))

  which captures how different the distributions of real images and generated
  images (or more accurately, their visual features) are. Note that unlike the
  Inception score, this is a true distance and utilizes information about real
  world images.

  Note that when computed using sample means and sample covariance matrices,
  Frechet distance is biased. It is more biased for small sample sizes. (e.g.
  even if the two distributions are the same, for a small sample size, the
  expected Frechet distance is large). It is important to use the same
  sample size to compute Frechet classifier distance when comparing two
  generative models.

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

  Args:
    real_images: Real images to use to compute Frechet Inception distance.
    generated_images: Generated images to use to compute Frechet Inception
      distance.
    classifier_fn: A function that takes images and produces activations
      based on a classifier.
    num_batches: Number of batches to split images in to in order to
      efficiently run them through the classifier network.

  Returns:
    The Frechet Inception distance. A floating-point scalar of the same type
    as the output of `classifier_fn`.
  """

    real_images_list = array_ops.split(real_images,
                                       num_or_size_splits=num_batches)
    generated_images_list = array_ops.split(generated_images,
                                            num_or_size_splits=num_batches)

    imgs = array_ops.stack(real_images_list + generated_images_list)

    # Compute the activations using the memory-efficient `map_fn`.
    activations = functional_ops.map_fn(fn=classifier_fn,
                                        elems=imgs,
                                        parallel_iterations=1,
                                        back_prop=False,
                                        swap_memory=True,
                                        name='RunClassifier')

    # Split the activations by the real and generated images.
    real_a, gen_a = array_ops.split(activations, [num_batches, num_batches], 0)

    # Ensure the activations have the right shapes.
    real_a = array_ops.concat(array_ops.unstack(real_a), 0)
    gen_a = array_ops.concat(array_ops.unstack(gen_a), 0)

    return frechet_classifier_distance_from_activations(real_a, gen_a)
コード例 #42
0
 def build_dataset(row, num):
     # pylint: disable=g-long-lambda
     dataset = dataset_ops.Dataset.from_tensors(row).map(
         lambda elems: functional_ops.map_fn(
             lambda x: control_map_fn(x, num), elems))
     return self.getNext(dataset)
コード例 #43
0
def frechet_classifier_distance(real_images,
                                generated_images,
                                classifier_fn,
                                num_batches=1):
  """Classifier distance for evaluating a generative model.

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

  This technique is described in detail in https://arxiv.org/abs/1706.08500.
  Given two Gaussian distribution with means m and m_w and covariance matrices
  C and C_w, this function calcuates

  |m - m_w|^2 + Tr(C + C_w - 2(C * C_w)^(1/2))

  which captures how different the distributions of real images and generated
  images (or more accurately, their visual features) are. Note that unlike the
  Inception score, this is a true distance and utilizes information about real
  world images.

  Note that when computed using sample means and sample covariance matrices,
  Frechet distance is biased. It is more biased for small sample sizes. (e.g.
  even if the two distributions are the same, for a small sample size, the
  expected Frechet distance is large). It is important to use the same
  sample size to compute frechet classifier distance when comparing two
  generative models.

  Args:
    real_images: Real images to use to compute Frechet Inception distance.
    generated_images: Generated images to use to compute Frechet Inception
      distance.
    classifier_fn: A function that takes images and produces activations
      based on a classifier.
    num_batches: Number of batches to split images in to in order to
      efficiently run them through the classifier network.

  Returns:
    The Frechet Inception distance. A floating-point scalar.
  """

  real_images_list = array_ops.split(
      real_images, num_or_size_splits=num_batches)
  generated_images_list = array_ops.split(
      generated_images, num_or_size_splits=num_batches)

  imgs = array_ops.stack(real_images_list + generated_images_list)

  # Compute the activations using the memory-efficient `map_fn`.
  activations = functional_ops.map_fn(
      fn=classifier_fn,
      elems=imgs,
      parallel_iterations=1,
      back_prop=False,
      swap_memory=True,
      name='RunClassifier')

  # Split the activations by the real and generated images.
  real_a, gen_a = array_ops.split(activations, [num_batches, num_batches], 0)

  # Ensure the activations have the right shapes.
  real_a = array_ops.concat(array_ops.unstack(real_a), 0)
  gen_a = array_ops.concat(array_ops.unstack(gen_a), 0)
  real_a.shape.assert_has_rank(2)
  gen_a.shape.assert_has_rank(2)

  # Compute mean and covariance matrices of activations.
  m = math_ops.reduce_mean(real_a, 0)
  m_v = math_ops.reduce_mean(gen_a, 0)
  num_examples = math_ops.to_float(array_ops.shape(real_a)[0])

  # sigma = (1 / (n - 1)) * (X - mu) (X - mu)^T
  sigma = math_ops.matmul(
      real_a - m, real_a - m, transpose_a=True) / (num_examples - 1)

  sigma_v = math_ops.matmul(
      gen_a - m_v, gen_a - m_v, transpose_a=True) / (num_examples - 1)

  # Find the Tr(sqrt(sigma sigma_v)) component of FID
  sqrt_trace_component = trace_sqrt_product(sigma, sigma_v)

  # Compute the two components of FID.

  # First the covariance component.
  # Here, note that trace(A + B) = trace(A) + trace(B)
  trace = math_ops.trace(sigma + sigma_v) - 2.0 * sqrt_trace_component

  # Next the distance between means.
  mean = math_ops.square(linalg_ops.norm(m - m_v))  # This uses the L2 norm.
  fid = trace + mean

  return fid
コード例 #44
0
  def decompress(self, strings, shape, channels=None):
    """Decompress values from their compressed string representations.

    Args:
      strings: A string `Tensor` vector containing the compressed data.
      shape: A `Tensor` vector of int32 type. Contains the shape of the tensor
        to be decompressed, excluding the batch dimension.
      channels: Integer. Specifies the number of channels statically. Needs only
        be set if the layer hasn't been built yet (i.e., this is the first input
        it receives).

    Returns:
      The decompressed `Tensor`. Its shape will be equal to `shape` prepended
      with the batch dimension from `strings`.

    Raises:
      ValueError: If the length of `shape` isn't available at graph construction
        time.
    """
    with ops.name_scope(self._name_scope()):
      strings = ops.convert_to_tensor(strings)
      shape = ops.convert_to_tensor(shape)
      if self.built:
        ndim = self.input_spec.ndim
        channel_axis = self._channel_axis(ndim)
        if channels is None:
          channels = self.input_spec.axes[channel_axis]
      else:
        if not (shape.shape.is_fully_defined() and shape.shape.ndims == 1):
          raise ValueError("`shape` must be a vector with known length.")
        ndim = shape.shape[0].value + 1
        channel_axis = self._channel_axis(ndim)
        input_shape = ndim * [None]
        input_shape[channel_axis] = channels
        self.build(input_shape)

      # Tuple of slices for expanding dimensions of tensors below.
      slices = ndim * [None] + [slice(None)]
      slices[channel_axis] = slice(None)
      slices = tuple(slices)

      # Expand dimensions of CDF to input dimensions, keeping the channels along
      # the right dimension.
      cdf = self._quantized_cdf[slices[1:]]
      num_levels = array_ops.shape(cdf)[-1] - 1

      def loop_body(string):
        return coder_ops.range_decode(
            string, shape, cdf, precision=self.range_coder_precision)
      outputs = functional_ops.map_fn(
          loop_body, strings, dtype=dtypes.int16, back_prop=False)
      outputs = math_ops.cast(outputs, self.dtype)

      medians = array_ops.squeeze(self._medians, [1, 2])
      offsets = math_ops.cast(num_levels // 2, self.dtype) - medians
      outputs -= offsets[slices[:-1]]

      if not context.executing_eagerly():
        outputs_shape = ndim * [None]
        outputs_shape[0] = strings.shape[0]
        outputs_shape[channel_axis] = channels
        outputs.set_shape(outputs_shape)

      return outputs
コード例 #45
0
 def testMapShape(self):
     with self.test_session():
         x = constant_op.constant([[1, 2, 3], [4, 5, 6]])
         y = functional_ops.map_fn(lambda e: e, x)
         self.assertAllEqual(y.get_shape(), y.eval().shape)
コード例 #46
0
 def testMapEmptyTensor(self):
   with self.cached_session():
     map_return = functional_ops.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)
コード例 #47
0
 def testMap_SimpleNotTensor(self):
   nums = np.array([1, 2, 3, 4, 5, 6])
   r = functional_ops.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))
コード例 #48
0
 def testMapUnknownShape(self):
     x = array_ops.placeholder(dtypes.float32)
     y = functional_ops.map_fn(lambda e: e, x)
     self.assertIs(None, y.get_shape().dims)
コード例 #49
0
ファイル: _tf_scores.py プロジェクト: arthurmensch/dseg
        tfgan.eval.run_inception(images,
                                 output_tensor=['logits:0', 'pool_3:0']))


input_images_ = tf.placeholder(tf.float32, [None, 3, None, None])
images_ = tf.transpose(input_images_, [0, 2, 3, 1])
size_ = 299
images_ = tf.image.resize_bilinear(images_, [size_, size_])
generated_images_list_ = array_ops.split(images_, num_or_size_splits=1)

with tf.device('/gpu:0'):
    # Run images through Inception.
    logits_, activations_ = functional_ops.map_fn(
        fn=_run_inception,
        elems=array_ops.stack(generated_images_list_),
        parallel_iterations=1,
        back_prop=False,
        dtype=(tf.float32, tf.float32),
        swap_memory=True,
        name='RunClassifier')

logits_ = array_ops.concat(array_ops.unstack(logits_), 0)
activations_ = array_ops.concat(array_ops.unstack(activations_), 0)

activations1_ = tf.placeholder(tf.float32, [None, None], name='activations1')
activations2_ = tf.placeholder(tf.float32, [None, None], name='activations2')
fcd = tfgan.eval.frechet_classifier_distance_from_activations(
    activations1_, activations2_)


def activations_to_distance(activations1, activations2):
    print('Compute distance')
コード例 #50
0
 def testMapEmptyScalar(self):
     with self.test_session():
         map_return = functional_ops.map_fn(lambda x: 1,
                                            constant_op.constant([]))
         self.assertAllEqual([0], map_return.get_shape().dims)
         self.assertAllEqual([0], map_return.eval().shape)
コード例 #51
0
 def generate_one(d):
     fn = lambda _: random_ops.random_shuffle(math_ops.range(d), seed=seed)
     return functional_ops.map_fn(fn, sample_range)