Esempio n. 1
0
 def _check_alpha(self, alpha):
   alpha = ops.convert_to_tensor(alpha, name='alpha')
   if not self.strict:
     return alpha
   return control_flow_ops.with_dependencies(
       [check_ops.assert_rank_at_least(alpha, 1),
        check_ops.assert_positive(alpha)], alpha)
Esempio n. 2
0
 def _assert_valid_alpha(self, alpha, validate_args):
   alpha = ops.convert_to_tensor(alpha, name="alpha")
   if not validate_args:
     return alpha
   return control_flow_ops.with_dependencies(
       [check_ops.assert_rank_at_least(alpha, 1),
        check_ops.assert_positive(alpha)], alpha)
Esempio n. 3
0
def _check_alpha(alpha):
    """Check alpha for proper shape, values, then return tensor version."""
    alpha = ops.convert_to_tensor(alpha, name='alpha_before_deps')
    return control_flow_ops.with_dependencies([
        check_ops.assert_rank_at_least(alpha, 1),
        check_ops.assert_positive(alpha)
    ], alpha)
Esempio n. 4
0
def maybe_check_quadrature_param(param, name, validate_args):
    """Helper which checks validity of `loc` and `scale` init args."""
    with ops.name_scope(name="check_" + name, values=[param]):
        assertions = []
        if param.shape.ndims is not None:
            if param.shape.ndims == 0:
                raise ValueError("Mixing params must be a (batch of) vector; "
                                 "{}.rank={} is not at least one.".format(
                                     name, param.shape.ndims))
        elif validate_args:
            assertions.append(
                check_ops.assert_rank_at_least(
                    param,
                    1,
                    message=("Mixing params must be a (batch of) vector; "
                             "{}.rank is not at least one.".format(name))))

        # TODO(jvdillon): Remove once we support k-mixtures.
        if param.shape.with_rank_at_least(1)[-1] is not None:
            if param.shape[-1].value != 1:
                raise NotImplementedError(
                    "Currently only bimixtures are supported; "
                    "{}.shape[-1]={} is not 1.".format(name,
                                                       param.shape[-1].value))
        elif validate_args:
            assertions.append(
                check_ops.assert_equal(
                    array_ops.shape(param)[-1],
                    1,
                    message=("Currently only bimixtures are supported; "
                             "{}.shape[-1] is not 1.".format(name))))

        if assertions:
            return control_flow_ops.with_dependencies(assertions, param)
        return param
Esempio n. 5
0
    def __init__(self, params, labels, event_index, model_hparams=None):
        del model_hparams
        del labels
        del event_index
        params_shape = array_ops.shape(params)
        assert_rank = check_ops.assert_rank_at_least(
            params,
            2,
            data=[params_shape],
            message='Cox model params shape must be [batch_size, num_feature]')

        with ops.control_dependencies([assert_rank]):
            logits_shape = params.get_shape()[1]
            # We assume the base rate is constant in this implementation:
            # lambda = lambda_0 * exp(X * weights) = exp (bias + logits * weights)
            with tf.variable_scope('logit_to_parameter', reuse=tf.AUTO_REUSE):
                self._weights = tf.get_variable(
                    'weights', [logits_shape, 1],
                    initializer=tf.initializers.truncated_normal(0, 0.01))
                self._bias = tf.get_variable(
                    'bias', [1],
                    initializer=tf.initializers.truncated_normal(0.01, 0.01))
                weighted_logits = tf.matmul(params, self._weights) + self._bias
                self._rate_param = tf.exp(weighted_logits)
                self._distribution = tfp.distributions.Exponential(
                    rate=self._rate_param)
Esempio n. 6
0
 def test_rank_one_tensor_raises_if_rank_too_small_static_rank(self):
   tensor = constant_op.constant([1, 2], name="my_tensor")
   desired_rank = 2
   with self.assertRaisesRegexp(ValueError, "rank at least 2"):
     with ops.control_dependencies(
         [check_ops.assert_rank_at_least(tensor, desired_rank)]):
       self.evaluate(array_ops.identity(tensor))
 def _assert_valid_alpha(self, alpha, validate_args):
   alpha = ops.convert_to_tensor(alpha, name="alpha")
   if not validate_args:
     return alpha
   return control_flow_ops.with_dependencies(
       [check_ops.assert_rank_at_least(alpha, 1),
        check_ops.assert_positive(alpha)], alpha)
Esempio n. 8
0
def maybe_check_quadrature_param(param, name, validate_args):
  """Helper which checks validity of `loc` and `scale` init args."""
  with ops.name_scope(name="check_" + name, values=[param]):
    assertions = []
    if param.shape.ndims is not None:
      if param.shape.ndims == 0:
        raise ValueError("Mixing params must be a (batch of) vector; "
                         "{}.rank={} is not at least one.".format(
                             name, param.shape.ndims))
    elif validate_args:
      assertions.append(check_ops.assert_rank_at_least(
          param, 1,
          message=("Mixing params must be a (batch of) vector; "
                   "{}.rank is not at least one.".format(
                       name))))

    # TODO(jvdillon): Remove once we support k-mixtures.
    if param.shape.with_rank_at_least(1)[-1] is not None:
      if param.shape[-1].value != 1:
        raise NotImplementedError("Currently only bimixtures are supported; "
                                  "{}.shape[-1]={} is not 1.".format(
                                      name, param.shape[-1].value))
    elif validate_args:
      assertions.append(check_ops.assert_equal(
          array_ops.shape(param)[-1], 1,
          message=("Currently only bimixtures are supported; "
                   "{}.shape[-1] is not 1.".format(name))))

    if assertions:
      return control_flow_ops.with_dependencies(assertions, param)
    return param
Esempio n. 9
0
 def test_rank_one_tensor_doesnt_raise_if_rank_just_right_static_rank(self):
   with self.test_session():
     tensor = constant_op.constant([1, 2], name="my_tensor")
     desired_rank = 1
     with ops.control_dependencies(
         [check_ops.assert_rank_at_least(tensor, desired_rank)]):
       array_ops.identity(tensor).eval()
Esempio n. 10
0
 def test_rank_one_tensor_doesnt_raise_if_rank_just_right_dynamic_rank(self):
   with self.test_session():
     tensor = array_ops.placeholder(dtypes.float32, name="my_tensor")
     desired_rank = 1
     with ops.control_dependencies(
         [check_ops.assert_rank_at_least(tensor, desired_rank)]):
       array_ops.identity(tensor).eval(feed_dict={tensor: [1, 2]})
Esempio n. 11
0
def check_logits_final_dim(logits, expected_logits_dimension):
  """Checks that logits shape is [D0, D1, ... DN, logits_dimension]."""
  with ops.name_scope('logits', values=(logits,)) as scope:
    logits = math_ops.to_float(logits)
    # Eager mode
    if context.executing_eagerly():
      logits_shape = logits._shape_tuple()  # pylint: disable=protected-access
      logits_rank = logits._rank()  # pylint: disable=protected-access
      if logits_rank < 2:
        raise ValueError('logits must have rank at least 2.  Received rank {}, '
                         'shape {}'.format(logits_rank, logits_shape))
      if logits_shape[-1] != expected_logits_dimension:
        raise ValueError(
            'logits shape must be [D0, D1, ... DN, logits_dimension], '
            'got {}.'.format(logits_shape))
      return logits
    # Graph mode
    logits_shape = array_ops.shape(logits)
    assert_rank = check_ops.assert_rank_at_least(
        logits, 2, data=[logits_shape],
        message='logits shape must be [D0, D1, ... DN, logits_dimension]')
    with ops.control_dependencies([assert_rank]):
      static_shape = logits.shape
      if static_shape.ndims is not None and static_shape[-1] is not None:
        if static_shape[-1] != expected_logits_dimension:
          raise ValueError(
              'logits shape must be [D0, D1, ... DN, logits_dimension], '
              'got {}.'.format(static_shape))
        return logits
      assert_dimension = check_ops.assert_equal(
          expected_logits_dimension, logits_shape[-1], data=[logits_shape],
          message='logits shape must be [D0, D1, ... DN, logits_dimension]')
      with ops.control_dependencies([assert_dimension]):
        return array_ops.identity(logits, name=scope)
Esempio n. 12
0
 def test_rank_one_tensor_raises_if_rank_too_small_dynamic_rank(self):
   with self.test_session():
     tensor = array_ops.placeholder(dtypes.float32, name="my_tensor")
     desired_rank = 2
     with ops.control_dependencies(
         [check_ops.assert_rank_at_least(tensor, desired_rank)]):
       with self.assertRaisesOpError("my_tensor.*rank"):
         array_ops.identity(tensor).eval(feed_dict={tensor: [1, 2]})
Esempio n. 13
0
 def test_rank_zero_tensor_raises_if_rank_too_small_static_rank(self):
   with self.test_session():
     tensor = constant_op.constant(1, name="my_tensor")
     desired_rank = 1
     with self.assertRaisesRegexp(ValueError, "my_tensor.*rank at least 1"):
       with ops.control_dependencies(
           [check_ops.assert_rank_at_least(tensor, desired_rank)]):
         array_ops.identity(tensor).eval()
Esempio n. 14
0
 def test_rank_one_tensor_raises_if_rank_too_small_static_rank(self):
   with self.test_session():
     tensor = constant_op.constant([1, 2], name="my_tensor")
     desired_rank = 2
     with self.assertRaisesRegexp(ValueError, "my_tensor.*rank"):
       with ops.control_dependencies(
           [check_ops.assert_rank_at_least(tensor, desired_rank)]):
         array_ops.identity(tensor).eval()
Esempio n. 15
0
def lbeta(x, name='lbeta'):
  r"""Computes `ln(|Beta(x)|)`, reducing along the last dimension.

  Given one-dimensional `z = [z_0,...,z_{K-1}]`, we define

  ```Beta(z) = \prod_j Gamma(z_j) / Gamma(\sum_j z_j)```

  And for `n + 1` dimensional `x` with shape `[N1, ..., Nn, K]`, we define
  `lbeta(x)[i1, ..., in] = Log(|Beta(x[i1, ..., in, :])|)`.  In other words,
  the last dimension is treated as the `z` vector.

  Note that if `z = [u, v]`, then
  `Beta(z) = int_0^1 t^{u-1} (1 - t)^{v-1} dt`, which defines the traditional
  bivariate beta function.

  Args:
    x: A rank `n + 1` `Tensor` with type `float`, or `double`.
    name: A name for the operation (optional).

  Returns:
    The logarithm of `|Beta(x)|` reducing along the last dimension.

  Raises:
    ValueError:  If `x` is empty with rank one or less.
  """
  with ops.op_scope([x], name):
    x = ops.convert_to_tensor(x, name='x')
    x = control_flow_ops.with_dependencies(
        [check_ops.assert_rank_at_least(x, 1)], x)

    is_empty = math_ops.equal(0, array_ops.size(x))

    def nonempty_lbeta():
      last_index = array_ops.size(array_ops.shape(x)) - 1
      log_prod_gamma_x = math_ops.reduce_sum(
          math_ops.lgamma(x),
          reduction_indices=last_index)
      sum_x = math_ops.reduce_sum(x, reduction_indices=last_index)
      log_gamma_sum_x = math_ops.lgamma(sum_x)
      result = log_prod_gamma_x - log_gamma_sum_x
      result.set_shape(x.get_shape()[:-1])
      return result

    def empty_lbeta():
      # If x is empty, return version with one less dimension.
      # Can only do this if rank >= 2.
      assertion = check_ops.assert_rank_at_least(x, 2)
      with ops.control_dependencies([assertion]):
        return array_ops.squeeze(x, squeeze_dims=[0])

    static_size = x.get_shape().num_elements()
    if static_size is not None:
      if static_size > 0:
        return nonempty_lbeta()
      else:
        return empty_lbeta()
    else:
      return control_flow_ops.cond(is_empty, empty_lbeta, nonempty_lbeta)
def lbeta(x, name='lbeta'):
    r"""Computes `ln(|Beta(x)|)`, reducing along the last dimension.

  Given one-dimensional `z = [z_0,...,z_{K-1}]`, we define

  ```Beta(z) = \prod_j Gamma(z_j) / Gamma(\sum_j z_j)```

  And for `n + 1` dimensional `x` with shape `[N1, ..., Nn, K]`, we define
  `lbeta(x)[i1, ..., in] = Log(|Beta(x[i1, ..., in, :])|)`.  In other words,
  the last dimension is treated as the `z` vector.

  Note that if `z = [u, v]`, then
  `Beta(z) = int_0^1 t^{u-1} (1 - t)^{v-1} dt`, which defines the traditional
  bivariate beta function.

  Args:
    x: A rank `n + 1` `Tensor` with type `float`, or `double`.
    name: A name for the operation (optional).

  Returns:
    The logarithm of `|Beta(x)|` reducing along the last dimension.

  Raises:
    ValueError:  If `x` is empty with rank one or less.
  """
    with ops.op_scope([x], name):
        x = ops.convert_to_tensor(x, name='x')
        x = control_flow_ops.with_dependencies(
            [check_ops.assert_rank_at_least(x, 1)], x)

        is_empty = math_ops.equal(0, array_ops.size(x))

        def nonempty_lbeta():
            last_index = array_ops.size(array_ops.shape(x)) - 1
            log_prod_gamma_x = math_ops.reduce_sum(
                math_ops.lgamma(x), reduction_indices=last_index)
            sum_x = math_ops.reduce_sum(x, reduction_indices=last_index)
            log_gamma_sum_x = math_ops.lgamma(sum_x)
            result = log_prod_gamma_x - log_gamma_sum_x
            result.set_shape(x.get_shape()[:-1])
            return result

        def empty_lbeta():
            # If x is empty, return version with one less dimension.
            # Can only do this if rank >= 2.
            assertion = check_ops.assert_rank_at_least(x, 2)
            with ops.control_dependencies([assertion]):
                return array_ops.squeeze(x, squeeze_dims=[0])

        static_size = x.get_shape().num_elements()
        if static_size is not None:
            if static_size > 0:
                return nonempty_lbeta()
            else:
                return empty_lbeta()
        else:
            return control_flow_ops.cond(is_empty, empty_lbeta, nonempty_lbeta)
Esempio n. 17
0
 def _forward(self, x):
   if self.validate_args:
     is_matrix = check_ops.assert_rank_at_least(x, 2)
     shape = array_ops.shape(x)
     is_square = check_ops.assert_equal(shape[-2], shape[-1])
     x = control_flow_ops.with_dependencies([is_matrix, is_square], x)
   # For safety, explicitly zero-out the upper triangular part.
   x = array_ops.matrix_band_part(x, -1, 0)
   return math_ops.matmul(x, x, adjoint_b=True)
Esempio n. 18
0
 def _forward(self, x):
     if self.validate_args:
         is_matrix = check_ops.assert_rank_at_least(x, 2)
         shape = array_ops.shape(x)
         is_square = check_ops.assert_equal(shape[-2], shape[-1])
         x = control_flow_ops.with_dependencies([is_matrix, is_square], x)
     # For safety, explicitly zero-out the upper triangular part.
     x = array_ops.matrix_band_part(x, -1, 0)
     return math_ops.matmul(x, x, adjoint_b=True)
Esempio n. 19
0
  def __init__(self,
               alpha,
               validate_args=False,
               allow_nan_stats=True,
               name="Dirichlet"):
    """Initialize a batch of Dirichlet distributions.

    Args:
      alpha:  Positive floating point tensor with shape broadcastable to
        `[N1,..., Nm, k]` `m >= 0`.  Defines this as a batch of `N1 x ... x Nm`
         different `k` class Dirichlet distributions.
      validate_args: `Boolean`, default `False`.  Whether to assert valid values
        for parameters `alpha` and `x` in `prob` and `log_prob`.  If `False`,
        correct behavior is not guaranteed.
      allow_nan_stats: `Boolean`, default `True`.  If `False`, raise an
        exception if a statistic (e.g. mean/mode/etc...) is undefined for any
        batch member.  If `True`, batch members with valid parameters leading to
        undefined statistics will return NaN for this statistic.
      name: The name to prefix Ops created by this distribution class.

    Examples:

    ```python
    # Define 1-batch of 2-class Dirichlet distributions,
    # also known as a Beta distribution.
    dist = Dirichlet([1.1, 2.0])

    # Define a 2-batch of 3-class distributions.
    dist = Dirichlet([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
    ```

    """
    parameters = locals()
    parameters.pop("self")
    with ops.name_scope(name, values=[alpha]) as ns:
      alpha = ops.convert_to_tensor(alpha, name="alpha")
      with ops.control_dependencies([
          check_ops.assert_positive(alpha),
          check_ops.assert_rank_at_least(alpha, 1)
      ] if validate_args else []):
        self._alpha = array_ops.identity(alpha, name="alpha")
        self._alpha_sum = math_ops.reduce_sum(alpha,
                                              reduction_indices=[-1],
                                              keep_dims=False)
    super(Dirichlet, self).__init__(
        dtype=self._alpha.dtype,
        validate_args=validate_args,
        allow_nan_stats=allow_nan_stats,
        is_continuous=True,
        is_reparameterized=False,
        parameters=parameters,
        graph_parents=[self._alpha, self._alpha_sum],
        name=ns)
Esempio n. 20
0
    def __init__(self,
                 alpha,
                 validate_args=False,
                 allow_nan_stats=True,
                 name="Dirichlet"):
        """Initialize a batch of Dirichlet distributions.

    Args:
      alpha:  Positive floating point tensor with shape broadcastable to
        `[N1,..., Nm, k]` `m >= 0`.  Defines this as a batch of `N1 x ... x Nm`
         different `k` class Dirichlet distributions.
      validate_args: `Boolean`, default `False`.  Whether to assert valid values
        for parameters `alpha` and `x` in `prob` and `log_prob`.  If `False`,
        correct behavior is not guaranteed.
      allow_nan_stats: `Boolean`, default `True`.  If `False`, raise an
        exception if a statistic (e.g. mean/mode/etc...) is undefined for any
        batch member.  If `True`, batch members with valid parameters leading to
        undefined statistics will return NaN for this statistic.
      name: The name to prefix Ops created by this distribution class.

    Examples:

    ```python
    # Define 1-batch of 2-class Dirichlet distributions,
    # also known as a Beta distribution.
    dist = Dirichlet([1.1, 2.0])

    # Define a 2-batch of 3-class distributions.
    dist = Dirichlet([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
    ```

    """
        parameters = locals()
        parameters.pop("self")
        with ops.name_scope(name, values=[alpha]) as ns:
            alpha = ops.convert_to_tensor(alpha, name="alpha")
            with ops.control_dependencies([
                    check_ops.assert_positive(alpha),
                    check_ops.assert_rank_at_least(alpha, 1)
            ] if validate_args else []):
                self._alpha = array_ops.identity(alpha, name="alpha")
                self._alpha_sum = math_ops.reduce_sum(alpha,
                                                      reduction_indices=[-1],
                                                      keep_dims=False)
        super(Dirichlet,
              self).__init__(dtype=self._alpha.dtype,
                             validate_args=validate_args,
                             allow_nan_stats=allow_nan_stats,
                             is_continuous=True,
                             is_reparameterized=False,
                             parameters=parameters,
                             graph_parents=[self._alpha, self._alpha_sum],
                             name=ns)
Esempio n. 21
0
    def __init__(self,
                 alpha,
                 validate_args=True,
                 allow_nan_stats=False,
                 name="Dirichlet"):
        """Initialize a batch of Dirichlet distributions.

    Args:
      alpha:  Positive floating point tensor with shape broadcastable to
        `[N1,..., Nm, k]` `m >= 0`.  Defines this as a batch of `N1 x ... x Nm`
         different `k` class Dirichlet distributions.
      validate_args: Whether to assert valid values for parameters `alpha` and
        `x` in `prob` and `log_prob`.  If `False`, correct behavior is not
        guaranteed.
      allow_nan_stats:  Boolean, default `False`.  If `False`, raise an
        exception if a statistic (e.g. mean/mode/etc...) is undefined for any
        batch member.  If `True`, batch members with valid parameters leading to
        undefined statistics will return NaN for this statistic.
      name: The name to prefix Ops created by this distribution class.

    Examples:

    ```python
    # Define 1-batch of 2-class Dirichlet distributions,
    # also known as a Beta distribution.
    dist = Dirichlet([1.1, 2.0])

    # Define a 2-batch of 3-class distributions.
    dist = Dirichlet([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
    ```

    """
        with ops.op_scope([alpha], name):
            alpha = ops.convert_to_tensor(alpha, name="alpha_before_deps")
            with ops.control_dependencies([
                    check_ops.assert_positive(alpha),
                    check_ops.assert_rank_at_least(alpha, 1)
            ] if validate_args else []):
                alpha = array_ops.identity(alpha, name="alpha")

            self._alpha = alpha
            self._name = name

            # Used for mean/mode/variance/entropy computations
            self._alpha_0 = math_ops.reduce_sum(alpha,
                                                reduction_indices=[-1],
                                                keep_dims=False)

            self._get_batch_shape = self._alpha_0.get_shape()
            self._get_event_shape = self._alpha.get_shape().with_rank_at_least(
                1)[-1:]
            self._validate_args = validate_args
            self._allow_nan_stats = allow_nan_stats
Esempio n. 22
0
  def __init__(self,
               alpha,
               validate_args=True,
               allow_nan_stats=False,
               name="Dirichlet"):
    """Initialize a batch of Dirichlet distributions.

    Args:
      alpha:  Positive floating point tensor with shape broadcastable to
        `[N1,..., Nm, k]` `m >= 0`.  Defines this as a batch of `N1 x ... x Nm`
         different `k` class Dirichlet distributions.
      validate_args: Whether to assert valid values for parameters `alpha` and
        `x` in `prob` and `log_prob`.  If `False`, correct behavior is not
        guaranteed.
      allow_nan_stats:  Boolean, default `False`.  If `False`, raise an
        exception if a statistic (e.g. mean/mode/etc...) is undefined for any
        batch member.  If `True`, batch members with valid parameters leading to
        undefined statistics will return NaN for this statistic.
      name: The name to prefix Ops created by this distribution class.

    Examples:

    ```python
    # Define 1-batch of 2-class Dirichlet distributions,
    # also known as a Beta distribution.
    dist = Dirichlet([1.1, 2.0])

    # Define a 2-batch of 3-class distributions.
    dist = Dirichlet([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
    ```

    """
    with ops.op_scope([alpha], name):
      alpha = ops.convert_to_tensor(alpha, name="alpha_before_deps")
      with ops.control_dependencies([
          check_ops.assert_positive(alpha), check_ops.assert_rank_at_least(
              alpha, 1)
      ] if validate_args else []):
        alpha = array_ops.identity(alpha, name="alpha")

      self._alpha = alpha
      self._name = name

      # Used for mean/mode/variance/entropy computations
      self._alpha_0 = math_ops.reduce_sum(alpha,
                                          reduction_indices=[-1],
                                          keep_dims=False)

      self._get_batch_shape = self._alpha_0.get_shape()
      self._get_event_shape = self._alpha.get_shape().with_rank_at_least(1)[-1:]
      self._validate_args = validate_args
      self._allow_nan_stats = allow_nan_stats
Esempio n. 23
0
 def _prob(self, x):
   if self.validate_args:
     is_vector_check = check_ops.assert_rank_at_least(x, 1)
     right_vec_space_check = check_ops.assert_equal(
         self.event_shape_tensor(),
         array_ops.gather(array_ops.shape(x), array_ops.rank(x) - 1),
         message=
         "Argument 'x' not defined in the same space R^k as this distribution")
     with ops.control_dependencies([is_vector_check]):
       with ops.control_dependencies([right_vec_space_check]):
         x = array_ops.identity(x)
   return math_ops.cast(
       math_ops.reduce_all(math_ops.abs(x - self.loc) <= self._slack, axis=-1),
       dtype=self.dtype)
Esempio n. 24
0
 def _maybe_assert_valid_concentration(self, concentration, validate_args):
   """Checks the validity of the concentration parameter."""
   if not validate_args:
     return concentration
   return control_flow_ops.with_dependencies([
       check_ops.assert_positive(
           concentration,
           message="Concentration parameter must be positive."),
       check_ops.assert_rank_at_least(
           concentration, 1,
           message="Concentration parameter must have >=1 dimensions."),
       check_ops.assert_less(
           1, array_ops.shape(concentration)[-1],
           message="Concentration parameter must have event_size >= 2."),
   ], concentration)
Esempio n. 25
0
def _maybe_validate_matrix(a, validate_args):
  """Checks that input is a `float` matrix."""
  assertions = []
  if not a.dtype.is_floating:
    raise TypeError('Input `a` must have `float`-like `dtype` '
                    '(saw {}).'.format(a.dtype.name))
  if a.shape is not None and a.shape.rank is not None:
    if a.shape.rank < 2:
      raise ValueError('Input `a` must have at least 2 dimensions '
                       '(saw: {}).'.format(a.shape.rank))
  elif validate_args:
    assertions.append(
        check_ops.assert_rank_at_least(
            a, rank=2, message='Input `a` must have at least 2 dimensions.'))
  return assertions
 def _maybe_assert_valid_concentration(self, concentration, validate_args):
   """Checks the validity of the concentration parameter."""
   if not validate_args:
     return concentration
   return control_flow_ops.with_dependencies([
       check_ops.assert_positive(
           concentration,
           message="Concentration parameter must be positive."),
       check_ops.assert_rank_at_least(
           concentration, 1,
           message="Concentration parameter must have >=1 dimensions."),
       check_ops.assert_less(
           1, array_ops.shape(concentration)[-1],
           message="Concentration parameter must have event_size >= 2."),
   ], concentration)
Esempio n. 27
0
    def __init__(self, params, labels, event_index, model_hparams=None):
        del model_hparams
        del labels
        del event_index
        params_shape = array_ops.shape(params)
        assert_rank = check_ops.assert_rank_at_least(
            params,
            2,
            data=[params_shape],
            message='Exponential model params shape must be [batch_size, 1]')

        with ops.control_dependencies([assert_rank]):
            # TODO(yuanxue,gafm): Experiment with tf.softplus.
            self._rate_param = tf.exp(params + INITIAL_LN_RATE)
            self._distribution = tfp.distributions.Exponential(
                rate=self._rate_param)
Esempio n. 28
0
    def _check_chol(self, chol):
        """Verify that `chol` is proper."""
        chol = ops.convert_to_tensor(chol, name='chol')
        if not self.verify_pd:
            return chol

        shape = array_ops.shape(chol)
        rank = array_ops.rank(chol)

        is_matrix = check_ops.assert_rank_at_least(chol, 2)
        is_square = check_ops.assert_equal(array_ops.gather(shape, rank - 2),
                                           array_ops.gather(shape, rank - 1))

        deps = [is_matrix, is_square]
        deps.append(check_ops.assert_positive(self._diag))

        return control_flow_ops.with_dependencies(deps, chol)
Esempio n. 29
0
  def _check_chol(self, chol):
    """Verify that `chol` is proper."""
    chol = ops.convert_to_tensor(chol, name='chol')
    if not self.verify_pd:
      return chol

    shape = array_ops.shape(chol)
    rank = array_ops.rank(chol)

    is_matrix = check_ops.assert_rank_at_least(chol, 2)
    is_square = check_ops.assert_equal(
        array_ops.gather(shape, rank - 2), array_ops.gather(shape, rank - 1))

    deps = [is_matrix, is_square]
    deps.append(check_ops.assert_positive(self._diag))

    return control_flow_ops.with_dependencies(deps, chol)
Esempio n. 30
0
def _check_logits_final_dim(logits, expected_logits_dimension):
  """Checks that logits shape is [D0, D1, ... DN, logits_dimension]."""
  with ops.name_scope(None, 'logits', (logits,)) as scope:
    logits = math_ops.to_float(logits)
    logits_shape = array_ops.shape(logits)
    assert_rank = check_ops.assert_rank_at_least(
        logits, 2, data=[logits_shape],
        message='logits shape must be [D0, D1, ... DN, logits_dimension]')
    with ops.control_dependencies([assert_rank]):
      static_shape = logits.shape
      if static_shape.ndims is not None and static_shape[-1] is not None:
        if static_shape[-1] != expected_logits_dimension:
          raise ValueError(
              'logits shape must be [D0, D1, ... DN, logits_dimension], '
              'got %s.' % (static_shape,))
        return logits
      assert_dimension = check_ops.assert_equal(
          expected_logits_dimension, logits_shape[-1], data=[logits_shape],
          message='logits shape must be [D0, D1, ... DN, logits_dimension]')
      with ops.control_dependencies([assert_dimension]):
        return array_ops.identity(logits, name=scope)
Esempio n. 31
0
def _check_logits_final_dim(logits, expected_logits_dimension):
  """Checks that logits shape is [D0, D1, ... DN, logits_dimension]."""
  with ops.name_scope(None, 'logits', (logits,)) as scope:
    logits = math_ops.to_float(logits)
    logits_shape = array_ops.shape(logits)
    assert_rank = check_ops.assert_rank_at_least(
        logits, 2, data=[logits_shape],
        message='logits shape must be [D0, D1, ... DN, logits_dimension]')
    with ops.control_dependencies([assert_rank]):
      static_shape = logits.shape
      if static_shape.ndims is not None and static_shape[-1] is not None:
        if static_shape[-1] != expected_logits_dimension:
          raise ValueError(
              'logits shape must be [D0, D1, ... DN, logits_dimension], '
              'got %s.' % (static_shape,))
        return logits
      assert_dimension = check_ops.assert_equal(
          expected_logits_dimension, logits_shape[-1], data=[logits_shape],
          message='logits shape must be [D0, D1, ... DN, logits_dimension]')
      with ops.control_dependencies([assert_dimension]):
        return array_ops.identity(logits, name=scope)
 def _assertions(self, x):
   if not self.validate_args:
     return []
   shape = array_ops.shape(x)
   is_matrix = check_ops.assert_rank_at_least(
       x, 2, message="Input must have rank at least 2.")
   is_square = check_ops.assert_equal(
       shape[-2], shape[-1], message="Input must be a square matrix.")
   above_diagonal = array_ops.matrix_band_part(
       array_ops.matrix_set_diag(
           x, array_ops.zeros(shape[:-1], dtype=dtypes.float32)),
       0, -1)
   is_lower_triangular = check_ops.assert_equal(
       above_diagonal, array_ops.zeros_like(above_diagonal),
       message="Input must be lower triangular.")
   # A lower triangular matrix is nonsingular iff all its diagonal entries are
   # nonzero.
   diag_part = array_ops.matrix_diag_part(x)
   is_nonsingular = check_ops.assert_none_equal(
       diag_part, array_ops.zeros_like(diag_part),
       message="Input must have all diagonal entries nonzero.")
   return [is_matrix, is_square, is_lower_triangular, is_nonsingular]
Esempio n. 33
0
 def _assertions(self, x):
   if not self.validate_args:
     return []
   shape = array_ops.shape(x)
   is_matrix = check_ops.assert_rank_at_least(
       x, 2, message="Input must have rank at least 2.")
   is_square = check_ops.assert_equal(
       shape[-2], shape[-1], message="Input must be a square matrix.")
   above_diagonal = array_ops.matrix_band_part(
       array_ops.matrix_set_diag(
           x, array_ops.zeros(shape[:-1], dtype=dtypes.float32)),
       0, -1)
   is_lower_triangular = check_ops.assert_equal(
       above_diagonal, array_ops.zeros_like(above_diagonal),
       message="Input must be lower triangular.")
   # A lower triangular matrix is nonsingular iff all its diagonal entries are
   # nonzero.
   diag_part = array_ops.matrix_diag_part(x)
   is_nonsingular = check_ops.assert_none_equal(
       diag_part, array_ops.zeros_like(diag_part),
       message="Input must have all diagonal entries nonzero.")
   return [is_matrix, is_square, is_lower_triangular, is_nonsingular]
Esempio n. 34
0
def _lu_solve_assertions(lower_upper, perm, rhs, validate_args):
    """Returns list of assertions related to `lu_solve` assumptions."""
    assertions = lu_reconstruct_assertions(lower_upper, perm, validate_args)

    message = 'Input `rhs` must have at least 2 dimensions.'
    if rhs.shape.ndims is not None:
        if rhs.shape.ndims < 2:
            raise ValueError(message)
    elif validate_args:
        assertions.append(
            check_ops.assert_rank_at_least(rhs, rank=2, message=message))

    message = '`lower_upper.shape[-1]` must equal `rhs.shape[-1]`.'
    if (lower_upper.shape[-1] is not None and rhs.shape[-2] is not None):
        if lower_upper.shape[-1] != rhs.shape[-2]:
            raise ValueError(message)
    elif validate_args:
        assertions.append(
            check_ops.assert_equal(array_ops.shape(lower_upper)[-1],
                                   array_ops.shape(rhs)[-2],
                                   message=message))

    return assertions
Esempio n. 35
0
File: util.py Progetto: lengjia/RRL
def embed_check_categorical_event_shape(
        categorical_param, name="embed_check_categorical_event_shape"):
    """Embeds checks that categorical distributions don't have too many classes.

  A categorical-type distribution is one which, e.g., returns the class label
  rather than a one-hot encoding.  E.g., `Categorical(probs)`.

  Since distributions output samples in the same dtype as the parameters, we
  must ensure that casting doesn't lose precision. That is, the
  `parameter.dtype` implies a maximum number of classes. However, since shape is
  `int32` and categorical variables are presumed to be indexes into a `Tensor`,
  we must also ensure that the number of classes is no larger than the largest
  possible `int32` index, i.e., `2**31-1`.

  In other words the number of classes, `K`, must satisfy the following
  condition:

  ```python
  K <= min(
      int(2**31 - 1),  # Largest float as an index.
      {
          dtypes.float16: int(2**11),   # Largest int as a float16.
          dtypes.float32: int(2**24),
          dtypes.float64: int(2**53),
      }.get(categorical_param.dtype.base_dtype, 0))
  ```

  Args:
    categorical_param: Floating-point `Tensor` representing parameters of
      distribution over categories. The rightmost shape is presumed to be the
      number of categories.
    name: A name for this operation (optional).

  Returns:
    categorical_param: Input `Tensor` with appropriate assertions embedded.

  Raises:
    TypeError: if `categorical_param` has an unknown `dtype`.
    ValueError: if we can statically identify `categorical_param` as being too
      large (for being closed under int32/float casting).
  """
    with ops.name_scope(name, values=[categorical_param]):
        x = ops.convert_to_tensor(categorical_param, name="categorical_param")
        # The size must not exceed both of:
        # - The largest possible int32 (since categorical values are presumed to be
        #   indexes into a Tensor).
        # - The largest possible integer exactly representable under the given
        #   floating-point dtype (since we need to cast to/from).
        #
        # The chosen floating-point thresholds are 2**(1 + mantissa_bits).
        # For more details, see:
        # https://en.wikipedia.org/wiki/Floating-point_arithmetic#Internal_representation
        x_dtype = x.dtype.base_dtype
        max_event_size = (_largest_integer_by_dtype(x_dtype)
                          if x_dtype.is_floating else 0)
        if max_event_size is 0:
            raise TypeError("Unable to validate size of unrecognized dtype "
                            "({}).".format(x_dtype.name))
        try:
            x_shape_static = x.get_shape().with_rank_at_least(1)
        except ValueError:
            raise ValueError("A categorical-distribution parameter must have "
                             "at least 1 dimension.")
        if x_shape_static[-1].value is not None:
            event_size = x_shape_static[-1].value
            if event_size < 2:
                raise ValueError(
                    "A categorical-distribution parameter must have at "
                    "least 2 events.")
            if event_size > max_event_size:
                raise ValueError(
                    "Number of classes exceeds `dtype` precision, i.e., "
                    "{} implies shape ({}) cannot exceed {}.".format(
                        x_dtype.name, event_size, max_event_size))
            return x
        else:
            event_size = array_ops.shape(x, name="x_shape")[-1]
            return control_flow_ops.with_dependencies([
                check_ops.assert_rank_at_least(
                    x,
                    1,
                    message=("A categorical-distribution parameter must have "
                             "at least 1 dimension.")),
                check_ops.assert_greater_equal(
                    array_ops.shape(x)[-1],
                    2,
                    message=(
                        "A categorical-distribution parameter must have at "
                        "least 2 events.")),
                check_ops.assert_less_equal(
                    event_size,
                    max_event_size,
                    message="Number of classes exceeds `dtype` precision, "
                    "i.e., {} dtype cannot exceed {} shape.".format(
                        x_dtype.name, max_event_size)),
            ], x)
Esempio n. 36
0
def _check_alpha(alpha):
  """Check alpha for proper shape, values, then return tensor version."""
  alpha = ops.convert_to_tensor(alpha, name='alpha_before_deps')
  return control_flow_ops.with_dependencies(
      [check_ops.assert_rank_at_least(alpha, 1),
       check_ops.assert_positive(alpha)], alpha)
Esempio n. 37
0
 def empty_lbeta():
   # If x is empty, return version with one less dimension.
   # Can only do this if rank >= 2.
   assertion = check_ops.assert_rank_at_least(x, 2)
   with ops.control_dependencies([assertion]):
     return array_ops.squeeze(x, squeeze_dims=[0])
Esempio n. 38
0
def _check_dense_labels_match_logits_and_reshape(
    labels, logits, expected_labels_dimension):
  """Checks that labels shape matches logits and reshapes if needed.

  Consider logits of shape [D0, D1, ... DN, logits_dimension]. Then labels
  shape must be [D0, D1, ... DN, expected_labels_dimension].
  If expected_labels_dimension=1, labels could be [D0, D1, ... DN] and this
  method reshapes them to [D0, D1, ... DN, 1].

  Args:
    labels: labels Tensor.
    logits: logits Tensor.
    expected_labels_dimension: Integer.
  Returns:
    Validated and reshaped labels Tensor.
  Raises:
    ValueError: If labels is a SparseTensor.
    ValueError: If labels shape is statically defined and fails validation.
    OpError: If labels shape is not statically defined and fails validation.
  """
  if labels is None:
    raise ValueError(
        'You must provide a labels Tensor. Given: None. '
        'Suggested troubleshooting steps: Check that your data contain '
        'your label feature. Check that your input_fn properly parses and '
        'returns labels.')
  with ops.name_scope(None, 'labels', (labels, logits)) as scope:
    labels = sparse_tensor.convert_to_tensor_or_sparse_tensor(labels)
    if isinstance(labels, sparse_tensor.SparseTensor):
      raise ValueError(
          'SparseTensor labels are not supported. '
          'labels must be a Tensor of shape [D0, D1, ..., DN, %s], '
          'e.g. [batch_size, %s]. '
          'Suggested Fix (1): Check the label feature in your data. '
          'Each example must contain %s value(s). If not, your choice of label '
          'was probably incorrect. '
          'Suggested Fix (2): In your input_fn, use '
          'tf.sparse_tensor_to_dense() to turn labels into a Tensor.'
          '' % (expected_labels_dimension, expected_labels_dimension,
                expected_labels_dimension))
    if (labels.shape.ndims is not None and logits.shape.ndims is not None and
        labels.shape.ndims == logits.shape.ndims - 1):
      labels = array_ops.expand_dims(labels, -1)
    labels_shape = array_ops.shape(labels)
    logits_shape = array_ops.shape(logits)
    err_msg = (
        'labels shape must be [D0, D1, ... DN, {}]. '
        'Suggested Fix: check your n_classes argument to the estimator '
        'and/or the shape of your label.'.format(expected_labels_dimension))
    assert_rank = check_ops.assert_rank_at_least(labels, 2, message=err_msg)
    with ops.control_dependencies([assert_rank]):
      static_shape = labels.shape
      if static_shape.ndims is not None:
        dim1 = static_shape[-1]
        if (dim1 is not None) and (dim1 != expected_labels_dimension):
          raise ValueError(
              'Mismatched label shape. '
              'Classifier configured with n_classes=%s.  Received %s. '
              'Suggested Fix: check your n_classes argument to the estimator '
              'and/or the shape of your label.' %
              (expected_labels_dimension, dim1))
      expected_labels_shape = array_ops.concat(
          [logits_shape[:-1], [expected_labels_dimension]], axis=0)
      assert_dimension = check_ops.assert_equal(
          expected_labels_shape, labels_shape, message=err_msg,
          data=['expected_labels_shape: ', expected_labels_shape,
                'labels_shape: ', labels_shape])
      with ops.control_dependencies([assert_dimension]):
        return array_ops.identity(labels, name=scope)
Esempio n. 39
0
def _check_dense_labels_match_logits_and_reshape(
    labels, logits, expected_labels_dimension):
  """Checks that labels shape matches logits and reshapes if needed.

  Consider logits of shape [D0, D1, ... DN, logits_dimension]. Then labels
  shape must be [D0, D1, ... DN, expected_labels_dimension].
  If expected_labels_dimension=1, labels could be [D0, D1, ... DN] and this
  method reshapes them to [D0, D1, ... DN, 1].

  Args:
    labels: labels Tensor.
    logits: logits Tensor.
    expected_labels_dimension: Integer.
  Returns:
    Validated and reshaped labels Tensor.
  Raises:
    ValueError: If labels is a SparseTensor.
    ValueError: If labels shape is statically defined and fails validation.
    OpError: If labels shape is not statically defined and fails validation.
  """
  if labels is None:
    raise ValueError(
        'You must provide a labels Tensor. Given: None. '
        'Suggested troubleshooting steps: Check that your data contain '
        'your label feature. Check that your input_fn properly parses and '
        'returns labels.')
  with ops.name_scope(None, 'labels', (labels, logits)) as scope:
    labels = sparse_tensor.convert_to_tensor_or_sparse_tensor(labels)
    if isinstance(labels, sparse_tensor.SparseTensor):
      raise ValueError(
          'SparseTensor labels are not supported. '
          'labels must be a Tensor of shape [D0, D1, ..., DN, %s], '
          'e.g. [batch_size, %s]. '
          'Suggested Fix (1): Check the label feature in your data. '
          'Each example must contain %s value(s). If not, your choice of label '
          'was probably incorrect. '
          'Suggested Fix (2): In your input_fn, use '
          'tf.sparse_tensor_to_dense() to turn labels into a Tensor.'
          '' % (expected_labels_dimension, expected_labels_dimension,
                expected_labels_dimension))
    if (labels.shape.ndims is not None and logits.shape.ndims is not None and
        labels.shape.ndims == logits.shape.ndims - 1):
      labels = array_ops.expand_dims(labels, -1)
    labels_shape = array_ops.shape(labels)
    logits_shape = array_ops.shape(logits)
    err_msg = (
        'labels shape must be [D0, D1, ... DN, {}]. '
        'Suggested Fix: check your n_classes argument to the estimator '
        'and/or the shape of your label.'.format(expected_labels_dimension))
    assert_rank = check_ops.assert_rank_at_least(labels, 2, message=err_msg)
    with ops.control_dependencies([assert_rank]):
      static_shape = labels.shape
      if static_shape.ndims is not None:
        dim1 = static_shape[-1]
        if (dim1 is not None) and (dim1 != expected_labels_dimension):
          raise ValueError(
              'Mismatched label shape. '
              'Classifier configured with n_classes=%s.  Received %s. '
              'Suggested Fix: check your n_classes argument to the estimator '
              'and/or the shape of your label.' %
              (expected_labels_dimension, dim1))
      expected_labels_shape = array_ops.concat(
          [logits_shape[:-1], [expected_labels_dimension]], axis=0)
      assert_dimension = check_ops.assert_equal(
          expected_labels_shape, labels_shape, message=err_msg,
          data=['expected_labels_shape: ', expected_labels_shape,
                'labels_shape: ', labels_shape])
      with ops.control_dependencies([assert_dimension]):
        return array_ops.identity(labels, name=scope)
Esempio n. 40
0
def check_dense_labels_match_logits_and_reshape(labels, logits,
                                                expected_labels_dimension):
    """Checks labels shape matches logits, and reshapes if needed.

  Consider logits of shape [D0, D1, ... DN, logits_dimension]. Then labels
  shape must be [D0, D1, ... DN, expected_labels_dimension].
  If expected_labels_dimension=1, labels could be [D0, D1, ... DN] and this
  method reshapes them to [D0, D1, ... DN, 1].

  Args:
    labels: labels Tensor.
    logits: logits Tensor.
    expected_labels_dimension: Integer.

  Returns:
    Validated and reshaped labels Tensor.

  Raises:
    ValueError: If labels is a SparseTensor.
    ValueError: If labels shape is statically defined and fails validation.
    OpError: If labels shape is not statically defined and fails validation.
  """
    if labels is None:
        raise ValueError(_LABEL_NONE_ERR_MSG)
    with ops.name_scope('labels', values=(labels, logits)) as scope:
        labels = sparse_tensor.convert_to_tensor_or_sparse_tensor(labels)
        if isinstance(labels, sparse_tensor.SparseTensor):
            raise ValueError(
                _SPARSE_LABEL_ERR_MSG.format(expected_labels_dimension,
                                             expected_labels_dimension,
                                             expected_labels_dimension))
        # Eager mode.
        if context.executing_eagerly():
            labels_rank = labels._rank()  # pylint: disable=protected-access
            logits_rank = logits._rank()  # pylint: disable=protected-access
            if (labels_rank is not None and logits_rank is not None
                    and labels_rank == logits_rank - 1):
                labels = array_ops.expand_dims(labels, -1)
                labels_rank += 1
            labels_shape = labels._shape_tuple()  # pylint: disable=protected-access
            if labels_rank < 2:
                raise ValueError(
                    'labels must have rank at least 2.  Received rank {}, '
                    'shape {}'.format(labels_rank, labels_shape))
            if labels_shape[-1] != expected_labels_dimension:
                raise ValueError(
                    _MISMATCHED_LABEL_DIM_ERR_MSG.format(
                        expected_labels_dimension, labels_shape[-1]))
            logits_shape = logits._shape_tuple()  # pylint: disable=protected-access
            expected_labels_shape = logits_shape[:-1] + (
                expected_labels_dimension, )
            if expected_labels_shape != labels_shape:
                raise ValueError(
                    '{}, expected_labels_shape: {}. labels_shape: {}.'.format(
                        _LABEL_SHAPE_ERR_MSG.format(expected_labels_dimension),
                        expected_labels_shape, labels_shape))
            return labels

        # Graph mode.
        if (labels.shape.ndims is not None and logits.shape.ndims is not None
                and labels.shape.ndims == logits.shape.ndims - 1):
            labels = array_ops.expand_dims(labels, -1)
        assert_rank = check_ops.assert_rank_at_least(
            labels,
            2,
            message=_LABEL_SHAPE_ERR_MSG.format(expected_labels_dimension))
        with ops.control_dependencies([assert_rank]):
            static_shape = labels.shape
            if static_shape.ndims is not None:
                final_dim = static_shape[-1]
                if (final_dim is not None) and (final_dim !=
                                                expected_labels_dimension):
                    raise ValueError(
                        _MISMATCHED_LABEL_DIM_ERR_MSG.format(
                            expected_labels_dimension, final_dim))
            logits_shape = array_ops.shape(logits)
            expected_labels_shape = array_ops.concat(
                [logits_shape[:-1], [expected_labels_dimension]], axis=0)
            labels_shape = array_ops.shape(labels)
            assert_dimension = check_ops.assert_equal(
                expected_labels_shape,
                labels_shape,
                message=_LABEL_SHAPE_ERR_MSG.format(expected_labels_dimension),
                data=[
                    'expected_labels_shape: ', expected_labels_shape,
                    'labels_shape: ', labels_shape
                ])
            with ops.control_dependencies([assert_dimension]):
                return array_ops.identity(labels, name=scope)
Esempio n. 41
0
  def __init__(self,
               loc,
               atol=None,
               rtol=None,
               is_vector=False,
               validate_args=False,
               allow_nan_stats=True,
               name="_BaseDeterministic"):
    """Initialize a batch of `_BaseDeterministic` distributions.

    The `atol` and `rtol` parameters allow for some slack in `pmf`, `cdf`
    computations, e.g. due to floating-point error.

    ```
    pmf(x; loc)
      = 1, if Abs(x - loc) <= atol + rtol * Abs(loc),
      = 0, otherwise.
    ```

    Args:
      loc: Numeric `Tensor`.  The point (or batch of points) on which this
        distribution is supported.
      atol:  Non-negative `Tensor` of same `dtype` as `loc` and broadcastable
        shape.  The absolute tolerance for comparing closeness to `loc`.
        Default is `0`.
      rtol:  Non-negative `Tensor` of same `dtype` as `loc` and broadcastable
        shape.  The relative tolerance for comparing closeness to `loc`.
        Default is `0`.
      is_vector:  Python `bool`.  If `True`, this is for `VectorDeterministic`,
        else `Deterministic`.
      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 `loc` is a scalar.
    """
    parameters = locals()
    with ops.name_scope(name, values=[loc, atol, rtol]):
      loc = ops.convert_to_tensor(loc, name="loc")
      if is_vector and validate_args:
        msg = "Argument loc must be at least rank 1."
        if loc.get_shape().ndims is not None:
          if loc.get_shape().ndims < 1:
            raise ValueError(msg)
        else:
          loc = control_flow_ops.with_dependencies(
              [check_ops.assert_rank_at_least(loc, 1, message=msg)], loc)
      self._loc = loc

      super(_BaseDeterministic, self).__init__(
          dtype=self._loc.dtype,
          reparameterization_type=distribution.NOT_REPARAMETERIZED,
          validate_args=validate_args,
          allow_nan_stats=allow_nan_stats,
          parameters=parameters,
          graph_parents=[self._loc],
          name=name)

      self._atol = self._get_tol(atol)
      self._rtol = self._get_tol(rtol)
      # Avoid using the large broadcast with self.loc if possible.
      if rtol is None:
        self._slack = self.atol
      else:
        self._slack = self.atol + self.rtol * math_ops.abs(self.loc)
Esempio n. 42
0
 def empty_lbeta():
     # If x is empty, return version with one less dimension.
     # Can only do this if rank >= 2.
     assertion = check_ops.assert_rank_at_least(x, 2)
     with ops.control_dependencies([assertion]):
         return array_ops.squeeze(x, squeeze_dims=[0])
  def _forward_log_det_jacobian(self, x):
    # Let Y be a symmetric, positive definite matrix and write:
    #   Y = X X.T
    # where X is lower-triangular.
    #
    # Observe that,
    #   dY[i,j]/dX[a,b]
    #   = d/dX[a,b] { X[i,:] X[j,:] }
    #   = sum_{d=1}^p { I[i=a] I[d=b] X[j,d] + I[j=a] I[d=b] X[i,d] }
    #
    # To compute the Jacobian dX/dY we must represent X,Y as vectors. Since Y is
    # symmetric and X is lower-triangular, we need vectors of dimension:
    #   d = p (p + 1) / 2
    # where X, Y are p x p matrices, p > 0. We use a row-major mapping, i.e.,
    #   k = { i (i + 1) / 2 + j   i>=j
    #       { undef               i<j
    # and assume zero-based indexes. When k is undef, the element is dropped.
    # Example:
    #           j      k
    #        0 1 2 3  /
    #    0 [ 0 . . . ]
    # i  1 [ 1 2 . . ]
    #    2 [ 3 4 5 . ]
    #    3 [ 6 7 8 9 ]
    # Write vec[.] to indicate transforming a matrix to vector via k(i,j). (With
    # slight abuse: k(i,j)=undef means the element is dropped.)
    #
    # We now show d vec[Y] / d vec[X] is lower triangular. Assuming both are
    # defined, observe that k(i,j) < k(a,b) iff (1) i<a or (2) i=a and j<b.
    # In both cases dvec[Y]/dvec[X]@[k(i,j),k(a,b)] = 0 since:
    # (1) j<=i<a thus i,j!=a.
    # (2) i=a>j  thus i,j!=a.
    #
    # Since the Jacobian is lower-triangular, we need only compute the product
    # of diagonal elements:
    #   d vec[Y] / d vec[X] @[k(i,j), k(i,j)]
    #   = X[j,j] + I[i=j] X[i,j]
    #   = 2 X[j,j].
    # Since there is a 2 X[j,j] term for every lower-triangular element of X we
    # conclude:
    #   |Jac(d vec[Y]/d vec[X])| = 2^p prod_{j=0}^{p-1} X[j,j]^{p-j}.
    if self._static_event_ndims == 0:
      if self.validate_args:
        is_positive = check_ops.assert_positive(
            x, message="All elements must be positive.")
        x = control_flow_ops.with_dependencies([is_positive], x)
      return np.log(2.) + math_ops.log(x)

    diag = array_ops.matrix_diag_part(x)

    # We now ensure diag is columnar. Eg, if `diag = [1, 2, 3]` then the output
    # is `[[1], [2], [3]]` and if `diag = [[1, 2, 3], [4, 5, 6]]` then the
    # output is unchanged.
    diag = self._make_columnar(diag)

    if self.validate_args:
      is_matrix = check_ops.assert_rank_at_least(
          x, 2, message="Input must be a (batch of) matrix.")
      shape = array_ops.shape(x)
      is_square = check_ops.assert_equal(
          shape[-2], shape[-1],
          message="Input must be a (batch of) square matrix.")
      # Assuming lower-triangular means we only need check diag>0.
      is_positive_definite = check_ops.assert_positive(
          diag, message="Input must be positive definite.")
      x = control_flow_ops.with_dependencies(
          [is_matrix, is_square, is_positive_definite], x)

    # Create a vector equal to: [p, p-1, ..., 2, 1].
    if x.get_shape().ndims is None or x.get_shape()[-1].value is None:
      p_int = array_ops.shape(x)[-1]
      p_float = math_ops.cast(p_int, dtype=x.dtype)
    else:
      p_int = x.get_shape()[-1].value
      p_float = np.array(p_int, dtype=x.dtype.as_numpy_dtype)
    exponents = math_ops.linspace(p_float, 1., p_int)

    sum_weighted_log_diag = array_ops.squeeze(
        math_ops.matmul(math_ops.log(diag),
                        exponents[..., array_ops.newaxis]),
        squeeze_dims=-1)
    fldj = p_float * np.log(2.) + sum_weighted_log_diag

    return fldj
Esempio n. 44
0
 def test_rank_zero_tensor_doesnt_raise_if_rank_just_right_static_rank(self):
   tensor = constant_op.constant(1, name="my_tensor")
   desired_rank = 0
   with ops.control_dependencies(
       [check_ops.assert_rank_at_least(tensor, desired_rank)]):
     self.evaluate(array_ops.identity(tensor))
Esempio n. 45
0
def embed_check_categorical_event_shape(
    categorical_param,
    name="embed_check_categorical_event_shape"):
  """Embeds checks that categorical distributions don't have too many classes.

  A categorical-type distribution is one which, e.g., returns the class label
  rather than a one-hot encoding.  E.g., `Categorical(probs)`.

  Since distributions output samples in the same dtype as the parameters, we
  must ensure that casting doesn't lose precision. That is, the
  `parameter.dtype` implies a maximum number of classes. However, since shape is
  `int32` and categorical variables are presumed to be indexes into a `Tensor`,
  we must also ensure that the number of classes is no larger than the largest
  possible `int32` index, i.e., `2**31-1`.

  In other words the number of classes, `K`, must satisfy the following
  condition:

  ```python
  K <= min(
      int(2**31 - 1),  # Largest float as an index.
      {
          dtypes.float16: int(2**11),   # Largest int as a float16.
          dtypes.float32: int(2**24),
          dtypes.float64: int(2**53),
      }.get(categorical_param.dtype.base_dtype, 0))
  ```

  Args:
    categorical_param: Floating-point `Tensor` representing parameters of
      distribution over categories. The rightmost shape is presumed to be the
      number of categories.
    name: A name for this operation (optional).

  Returns:
    categorical_param: Input `Tensor` with appropriate assertions embedded.

  Raises:
    TypeError: if `categorical_param` has an unknown `dtype`.
    ValueError: if we can statically identify `categorical_param` as being too
      large (for being closed under int32/float casting).
  """
  with ops.name_scope(name, values=[categorical_param]):
    x = ops.convert_to_tensor(categorical_param, name="categorical_param")
    # The size must not exceed both of:
    # - The largest possible int32 (since categorical values are presumed to be
    #   indexes into a Tensor).
    # - The largest possible integer exactly representable under the given
    #   floating-point dtype (since we need to cast to/from).
    #
    # The chosen floating-point thresholds are 2**(1 + mantissa_bits).
    # For more details, see:
    # https://en.wikipedia.org/wiki/Floating-point_arithmetic#Internal_representation
    x_dtype = x.dtype.base_dtype
    max_event_size = (_largest_integer_by_dtype(x_dtype)
                      if x_dtype.is_floating else 0)
    if max_event_size is 0:
      raise TypeError("Unable to validate size of unrecognized dtype "
                      "({}).".format(x_dtype.name))
    try:
      x_shape_static = x.get_shape().with_rank_at_least(1)
    except ValueError:
      raise ValueError("A categorical-distribution parameter must have "
                       "at least 1 dimension.")
    if x_shape_static[-1].value is not None:
      event_size = x_shape_static[-1].value
      if event_size < 2:
        raise ValueError("A categorical-distribution parameter must have at "
                         "least 2 events.")
      if event_size > max_event_size:
        raise ValueError(
            "Number of classes exceeds `dtype` precision, i.e., "
            "{} implies shape ({}) cannot exceed {}.".format(
                x_dtype.name, event_size, max_event_size))
      return x
    else:
      event_size = array_ops.shape(x, name="x_shape")[-1]
      return control_flow_ops.with_dependencies([
          check_ops.assert_rank_at_least(
              x, 1, message=("A categorical-distribution parameter must have "
                             "at least 1 dimension.")),
          check_ops.assert_greater_equal(
              array_ops.shape(x)[-1], 2,
              message=("A categorical-distribution parameter must have at "
                       "least 2 events.")),
          check_ops.assert_less_equal(
              event_size, max_event_size,
              message="Number of classes exceeds `dtype` precision, "
                      "i.e., {} dtype cannot exceed {} shape.".format(
                          x_dtype.name, max_event_size)),
      ], x)
Esempio n. 46
0
 def test_rank_one_ten_doesnt_raise_raise_if_rank_too_large_static_rank(self):
   tensor = constant_op.constant([1, 2], name="my_tensor")
   desired_rank = 0
   with ops.control_dependencies(
       [check_ops.assert_rank_at_least(tensor, desired_rank)]):
     self.evaluate(array_ops.identity(tensor))