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")
def _parameter_control_dependencies(self, is_init): if not self.validate_args: return [] assertions = [] if is_init != tensor_util.is_ref(self.concentration): assertions.append( assert_util.assert_positive( self.concentration, message='`concentration` must be positive.')) if is_init != tensor_util.is_ref(self.scale): assertions.append( assert_util.assert_positive( self.scale, message='`scale` must be positive.')) return assertions
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
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
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.') ]
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]
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.') ]
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.") ]
def _parameter_control_dependencies(self, is_init): if not self.validate_args: return [] assertions = [] if is_init != tensor_util.is_ref(self._df): assertions.append( assert_util.assert_positive( self._df, message='Argument `df` must be positive.')) return assertions
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`.") ]
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
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
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`'), ]
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)
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): 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
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
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
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
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
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 _maybe_assert_valid_sample(self, x): if not self.validate_args: return [] return [ assert_util.assert_positive(x, message='Sample must be positive.') ]
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)
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
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