def testArgMinMax(self):
        # Complex numbers do not support argmin/argmax.
        minmax_types = set(self.numeric_types) - set(self.complex_types)
        for dtype in minmax_types:
            self._assertOpOutputMatchesExpected(
                lambda x: math_ops.argmax(x, axis=0, output_type=dtypes.int32),
                np.array([1, 10, 27, 3, 3, 4], dtype=dtype),
                expected=np.int32(2))
            self._assertOpOutputMatchesExpected(
                lambda x: math_ops.argmax(x, axis=0, output_type=dtypes.int32),
                np.array([[4, 1, 7], [3, 2, 4]], dtype=dtype),
                expected=np.array([0, 1, 0], dtype=np.int32))
            self._assertOpOutputMatchesExpected(
                lambda x: math_ops.argmax(x, axis=1, output_type=dtypes.int32),
                np.array([[4, 1], [3, 2]], dtype=dtype),
                expected=np.array([0, 0], dtype=np.int32))

            self._assertOpOutputMatchesExpected(
                lambda x: math_ops.argmin(x, axis=0, output_type=dtypes.int32),
                np.array([3, 10, 27, 3, 2, 4], dtype=dtype),
                expected=np.int32(4))
            self._assertOpOutputMatchesExpected(
                lambda x: math_ops.argmin(x, axis=0, output_type=dtypes.int32),
                np.array([[4, 1, 7], [3, 2, 4]], dtype=dtype),
                expected=np.array([1, 0, 1], dtype=np.int32))
            self._assertOpOutputMatchesExpected(
                lambda x: math_ops.argmin(x, axis=1, output_type=dtypes.int32),
                np.array([[4, 1], [3, 2]], dtype=dtype),
                expected=np.array([1, 1], dtype=np.int32))
Esempio n. 2
0
  def testArgMinMax(self):
    for dtype in self.numeric_types:
      self._assertOpOutputMatchesExpected(
          lambda x: math_ops.argmax(x, axis=0, output_type=dtypes.int32),
          np.array([1, 10, 27, 3, 3, 4], dtype=dtype),
          expected=np.int32(2))
      self._assertOpOutputMatchesExpected(
          lambda x: math_ops.argmax(x, axis=0, output_type=dtypes.int32),
          np.array([[4, 1, 7], [3, 2, 4]], dtype=dtype),
          expected=np.array([0, 1, 0], dtype=np.int32))
      self._assertOpOutputMatchesExpected(
          lambda x: math_ops.argmax(x, axis=1, output_type=dtypes.int32),
          np.array([[4, 1], [3, 2]], dtype=dtype),
          expected=np.array([0, 0], dtype=np.int32))

      self._assertOpOutputMatchesExpected(
          lambda x: math_ops.argmin(x, axis=0, output_type=dtypes.int32),
          np.array([3, 10, 27, 3, 2, 4], dtype=dtype),
          expected=np.int32(4))
      self._assertOpOutputMatchesExpected(
          lambda x: math_ops.argmin(x, axis=0, output_type=dtypes.int32),
          np.array([[4, 1, 7], [3, 2, 4]], dtype=dtype),
          expected=np.array([1, 0, 1], dtype=np.int32))
      self._assertOpOutputMatchesExpected(
          lambda x: math_ops.argmin(x, axis=1, output_type=dtypes.int32),
          np.array([[4, 1], [3, 2]], dtype=dtype),
          expected=np.array([1, 1], dtype=np.int32))
Esempio n. 3
0
  def testArgMinMax(self):
    # Complex numbers do not support argmin/argmax.
    minmax_types = set(self.numeric_types) - set(self.complex_types)
    for dtype in minmax_types:
      self._assertOpOutputMatchesExpected(
          lambda x: math_ops.argmax(x, axis=0, output_type=dtypes.int32),
          np.array([1, 10, 27, 3, 3, 4], dtype=dtype),
          expected=np.int32(2))
      self._assertOpOutputMatchesExpected(
          lambda x: math_ops.argmax(x, axis=0, output_type=dtypes.int32),
          np.array([[4, 1, 7], [3, 2, 4]], dtype=dtype),
          expected=np.array([0, 1, 0], dtype=np.int32))
      self._assertOpOutputMatchesExpected(
          lambda x: math_ops.argmax(x, axis=1, output_type=dtypes.int32),
          np.array([[4, 1], [3, 2]], dtype=dtype),
          expected=np.array([0, 0], dtype=np.int32))

      self._assertOpOutputMatchesExpected(
          lambda x: math_ops.argmin(x, axis=0, output_type=dtypes.int32),
          np.array([3, 10, 27, 3, 2, 4], dtype=dtype),
          expected=np.int32(4))
      self._assertOpOutputMatchesExpected(
          lambda x: math_ops.argmin(x, axis=0, output_type=dtypes.int32),
          np.array([[4, 1, 7], [3, 2, 4]], dtype=dtype),
          expected=np.array([1, 0, 1], dtype=np.int32))
      self._assertOpOutputMatchesExpected(
          lambda x: math_ops.argmin(x, axis=1, output_type=dtypes.int32),
          np.array([[4, 1], [3, 2]], dtype=dtype),
          expected=np.array([1, 1], dtype=np.int32))
Esempio n. 4
0
  def testArgMinReturnsFirstOccurence(self):
    for dtype in self._getValidDtypes():
      values = constant_op.constant(
          [[10, 11, 15, 15, 10], [12, 12, 10, 10, 12]], dtype=dtype)
      self.assertAllEqual(
          math_ops.argmin(values, axis=1),
          np.argmin(self.evaluate(values), axis=1))

      # Long tensor to ensure works with multithreading/GPU
      values = array_ops.zeros(shape=(193681,), dtype=dtype)
      self.assertAllEqual(math_ops.argmin(values), 0)
Esempio n. 5
0
def get_cluster_assignment(pairwise_distances, centroid_ids):
  """Assign data points to the neareset centroids.
  Tensorflow has numerical instability and doesn't always choose
    the data point with theoretically zero distance as it's nearest neighbor.
    Thus, for each centroid in centroid_ids, explicitly assign
    the centroid itself as the nearest centroid.
    This is done through the mask tensor and the constraint_vect tensor.
  Args:
    pairwise_distances: 2-D Tensor of pairwise distances.
    centroid_ids: 1-D Tensor of centroid indices.
  Returns:
    y_fixed: 1-D tensor of cluster assignment.
  """
  predictions = math_ops.argmin(
      array_ops.gather(pairwise_distances, centroid_ids), dimension=0)
  batch_size = array_ops.shape(pairwise_distances)[0]

  # Deal with numerical instability
  mask = math_ops.reduce_any(array_ops.one_hot(
      centroid_ids, batch_size, True, False, axis=-1, dtype=dtypes.bool),
                             axis=0)
  constraint_one_hot = math_ops.multiply(
      array_ops.one_hot(centroid_ids,
                        batch_size,
                        array_ops.constant(1, dtype=dtypes.int64),
                        array_ops.constant(0, dtype=dtypes.int64),
                        axis=0,
                        dtype=dtypes.int64),
      math_ops.to_int64(math_ops.range(array_ops.shape(centroid_ids)[0])))
  constraint_vect = math_ops.reduce_sum(
      array_ops.transpose(constraint_one_hot), axis=0)

  y_fixed = array_ops.where(mask, constraint_vect, predictions)
  return y_fixed
Esempio n. 6
0
 def testArgMin(self):
   shape = (24, 8)
   for dtype in self._getValidDtypes():
     tf_values = self._generateRandomTensor(dtype, shape)
     np_values = self.evaluate(tf_values)
     for axis in range(0, len(shape)):
       np_min = np.argmin(np_values, axis=axis)
       tf_min = math_ops.argmin(tf_values, axis=axis)
       self.assertAllEqual(tf_min, np_min)
 def testFloatInt32Output(self):
   x = np.asarray(100 * np.random.randn(200), dtype=np.float32)
   expected_values = x.argmax()
   with self.session(use_gpu=True):
     ans = math_ops.argmax(x, axis=0, output_type=dtypes.int32)
     tf_ans = ans.eval()
     self.assertEqual(np.int32, tf_ans.dtype)
     # The values are equal when comparing int32 to int64 because
     # the values don't have a range that exceeds 32-bit integers.
     self.assertAllEqual(tf_ans, expected_values)
   expected_values = x.argmin()
   with self.session(use_gpu=True):
     ans = math_ops.argmin(x, axis=0, output_type=dtypes.int32)
     tf_ans = ans.eval()
     self.assertEqual(np.int32, tf_ans.dtype)
     self.assertAllEqual(tf_ans, expected_values)
Esempio n. 8
0
 def testFloatInt32Output(self):
     x = np.asarray(100 * np.random.randn(200), dtype=np.float32)
     expected_values = x.argmax()
     with self.test_session(use_gpu=True):
         ans = math_ops.argmax(x, axis=0, output_type=dtypes.int32)
         tf_ans = ans.eval()
         self.assertEqual(np.int32, tf_ans.dtype)
         # The values are equal when comparing int32 to int64 because
         # the values don't have a range that exceeds 32-bit integers.
         self.assertAllEqual(tf_ans, expected_values)
     expected_values = x.argmin()
     with self.test_session(use_gpu=True):
         ans = math_ops.argmin(x, axis=0, output_type=dtypes.int32)
         tf_ans = ans.eval()
         self.assertEqual(np.int32, tf_ans.dtype)
         self.assertAllEqual(tf_ans, expected_values)
Esempio n. 9
0
def get_cluster_assignment(pairwise_distances, centroid_ids):
  """Assign data points to the neareset centroids.

  Tensorflow has numerical instability and doesn't always choose
    the data point with theoretically zero distance as it's nearest neighbor.
    Thus, for each centroid in centroid_ids, explicitly assign
    the centroid itself as the nearest centroid.
    This is done through the mask tensor and the constraint_vect tensor.

  Args:
    pairwise_distances: 2-D Tensor of pairwise distances.
    centroid_ids: 1-D Tensor of centroid indices.

  Returns:
    y_fixed: 1-D tensor of cluster assignment.
  """
  predictions = math_ops.argmin(
      array_ops.gather(pairwise_distances, centroid_ids), dimension=0)
  batch_size = array_ops.shape(pairwise_distances)[0]

  # Deal with numerical instability
  mask = math_ops.reduce_any(array_ops.one_hot(
      centroid_ids, batch_size, True, False, axis=-1, dtype=dtypes.bool),
                             axis=0)
  constraint_one_hot = math_ops.multiply(
      array_ops.one_hot(centroid_ids,
                        batch_size,
                        array_ops.constant(1, dtype=dtypes.int64),
                        array_ops.constant(0, dtype=dtypes.int64),
                        axis=0,
                        dtype=dtypes.int64),
      math_ops.cast(math_ops.range(array_ops.shape(centroid_ids)[0]),
                    dtypes.int64))
  constraint_vect = math_ops.reduce_sum(
      array_ops.transpose(constraint_one_hot), axis=0)

  y_fixed = array_ops.where(mask, constraint_vect, predictions)
  return y_fixed
Esempio n. 10
0
 def argmin(x):
     return math_ops.argmin(x)
Esempio n. 11
0
 def _update_statistics_from_mini_batch(
     self, statistics, auxiliary_variables, times, values):
   """Given mini-batch input, update `statistics` and `auxiliary_variables`."""
   values = math_ops.cast(values, self._dtype)
   # The density (measured in times per observation) that we see in each part
   # of the mini-batch.
   batch_inter_observation_duration = (math_ops.cast(
       math_ops.reduce_max(times, axis=1) - math_ops.reduce_min(times, axis=1),
       self._dtype) / math_ops.cast(
           array_ops.shape(times)[1] - 1, self._dtype))
   # Co-locate updates with their variables to minimize race conditions when
   # updating statistics.
   with ops.colocate_with(auxiliary_variables.max_time_seen):
     # There is a race condition if this value is being updated from multiple
     # workers. However, it should eventually reach the correct value if the
     # last chunk is presented enough times.
     max_time_seen_assign = state_ops.assign(
         auxiliary_variables.max_time_seen,
         gen_math_ops.maximum(auxiliary_variables.max_time_seen,
                              math_ops.reduce_max(times)))
   with ops.colocate_with(auxiliary_variables.chunk_count):
     chunk_count_assign = state_ops.assign_add(auxiliary_variables.chunk_count,
                                               array_ops.shape(
                                                   times,
                                                   out_type=dtypes.int64)[0])
   with ops.colocate_with(auxiliary_variables.inter_observation_duration_sum):
     inter_observation_duration_assign = state_ops.assign_add(
         auxiliary_variables.inter_observation_duration_sum,
         math_ops.reduce_sum(batch_inter_observation_duration))
   with ops.colocate_with(auxiliary_variables.example_count):
     example_count_assign = state_ops.assign_add(
         auxiliary_variables.example_count,
         array_ops.size(times, out_type=dtypes.int64))
   # Note: These mean/variance updates assume that all points are equally
   # likely, which is not true if _chunks_ are sampled uniformly from the space
   # of all possible contiguous chunks, since points at the start and end of
   # the series are then members of fewer chunks. For series which are much
   # longer than the chunk size (the usual/expected case), this effect becomes
   # irrelevant.
   with ops.colocate_with(auxiliary_variables.overall_feature_sum):
     overall_feature_sum_assign = state_ops.assign_add(
         auxiliary_variables.overall_feature_sum,
         math_ops.reduce_sum(values, axis=[0, 1]))
   with ops.colocate_with(auxiliary_variables.overall_feature_sum_of_squares):
     overall_feature_sum_of_squares_assign = state_ops.assign_add(
         auxiliary_variables.overall_feature_sum_of_squares,
         math_ops.reduce_sum(values**2, axis=[0, 1]))
   per_chunk_aux_updates = control_flow_ops.group(
       max_time_seen_assign, chunk_count_assign,
       inter_observation_duration_assign, example_count_assign,
       overall_feature_sum_assign, overall_feature_sum_of_squares_assign)
   with ops.control_dependencies([per_chunk_aux_updates]):
     example_count_float = math_ops.cast(auxiliary_variables.example_count,
                                         self._dtype)
     new_feature_mean = (auxiliary_variables.overall_feature_sum /
                         example_count_float)
     overall_feature_mean_update = state_ops.assign(
         statistics.overall_feature_moments.mean, new_feature_mean)
     overall_feature_var_update = state_ops.assign(
         statistics.overall_feature_moments.variance,
         # De-biased n / (n - 1) variance correction
         example_count_float / (example_count_float - 1.) *
         (auxiliary_variables.overall_feature_sum_of_squares /
          example_count_float - new_feature_mean**2))
     # TODO(b/35675805): Remove this cast
     min_time_batch = math_ops.cast(math_ops.argmin(times[:, 0]), dtypes.int32)
     def series_start_updates():
       # If this is the lowest-time chunk that we have seen so far, update
       # series start moments to reflect that. Note that these statistics are
       # "best effort", as there are race conditions in the update (however,
       # they should eventually converge if the start of the series is
       # presented enough times).
       mean, variance = nn.moments(
           values[min_time_batch, :self._starting_variance_window_size],
           axes=[0])
       return control_flow_ops.group(
           state_ops.assign(statistics.series_start_moments.mean, mean),
           state_ops.assign(statistics.series_start_moments.variance,
                            variance))
     with ops.colocate_with(statistics.start_time):
       series_start_update = control_flow_ops.cond(
           # Update moments whenever we even match the lowest time seen so far,
           # to ensure that series start statistics are eventually updated to
           # their correct values, despite race conditions (i.e. eventually
           # statistics.start_time will reflect the global lowest time, and
           # given that we will eventually update the series start moments to
           # their correct values).
           math_ops.less_equal(times[min_time_batch, 0],
                               statistics.start_time),
           series_start_updates,
           control_flow_ops.no_op)
       with ops.control_dependencies([series_start_update]):
         # There is a race condition if this update is performed in parallel on
         # multiple workers. Since models may be sensitive to being presented
         # with times before the putative start time, the value of this
         # variable is post-processed above to guarantee that each worker is
         # presented with a start time which is at least as low as the lowest
         # time in its current mini-batch.
         start_time_update = state_ops.assign(statistics.start_time,
                                              gen_math_ops.minimum(
                                                  statistics.start_time,
                                                  math_ops.reduce_min(times)))
     inter_observation_duration_estimate = (
         auxiliary_variables.inter_observation_duration_sum / math_ops.cast(
             auxiliary_variables.chunk_count, self._dtype))
     # Estimate the total number of observations as:
     #   (end time - start time + 1) * average intra-chunk time density
     total_observation_count_update = state_ops.assign(
         statistics.total_observation_count,
         math_ops.cast(
             gen_math_ops.round(
                 math_ops.cast(auxiliary_variables.max_time_seen -
                               statistics.start_time + 1, self._dtype) /
                 inter_observation_duration_estimate), dtypes.int64))
     per_chunk_stat_updates = control_flow_ops.group(
         overall_feature_mean_update, overall_feature_var_update,
         series_start_update, start_time_update,
         total_observation_count_update)
   return per_chunk_stat_updates
Esempio n. 12
0
    def _update_statistics_from_mini_batch(self, statistics,
                                           auxiliary_variables, times, values):
        """Given mini-batch input, update `statistics` and `auxiliary_variables`."""
        values = math_ops.cast(values, self._dtype)
        # The density (measured in times per observation) that we see in each part
        # of the mini-batch.
        batch_inter_observation_duration = (
            math_ops.cast(
                math_ops.reduce_max(times, axis=1) -
                math_ops.reduce_min(times, axis=1), self._dtype) /
            math_ops.cast(array_ops.shape(times)[1] - 1, self._dtype))
        # Co-locate updates with their variables to minimize race conditions when
        # updating statistics.
        with ops.colocate_with(auxiliary_variables.max_time_seen):
            # There is a race condition if this value is being updated from multiple
            # workers. However, it should eventually reach the correct value if the
            # last chunk is presented enough times.
            max_time_seen_assign = state_ops.assign(
                auxiliary_variables.max_time_seen,
                gen_math_ops.maximum(auxiliary_variables.max_time_seen,
                                     math_ops.reduce_max(times)))
        with ops.colocate_with(auxiliary_variables.chunk_count):
            chunk_count_assign = state_ops.assign_add(
                auxiliary_variables.chunk_count,
                array_ops.shape(times, out_type=dtypes.int64)[0])
        with ops.colocate_with(
                auxiliary_variables.inter_observation_duration_sum):
            inter_observation_duration_assign = state_ops.assign_add(
                auxiliary_variables.inter_observation_duration_sum,
                math_ops.reduce_sum(batch_inter_observation_duration))
        with ops.colocate_with(auxiliary_variables.example_count):
            example_count_assign = state_ops.assign_add(
                auxiliary_variables.example_count,
                array_ops.size(times, out_type=dtypes.int64))
        # Note: These mean/variance updates assume that all points are equally
        # likely, which is not true if _chunks_ are sampled uniformly from the space
        # of all possible contiguous chunks, since points at the start and end of
        # the series are then members of fewer chunks. For series which are much
        # longer than the chunk size (the usual/expected case), this effect becomes
        # irrelevant.
        with ops.colocate_with(auxiliary_variables.overall_feature_sum):
            overall_feature_sum_assign = state_ops.assign_add(
                auxiliary_variables.overall_feature_sum,
                math_ops.reduce_sum(values, axis=[0, 1]))
        with ops.colocate_with(
                auxiliary_variables.overall_feature_sum_of_squares):
            overall_feature_sum_of_squares_assign = state_ops.assign_add(
                auxiliary_variables.overall_feature_sum_of_squares,
                math_ops.reduce_sum(values**2, axis=[0, 1]))
        per_chunk_aux_updates = control_flow_ops.group(
            max_time_seen_assign, chunk_count_assign,
            inter_observation_duration_assign, example_count_assign,
            overall_feature_sum_assign, overall_feature_sum_of_squares_assign)
        with ops.control_dependencies([per_chunk_aux_updates]):
            example_count_float = math_ops.cast(
                auxiliary_variables.example_count, self._dtype)
            new_feature_mean = (auxiliary_variables.overall_feature_sum /
                                example_count_float)
            overall_feature_mean_update = state_ops.assign(
                statistics.overall_feature_moments.mean, new_feature_mean)
            overall_feature_var_update = state_ops.assign(
                statistics.overall_feature_moments.variance,
                # De-biased n / (n - 1) variance correction
                example_count_float / (example_count_float - 1.) *
                (auxiliary_variables.overall_feature_sum_of_squares /
                 example_count_float - new_feature_mean**2))
            # TODO(b/35675805): Remove this cast
            min_time_batch = math_ops.cast(math_ops.argmin(times[:, 0]),
                                           dtypes.int32)

            def series_start_updates():
                # If this is the lowest-time chunk that we have seen so far, update
                # series start moments to reflect that. Note that these statistics are
                # "best effort", as there are race conditions in the update (however,
                # they should eventually converge if the start of the series is
                # presented enough times).
                mean, variance = nn.moments(values[
                    min_time_batch, :self._starting_variance_window_size],
                                            axes=[0])
                return control_flow_ops.group(
                    state_ops.assign(statistics.series_start_moments.mean,
                                     mean),
                    state_ops.assign(statistics.series_start_moments.variance,
                                     variance))

            with ops.colocate_with(statistics.start_time):
                series_start_update = control_flow_ops.cond(
                    # Update moments whenever we even match the lowest time seen so far,
                    # to ensure that series start statistics are eventually updated to
                    # their correct values, despite race conditions (i.e. eventually
                    # statistics.start_time will reflect the global lowest time, and
                    # given that we will eventually update the series start moments to
                    # their correct values).
                    math_ops.less_equal(times[min_time_batch, 0],
                                        statistics.start_time),
                    series_start_updates,
                    control_flow_ops.no_op)
                with ops.control_dependencies([series_start_update]):
                    # There is a race condition if this update is performed in parallel on
                    # multiple workers. Since models may be sensitive to being presented
                    # with times before the putative start time, the value of this
                    # variable is post-processed above to guarantee that each worker is
                    # presented with a start time which is at least as low as the lowest
                    # time in its current mini-batch.
                    start_time_update = state_ops.assign(
                        statistics.start_time,
                        gen_math_ops.minimum(statistics.start_time,
                                             math_ops.reduce_min(times)))
            inter_observation_duration_estimate = (
                auxiliary_variables.inter_observation_duration_sum /
                math_ops.cast(auxiliary_variables.chunk_count, self._dtype))
            # Estimate the total number of observations as:
            #   (end time - start time + 1) * average intra-chunk time density
            total_observation_count_update = state_ops.assign(
                statistics.total_observation_count,
                math_ops.cast(
                    gen_math_ops.round(
                        math_ops.cast(
                            auxiliary_variables.max_time_seen -
                            statistics.start_time + 1, self._dtype) /
                        inter_observation_duration_estimate), dtypes.int64))
            per_chunk_stat_updates = control_flow_ops.group(
                overall_feature_mean_update, overall_feature_var_update,
                series_start_update, start_time_update,
                total_observation_count_update)
        return per_chunk_stat_updates
Esempio n. 13
0
 def model(a, axis):
   return math_ops.argmin(a, axis=axis, output_type=dtypes.int32)
Esempio n. 14
0
 def model(a):
   return math_ops.argmin(a, output_type=dtypes.int32)