예제 #1
0
 def _validate(self):
     vops = [
         assert_util.assert_positive(self._scale),
         assert_util.assert_positive(self._high - self._low),
         assert_util.assert_finite(self._low,
                                   message="Lower bound not finite"),
         assert_util.assert_finite(self._high,
                                   message="Upper bound not finite"),
         assert_util.assert_finite(self._loc, message="Loc not finite"),
         assert_util.assert_finite(self._scale, message="scale not finite"),
     ]
     return tf.group(*vops, name="ValidationOps")
예제 #2
0
 def _parameter_control_dependencies(self, is_init):
   if not self.validate_args:
     return []
   assertions = []
   if is_init != tensor_util.is_ref(self.scale):
     assertions.append(assert_util.assert_positive(
         self.scale,
         message='Argument `scale` must be positive.'))
   if is_init != tensor_util.is_ref(self.concentration):
     assertions.append(assert_util.assert_positive(
         self.concentration,
         message='Argument `concentration` must be positive.'))
   return assertions
예제 #3
0
 def _parameter_control_dependencies(self, is_init):
     if not self.validate_args:
         return []
     assertions = []
     if is_init != tensor_util.is_ref(self.concentration0):
         assertions.append(
             assert_util.assert_positive(
                 self.concentration0,
                 message="Argument `concentration0` must be positive."))
     if is_init != tensor_util.is_ref(self.concentration1):
         assertions.append(
             assert_util.assert_positive(
                 self.concentration1,
                 message="Argument `concentration1` must be positive."))
     return assertions
예제 #4
0
 def _maybe_assert_valid_sample(self, x):
     dtype_util.assert_same_float_dtype(tensors=[x], dtype=self.dtype)
     if not self.validate_args:
         return []
     return [
         assert_util.assert_positive(x, message='Sample must be positive.')
     ]
예제 #5
0
def calculate_reshape(original_shape, new_shape, validate=False, name=None):
    """Calculates the reshaped dimensions (replacing up to one -1 in reshape)."""
    batch_shape_static = tensorshape_util.constant_value_as_shape(new_shape)
    if tensorshape_util.is_fully_defined(batch_shape_static):
        return np.int32(batch_shape_static), batch_shape_static, []
    with tf.name_scope(name or 'calculate_reshape'):
        original_size = tf.reduce_prod(original_shape)
        implicit_dim = tf.equal(new_shape, -1)
        size_implicit_dim = (original_size //
                             tf.maximum(1, -tf.reduce_prod(new_shape)))
        expanded_new_shape = tf.where(  # Assumes exactly one `-1`.
            implicit_dim, size_implicit_dim, new_shape)
        validations = [] if not validate else [  # pylint: disable=g-long-ternary
            assert_util.assert_rank(
                original_shape, 1, message='Original shape must be a vector.'),
            assert_util.assert_rank(
                new_shape, 1, message='New shape must be a vector.'),
            assert_util.assert_less_equal(
                tf.math.count_nonzero(implicit_dim, dtype=tf.int32),
                1,
                message='At most one dimension can be unknown.'),
            assert_util.assert_positive(
                expanded_new_shape, message='Shape elements must be >=-1.'),
            assert_util.assert_equal(tf.reduce_prod(expanded_new_shape),
                                     original_size,
                                     message='Shape sizes do not match.'),
        ]
        return expanded_new_shape, batch_shape_static, validations
예제 #6
0
 def _assertions(self, t):
     if self.validate_args:
         return []
     is_matrix = assert_util.assert_rank_at_least(t, 2)
     is_square = assert_util.assert_equal(tf.shape(t)[-2], tf.shape(t)[-1])
     is_positive_definite = assert_util.assert_positive(
         tf.linalg.diag_part(t), message="Input must be positive definite.")
     return [is_matrix, is_square, is_positive_definite]
예제 #7
0
 def _maybe_assert_valid_y(self, y):
     if not self.validate_args:
         return []
     return [
         assert_util.assert_positive(
             y,
             message='Inverse transformation input must be greater than 0.')
     ]
예제 #8
0
 def _assertions(self, t):
     if not self.validate_args:
         return []
     return [
         assert_util.assert_positive(
             t[..., 1:] - t[..., :-1],
             message=
             "Forward transformation input must be strictly increasing.")
     ]
예제 #9
0
 def _parameter_control_dependencies(self, is_init):
   if not self.validate_args:
     return []
   assertions = []
   if self._rate is not None:
     if is_init != tensor_util.is_ref(self._rate):
       assertions.append(assert_util.assert_positive(
           self._rate,
           message='Argument `rate` must be positive.'))
   return assertions
예제 #10
0
 def _maybe_assert_valid_sample(self, x):
     """Checks the validity of a sample."""
     if not self.validate_args:
         return []
     return [
         assert_util.assert_positive(x, message="Sample must be positive."),
         assert_util.assert_less(x,
                                 1.,
                                 message="Sample must be less than `1`.")
     ]
예제 #11
0
 def _parameter_control_dependencies(self, is_init):
   if is_init:
     dtype_util.assert_same_float_dtype([self.loc, self.scale])
   if not self.validate_args:
     return []
   assertions = []
   if is_init != tensor_util.is_ref(self._scale):
     assertions.append(assert_util.assert_positive(
         self._scale, message='Argument `scale` must be positive.'))
   return assertions
예제 #12
0
 def _parameter_control_dependencies(self, is_init):
     if not self.validate_args:
         return []
     assertions = []
     if is_init != tensor_util.is_ref(self.tailweight):
         assertions.append(
             assert_util.assert_positive(
                 self.tailweight,
                 message="Argument `tailweight` must be positive."))
     return assertions
예제 #13
0
 def _maybe_assert_valid_sample(self, x):
   """Checks the validity of a sample."""
   if not self.validate_args:
     return []
   return [
       assert_util.assert_positive(x, message='samples must be positive'),
       assert_util.assert_near(
           tf.ones([], dtype=self.dtype),
           tf.reduce_sum(x, axis=-1),
           message='sample last-dimension must sum to `1`'),
   ]
예제 #14
0
 def _parameter_control_dependencies(self, is_init):
     if not self.validate_args:
         return []
     assertions = []
     for concentration in [self.concentration0, self.concentration1]:
         if is_init != tensor_util.is_ref(concentration):
             assertions.append(
                 assert_util.assert_positive(
                     concentration,
                     message="Concentration parameter must be positive."))
     return assertions
예제 #15
0
 def __init__(self, temperature, validate_args=False, name="softfloor"):
     with tf.name_scope(name) as name:
         self._temperature = tf.convert_to_tensor(temperature,
                                                  name="temperature")
         if validate_args:
             self._temperature = distribution_util.with_dependencies([
                 assert_util.assert_positive(
                     self._temperature,
                     message="Argument temperature was not positive")
             ], self._temperature)
         super(Softfloor, self).__init__(forward_min_event_ndims=0,
                                         validate_args=validate_args,
                                         dtype=self._temperature.dtype,
                                         name=name)
예제 #16
0
    def _parameter_control_dependencies(self, is_init):
        if not self.validate_args:
            return []
        assertions = []
        for param_name, param in dict(
                concentration=self.concentration,
                mixing_concentration=self.mixing_concentration,
                mixing_rate=self.mixing_rate).items():

            if is_init != tensor_util.is_ref(param):
                assertions.append(
                    assert_util.assert_positive(
                        param,
                        message='Argument `{}` must be positive.'.format(
                            param_name)))
        return assertions
예제 #17
0
 def _parameter_control_dependencies(self, is_init):
     if not self.validate_args:
         return []
     assertions = []
     if self._probs is not None:
         if is_init != tensor_util.is_ref(self._probs):
             probs = tf.convert_to_tensor(self._probs)
             assertions.append(
                 assert_util.assert_positive(
                     probs, message='Argument `probs` must be positive.'))
             assertions.append(
                 assert_util.assert_less_equal(
                     probs,
                     dtype_util.as_numpy_dtype(self.dtype)(1.),
                     message=
                     'Argument `probs` must be less than or equal to 1.'))
     return assertions
예제 #18
0
 def _assertions(self, x):
     if not self.validate_args:
         return []
     x_shape = tf.shape(x)
     is_matrix = assert_util.assert_rank_at_least(
         x, 2, message="Input must have rank at least 2.")
     is_square = assert_util.assert_equal(
         x_shape[-2], x_shape[-1], message="Input must be a square matrix.")
     diag_part_x = tf.linalg.diag_part(x)
     is_lower_triangular = assert_util.assert_equal(
         tf.linalg.band_part(x, 0, -1),  # Preserves triu, zeros rest.
         tf.linalg.diag(diag_part_x),
         message="Input must be lower triangular.")
     is_positive_diag = assert_util.assert_positive(
         diag_part_x,
         message="Input must have all positive diagonal entries.")
     return [is_matrix, is_square, is_lower_triangular, is_positive_diag]
  def _parameter_control_dependencies(self, is_init):
    assertions = []

    if is_init and self.validate_args:
      # assert_categorical_event_shape handles both the static and dynamic case.
      assertions.extend(
          distribution_util.assert_categorical_event_shape(self._concentration))

    if is_init != tensor_util.is_ref(self._total_count):
      if self.validate_args:
        assertions.extend(
            distribution_util.assert_nonnegative_integer_form(
                self._total_count))

    if is_init != tensor_util.is_ref(self._concentration):
      if self.validate_args:
        assertions.append(
            assert_util.assert_positive(
                self._concentration,
                message='Concentration parameter must be positive.'))
    return assertions
예제 #20
0
  def _parameter_control_dependencies(self, is_init):
    """Checks the validity of the concentration parameter."""
    assertions = []

    # In init, we can always build shape and dtype checks because
    # we assume shape doesn't change for Variable backed args.
    if is_init:
      if not dtype_util.is_floating(self.concentration.dtype):
        raise TypeError('Argument `concentration` must be float type.')

      msg = 'Argument `concentration` must have rank at least 1.'
      ndims = tensorshape_util.rank(self.concentration.shape)
      if ndims is not None:
        if ndims < 1:
          raise ValueError(msg)
      elif self.validate_args:
        assertions.append(assert_util.assert_rank_at_least(
            self.concentration, 1, message=msg))

      msg = 'Argument `concentration` must have `event_size` at least 2.'
      event_size = tf.compat.dimension_value(self.concentration.shape[-1])
      if event_size is not None:
        if event_size < 2:
          raise ValueError(msg)
      elif self.validate_args:
        assertions.append(assert_util.assert_less(
            1,
            tf.shape(self.concentration)[-1],
            message=msg))

    if not self.validate_args:
      assert not assertions  # Should never happen.
      return []

    if is_init != tensor_util.is_ref(self.concentration):
      assertions.append(assert_util.assert_positive(
          self.concentration,
          message='Argument `concentration` must be positive.'))

    return assertions
예제 #21
0
  def _parameter_control_dependencies(self, is_init):
    assertions = []

    if is_init:
      try:
        self._batch_shape()
      except ValueError:
        raise ValueError(
            'Arguments `loc` and `scale` must have compatible shapes; '
            'loc.shape={}, scale.shape={}.'.format(
                self.loc.shape, self.scale.shape))
      # We don't bother checking the shapes in the dynamic case because
      # all member functions access both arguments anyway.

    if not self.validate_args:
      assert not assertions  # Should never happen.
      return []

    if is_init != tensor_util.is_ref(self.scale):
      assertions.append(assert_util.assert_positive(
          self.scale, message='Argument `scale` must be positive.'))

    return assertions
예제 #22
0
    def _parameter_control_dependencies(self, is_init):
        assertions = []

        logits = self._logits
        probs = self._probs
        param, name = (probs, 'probs') if logits is None else (logits,
                                                               'logits')

        # In init, we can always build shape and dtype checks because
        # we assume shape doesn't change for Variable backed args.
        if is_init:
            if not dtype_util.is_floating(param.dtype):
                raise TypeError(
                    'Argument `{}` must having floating type.'.format(name))

            msg = 'Argument `{}` must have rank at least 1.'.format(name)
            shape_static = tensorshape_util.dims(param.shape)
            if shape_static is not None:
                if len(shape_static) < 1:
                    raise ValueError(msg)
            elif self.validate_args:
                param = tf.convert_to_tensor(param)
                assertions.append(
                    assert_util.assert_rank_at_least(param, 1, message=msg))

            msg1 = 'Argument `{}` must have final dimension >= 1.'.format(name)
            msg2 = 'Argument `{}` must have final dimension <= {}.'.format(
                name, tf.int32.max)
            event_size = shape_static[-1] if shape_static is not None else None
            if event_size is not None:
                if event_size < 1:
                    raise ValueError(msg1)
                if event_size > tf.int32.max:
                    raise ValueError(msg2)
            elif self.validate_args:
                param = tf.convert_to_tensor(param)
                assertions.append(
                    assert_util.assert_greater_equal(tf.shape(param)[-1:],
                                                     1,
                                                     message=msg1))
                # NOTE: For now, we leave out a runtime assertion that
                # `tf.shape(param)[-1] <= tf.int32.max`.  An earlier `tf.shape` call
                # will fail before we get to this point.

        if not self.validate_args:
            assert not assertions  # Should never happen.
            return []

        if is_init != tensor_util.is_ref(self.temperature):
            assertions.append(assert_util.assert_positive(self.temperature))

        if probs is not None:
            probs = param  # reuse tensor conversion from above
            if is_init != tensor_util.is_ref(probs):
                probs = tf.convert_to_tensor(probs)
                one = tf.ones([], dtype=probs.dtype)
                assertions.extend([
                    assert_util.assert_non_negative(probs),
                    assert_util.assert_less_equal(probs, one),
                    assert_util.assert_near(
                        tf.reduce_sum(probs, axis=-1),
                        one,
                        message='Argument `probs` must sum to 1.'),
                ])

        return assertions
    def __init__(self,
                 temperature,
                 logits=None,
                 probs=None,
                 validate_args=False,
                 allow_nan_stats=True,
                 name='RelaxedBernoulli'):
        """Construct RelaxedBernoulli distributions.

    Args:
      temperature: An 0-D `Tensor`, representing the temperature
        of a set of RelaxedBernoulli distributions. The temperature should be
        positive.
      logits: An N-D `Tensor` representing the log-odds
        of a positive event. Each entry in the `Tensor` parametrizes
        an independent RelaxedBernoulli distribution where the probability of an
        event is sigmoid(logits). Only one of `logits` or `probs` should be
        passed in.
      probs: An N-D `Tensor` representing the probability of a positive event.
        Each entry in the `Tensor` parameterizes an independent Bernoulli
        distribution. Only one of `logits` or `probs` should be passed in.
      validate_args: Python `bool`, default `False`. When `True` distribution
        parameters are checked for validity despite possibly degrading runtime
        performance. When `False` invalid inputs may silently render incorrect
        outputs.
      allow_nan_stats: Python `bool`, default `True`. When `True`, statistics
        (e.g., mean, mode, variance) use the value "`NaN`" to indicate the
        result is undefined. When `False`, an exception is raised if one or
        more of the statistic's batch members are undefined.
      name: Python `str` name prefixed to Ops created by this class.

    Raises:
      ValueError: If both `probs` and `logits` are passed, or if neither.
    """
        parameters = dict(locals())
        with tf.name_scope(name) as name:
            dtype = dtype_util.common_dtype([logits, probs, temperature],
                                            tf.float32)
            self._temperature = tf.convert_to_tensor(temperature,
                                                     name='temperature',
                                                     dtype=dtype)
            if validate_args:
                with tf.control_dependencies(
                    [assert_util.assert_positive(temperature)]):
                    self._temperature = tf.identity(self._temperature)
            self._logits, self._probs = distribution_util.get_logits_and_probs(
                logits=logits,
                probs=probs,
                validate_args=validate_args,
                dtype=dtype)
            super(RelaxedBernoulli, self).__init__(
                distribution=logistic.Logistic(self._logits /
                                               self._temperature,
                                               1. / self._temperature,
                                               validate_args=validate_args,
                                               allow_nan_stats=allow_nan_stats,
                                               name=name + '/Logistic'),
                bijector=sigmoid_bijector.Sigmoid(validate_args=validate_args),
                validate_args=validate_args,
                name=name)
        self._parameters = parameters
예제 #24
0
 def _maybe_assert_valid_sample(self, x):
     dtype_util.assert_same_float_dtype(tensors=[x], dtype=self.dtype)
     if not self.validate_args:
         return x
     with tf.control_dependencies([assert_util.assert_positive(x)]):
         return tf.identity(x)
예제 #25
0
    def __init__(self,
                 df,
                 scale=None,
                 scale_tril=None,
                 input_output_cholesky=False,
                 validate_args=False,
                 allow_nan_stats=True,
                 name="Wishart"):
        """Construct Wishart distributions.

    Args:
      df: `float` or `double` `Tensor`. Degrees of freedom, must be greater than
        or equal to dimension of the scale matrix.
      scale: `float` or `double` `Tensor`. The symmetric positive definite
        scale matrix of the distribution. Exactly one of `scale` and
        'scale_tril` must be passed.
      scale_tril: `float` or `double` `Tensor`. The Cholesky factorization
        of the symmetric positive definite scale matrix of the distribution.
        Exactly one of `scale` and 'scale_tril` must be passed.
      input_output_cholesky: Python `bool`. If `True`, functions whose input or
        output have the semantics of samples assume inputs are in Cholesky form
        and return outputs in Cholesky form. In particular, if this flag is
        `True`, input to `log_prob` is presumed of Cholesky form and output from
        `sample`, `mean`, and `mode` are of Cholesky form.  Setting this
        argument to `True` is purely a computational optimization and does not
        change the underlying distribution; for instance, `mean` returns the
        Cholesky of the mean, not the mean of Cholesky factors. The `variance`
        and `stddev` methods are unaffected by this flag.
        Default value: `False` (i.e., input/output does not have Cholesky
        semantics).
      validate_args: Python `bool`, default `False`. When `True` distribution
        parameters are checked for validity despite possibly degrading runtime
        performance. When `False` invalid inputs may silently render incorrect
        outputs.
      allow_nan_stats: Python `bool`, default `True`. When `True`, statistics
        (e.g., mean, mode, variance) use the value "`NaN`" to indicate the
        result is undefined. When `False`, an exception is raised if one or
        more of the statistic's batch members are undefined.
      name: Python `str` name prefixed to Ops created by this class.
    Raises:
      ValueError: if zero or both of 'scale' and 'scale_tril' are passed in.
    """
        parameters = dict(locals())

        with tf.name_scope(name) as name:
            with tf.name_scope("init"):
                if (scale is None) == (scale_tril is None):
                    raise ValueError(
                        "Must pass scale or scale_tril, but not both.")

                dtype = dtype_util.common_dtype([df, scale, scale_tril],
                                                tf.float32)
                df = tf.convert_to_tensor(df, name="df", dtype=dtype)
                if scale is not None:
                    scale = tf.convert_to_tensor(scale,
                                                 name="scale",
                                                 dtype=dtype)
                    if validate_args:
                        scale = distribution_util.assert_symmetric(scale)
                    scale_tril = tf.linalg.cholesky(scale)
                else:  # scale_tril is not None
                    scale_tril = tf.convert_to_tensor(scale_tril,
                                                      name="scale_tril",
                                                      dtype=dtype)
                    if validate_args:
                        scale_tril = distribution_util.with_dependencies([
                            assert_util.assert_positive(
                                tf.linalg.diag_part(scale_tril),
                                message="scale_tril must be positive definite"
                            ),
                            assert_util.assert_equal(
                                tf.shape(scale_tril)[-1],
                                tf.shape(scale_tril)[-2],
                                message="scale_tril must be square")
                        ], scale_tril)

            super(Wishart, self).__init__(
                df=df,
                scale_operator=tf.linalg.LinearOperatorLowerTriangular(
                    tril=scale_tril,
                    is_non_singular=True,
                    is_positive_definite=True,
                    is_square=True),
                input_output_cholesky=input_output_cholesky,
                validate_args=validate_args,
                allow_nan_stats=allow_nan_stats,
                name=name)
        self._parameters = parameters
예제 #26
0
 def _maybe_assert_valid_sample(self, x):
     if not self.validate_args:
         return []
     return [
         assert_util.assert_positive(x, message='Sample must be positive.')
     ]