def _maybe_assert_valid_sample(self, x): tf.assert_same_float_dtype(tensors=[x], dtype=self.dtype) if not self.validate_args: return x return control_flow_ops.with_dependencies([ tf.assert_positive(x), ], x)
def __init__(self, loc=0., scale=1., validate_args=False, name="gumbel"): """Instantiates the `Gumbel` bijector. Args: loc: Float-like `Tensor` that is the same dtype and is broadcastable with `scale`. This is `loc` in `Y = g(X) = exp(-exp(-(X - loc) / scale))`. scale: Positive Float-like `Tensor` that is the same dtype and is broadcastable with `loc`. This is `scale` in `Y = g(X) = exp(-exp(-(X - loc) / scale))`. validate_args: Python `bool` indicating whether arguments should be checked for correctness. name: Python `str` name given to ops managed by this object. """ self._graph_parents = [] self._name = name self._validate_args = validate_args with self._name_scope("init", values=[loc, scale]): self._loc = tf.convert_to_tensor(loc, name="loc") self._scale = tf.convert_to_tensor(scale, name="scale") tf.assert_same_float_dtype([self._loc, self._scale]) if validate_args: self._scale = control_flow_ops.with_dependencies([ tf.assert_positive( self._scale, message="Argument scale was not positive") ], self._scale) super(Gumbel, self).__init__( validate_args=validate_args, forward_min_event_ndims=0, name=name)
def __init__(self, amplitude=None, length_scale=None, feature_ndims=1, validate_args=False, name="ExponentiatedQuadratic"): """Construct an ExponentiatedQuadratic kernel instance. Args: amplitude: floating point `Tensor` that controls the maximum value of the kernel. Must be broadcastable with `length_scale` and inputs to `apply` and `matrix` methods. Must be greater than zero. length_scale: floating point `Tensor` that controls how sharp or wide the kernel shape is. This provides a characteristic "unit" of length against which `||x - y||` can be compared for scale. Must be broadcastable with `amplitude` and inputs to `apply` and `matrix` methods. feature_ndims: Python `int` number of rightmost dims to include in the squared difference norm in the exponential. validate_args: If `True`, parameters are checked for validity despite possibly degrading runtime performance name: Python `str` name prefixed to Ops created by this class. """ with tf.name_scope(name, values=[amplitude, length_scale]) as name: self._amplitude = _validate_arg_if_not_none( amplitude, tf.assert_positive, validate_args) self._length_scale = _validate_arg_if_not_none( length_scale, tf.assert_positive, validate_args) tf.assert_same_float_dtype([self._amplitude, self._length_scale]) super(ExponentiatedQuadratic, self).__init__(feature_ndims, name)
def __init__(self, df, loc, scale, validate_args=False, allow_nan_stats=True, name="StudentT"): """Construct Student's t distributions. The distributions have degree of freedom `df`, mean `loc`, and scale `scale`. The parameters `df`, `loc`, and `scale` must be shaped in a way that supports broadcasting (e.g. `df + loc + scale` is a valid operation). Args: df: Floating-point `Tensor`. The degrees of freedom of the distribution(s). `df` must contain only positive values. loc: Floating-point `Tensor`. The mean(s) of the distribution(s). scale: Floating-point `Tensor`. The scaling factor(s) for the distribution(s). Note that `scale` is not technically the standard deviation of this distribution but has semantics more similar to standard deviation than variance. 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: TypeError: if loc and scale are different dtypes. """ parameters = dict(locals()) with tf.name_scope(name, values=[df, loc, scale]) as name: dtype = dtype_util.common_dtype([df, loc, scale], tf.float32) df = tf.convert_to_tensor(df, name="df", dtype=dtype) loc = tf.convert_to_tensor(loc, name="loc", dtype=dtype) scale = tf.convert_to_tensor(scale, name="scale", dtype=dtype) with tf.control_dependencies([tf.assert_positive(df)] if validate_args else []): self._df = tf.identity(df) self._loc = tf.identity(loc) self._scale = tf.identity(scale) tf.assert_same_float_dtype( (self._df, self._loc, self._scale)) super(StudentT, self).__init__( dtype=self._scale.dtype, reparameterization_type=reparameterization.FULLY_REPARAMETERIZED, validate_args=validate_args, allow_nan_stats=allow_nan_stats, parameters=parameters, graph_parents=[self._df, self._loc, self._scale], name=name)
def __init__(self, concentration, rate, validate_args=False, allow_nan_stats=True, name="InverseGamma"): """Construct InverseGamma with `concentration` and `rate` parameters. The parameters `concentration` and `rate` must be shaped in a way that supports broadcasting (e.g. `concentration + rate` is a valid operation). Args: concentration: Floating point tensor, the concentration params of the distribution(s). Must contain only positive values. rate: Floating point tensor, the inverse scale params of the distribution(s). Must contain only positive values. 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: TypeError: if `concentration` and `rate` are different dtypes. """ parameters = dict(locals()) with tf.name_scope(name, values=[concentration, rate]) as name: dtype = dtype_util.common_dtype([concentration, rate], preferred_dtype=tf.float32) concentration = tf.convert_to_tensor( concentration, name="concentration", dtype=dtype) rate = tf.convert_to_tensor(rate, name="rate", dtype=dtype) with tf.control_dependencies([ tf.assert_positive( concentration, message="Concentration must be positive."), tf.assert_positive( rate, message="Rate must be positive."), ] if validate_args else []): self._concentration = tf.identity(concentration, name="concentration") self._rate = tf.identity(rate, name="rate") tf.assert_same_float_dtype([self._concentration, self._rate]) super(InverseGamma, self).__init__( dtype=self._concentration.dtype, validate_args=validate_args, allow_nan_stats=allow_nan_stats, reparameterization_type=reparameterization.FULLY_REPARAMETERIZED, parameters=parameters, graph_parents=[self._concentration, self._rate], name=name)
def __init__(self, loc, scale, validate_args=False, allow_nan_stats=True, name="Gumbel"): """Construct Gumbel distributions with location and scale `loc` and `scale`. The parameters `loc` and `scale` must be shaped in a way that supports broadcasting (e.g. `loc + scale` is a valid operation). Args: loc: Floating point tensor, the means of the distribution(s). scale: Floating point tensor, the scales of the distribution(s). scale must contain only positive values. 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. Default value: `False`. 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. Default value: `True`. name: Python `str` name prefixed to Ops created by this class. Default value: `'Gumbel'`. Raises: TypeError: if loc and scale are different dtypes. """ with tf.name_scope(name, values=[loc, scale]) as name: dtype = dtype_util.common_dtype([loc, scale], preferred_dtype=tf.float32) loc = tf.convert_to_tensor(loc, name="loc", dtype=dtype) scale = tf.convert_to_tensor(scale, name="scale", dtype=dtype) with tf.control_dependencies( [tf.assert_positive(scale)] if validate_args else []): loc = tf.identity(loc, name="loc") scale = tf.identity(scale, name="scale") tf.assert_same_float_dtype([loc, scale]) self._gumbel_bijector = gumbel_bijector.Gumbel( loc=loc, scale=scale, validate_args=validate_args) super(Gumbel, self).__init__( distribution=uniform.Uniform(low=tf.zeros([], dtype=loc.dtype), high=tf.ones([], dtype=loc.dtype), allow_nan_stats=allow_nan_stats), # The Gumbel bijector encodes the quantile # function as the forward, and hence needs to # be inverted. bijector=invert_bijector.Invert(self._gumbel_bijector), batch_shape=distribution_util.get_broadcast_shape(loc, scale), name=name)
def __init__(self, loc, scale, validate_args=False, allow_nan_stats=True, name="Gumbel"): """Construct Gumbel distributions with location and scale `loc` and `scale`. The parameters `loc` and `scale` must be shaped in a way that supports broadcasting (e.g. `loc + scale` is a valid operation). Args: loc: Floating point tensor, the means of the distribution(s). scale: Floating point tensor, the scales of the distribution(s). scale must contain only positive values. 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. Default value: `False`. 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. Default value: `True`. name: Python `str` name prefixed to Ops created by this class. Default value: `'Gumbel'`. Raises: TypeError: if loc and scale are different dtypes. """ with tf.name_scope(name, values=[loc, scale]) as name: dtype = dtype_util.common_dtype([loc, scale], preferred_dtype=tf.float32) loc = tf.convert_to_tensor(loc, name="loc", dtype=dtype) scale = tf.convert_to_tensor(scale, name="scale", dtype=dtype) with tf.control_dependencies([tf.assert_positive(scale)] if validate_args else []): loc = tf.identity(loc, name="loc") scale = tf.identity(scale, name="scale") tf.assert_same_float_dtype([loc, scale]) self._gumbel_bijector = gumbel_bijector.Gumbel( loc=loc, scale=scale, validate_args=validate_args) super(Gumbel, self).__init__( distribution=uniform.Uniform( low=tf.zeros([], dtype=loc.dtype), high=tf.ones([], dtype=loc.dtype), allow_nan_stats=allow_nan_stats), # The Gumbel bijector encodes the quantile # function as the forward, and hence needs to # be inverted. bijector=invert_bijector.Invert(self._gumbel_bijector), batch_shape=distribution_util.get_broadcast_shape(loc, scale), name=name)
def __init__(self, loc, scale, rate, validate_args=False, allow_nan_stats=True, name="ExponentiallyModifiedNormal"): """Construct ExponentiallyModifiedNormal distributions. The parameters `loc`, `scale`, and `rate` must be shaped in a way that supports broadcasting (e.g. `loc + scale + rate` is a valid operation). Args: loc: Floating point tensor; the means of the normal component of the distribution(s). scale: Floating point tensor; the stddevs of the normal component of the distribution(s). Must contain only positive values. rate: Floating point tensor; the rate of the exponential component of the distribution(s). Must contain only positive values. 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: TypeError: if `loc`, `scale`, and `rate` have different `dtype`. """ parameters = dict(locals()) with tf.name_scope(name, values=[loc, scale, rate]) as name: dtype = dtype_util.common_dtype([loc, scale, rate], tf.float32) loc = tf.convert_to_tensor(loc, name="loc", dtype=dtype) scale = tf.convert_to_tensor(scale, name="scale", dtype=dtype) rate = tf.convert_to_tensor(rate, name="rate", dtype=dtype) with tf.control_dependencies([ tf.assert_positive(scale), tf.assert_positive(rate) ] if validate_args else []): self._loc = tf.identity(loc) self._scale = tf.identity(scale) self._rate = tf.identity(rate) tf.assert_same_float_dtype([self._loc, self._scale, self._rate]) super(ExponentiallyModifiedNormal, self).__init__( dtype=dtype, reparameterization_type=reparameterization.FULLY_REPARAMETERIZED, validate_args=validate_args, allow_nan_stats=allow_nan_stats, parameters=parameters, graph_parents=[self._loc, self._scale, self._rate], name=name)
def __init__(self, loc=0.0, scale=1.1, minval=-2., maxval=2., validate_args=False, allow_nan_stats=True, name="TruncatedNormal"): """Construct Truncated Normal distributions with mean `loc`, stddev `scale`, within the interval (`lower_bound`, `upper_bound`). Args: loc: Floating point tensor; the means of the distribution(s). scale: Floating point tensor; the stddevs of the distribution(s). Must contain only positive values. minval: Floating point tensor; the lower bounds of the range for the distribution(s). maxval: Floating point tensor; the upper bounds of the range for the distribution(s). 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. """ parameters = locals() with tf.name_scope(name, values=[loc, scale, minval, maxval]): with tf.control_dependencies([tf.assert_positive(scale)] if validate_args else []): self._loc = loc self._scale = scale self._minval = minval self._maxval = maxval tf.assert_same_float_dtype([self._loc, self._scale, self._minval, self._maxval]) super(distributions_TruncatedNormal, self).__init__( dtype=self._scale.dtype, reparameterization_type=tf.contrib.distributions.NOT_REPARAMETERIZED, validate_args=validate_args, allow_nan_stats=allow_nan_stats, parameters=parameters, graph_parents=[self._loc, self._scale, self._minval, self._maxval], name=name)
def __init__(self, loc, concentration, validate_args=False, allow_nan_stats=True, name="VonMises"): """Construct von Mises distributions with given location and concentration. The parameters `loc` and `concentration` must be shaped in a way that supports broadcasting (e.g. `loc + concentration` is a valid operation). Args: loc: Floating point tensor, the circular means of the distribution(s). concentration: Floating point tensor, the level of concentration of the distribution(s) around `loc`. Must take non-negative values. `concentration = 0` defines a Uniform distribution, while `concentration = +inf` indicates a Deterministic distribution at `loc`. 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: TypeError: if loc and concentration are different dtypes. """ parameters = dict(locals()) with tf.name_scope(name, values=[loc, concentration]) as name: dtype = dtype_util.common_dtype([loc, concentration], preferred_dtype=tf.float32) loc = tf.convert_to_tensor(loc, name="loc", dtype=dtype) concentration = tf.convert_to_tensor(concentration, name="concentration", dtype=dtype) with tf.control_dependencies( [tf.assert_non_negative(concentration )] if validate_args else []): self._loc = tf.identity(loc, name="loc") self._concentration = tf.identity(concentration, name="concentration") tf.assert_same_float_dtype([self._loc, self._concentration]) super(VonMises, self).__init__( dtype=self._concentration.dtype, reparameterization_type=reparameterization.FULLY_REPARAMETERIZED, validate_args=validate_args, allow_nan_stats=allow_nan_stats, parameters=parameters, graph_parents=[self._loc, self._concentration], name=name)
def __init__(self, concentration1=None, concentration0=None, validate_args=False, allow_nan_stats=True, name="Beta"): """Initialize a batch of Beta distributions. Args: concentration1: Positive floating-point `Tensor` indicating mean number of successes; aka "alpha". Implies `self.dtype` and `self.batch_shape`, i.e., `concentration1.shape = [N1, N2, ..., Nm] = self.batch_shape`. concentration0: Positive floating-point `Tensor` indicating mean number of failures; aka "beta". Otherwise has same semantics as `concentration1`. 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. """ parameters = dict(locals()) with tf.name_scope(name, values=[concentration1, concentration0]) as name: dtype = dtype_util.common_dtype([concentration1, concentration0], tf.float32) self._concentration1 = self._maybe_assert_valid_concentration( tf.convert_to_tensor(concentration1, name="concentration1", dtype=dtype), validate_args) self._concentration0 = self._maybe_assert_valid_concentration( tf.convert_to_tensor(concentration0, name="concentration0", dtype=dtype), validate_args) tf.assert_same_float_dtype( [self._concentration1, self._concentration0]) self._total_concentration = self._concentration1 + self._concentration0 super(Beta, self).__init__( dtype=dtype, validate_args=validate_args, allow_nan_stats=allow_nan_stats, reparameterization_type=reparameterization.FULLY_REPARAMETERIZED, parameters=parameters, graph_parents=[ self._concentration1, self._concentration0, self._total_concentration ], name=name)
def __init__(self, df, loc, scale, validate_args=False, allow_nan_stats=True, name="StudentT"): """Construct Student's t distributions. The distributions have degree of freedom `df`, mean `loc`, and scale `scale`. The parameters `df`, `loc`, and `scale` must be shaped in a way that supports broadcasting (e.g. `df + loc + scale` is a valid operation). Args: df: Floating-point `Tensor`. The degrees of freedom of the distribution(s). `df` must contain only positive values. loc: Floating-point `Tensor`. The mean(s) of the distribution(s). scale: Floating-point `Tensor`. The scaling factor(s) for the distribution(s). Note that `scale` is not technically the standard deviation of this distribution but has semantics more similar to standard deviation than variance. 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: TypeError: if loc and scale are different dtypes. """ parameters = dict(locals()) with tf.name_scope(name, values=[df, loc, scale]) as name: with tf.control_dependencies( [tf.assert_positive(df)] if validate_args else []): self._df = tf.identity(df, name="df") self._loc = tf.identity(loc, name="loc") self._scale = tf.identity(scale, name="scale") tf.assert_same_float_dtype((self._df, self._loc, self._scale)) super(StudentT, self).__init__( dtype=self._scale.dtype, reparameterization_type=reparameterization.FULLY_REPARAMETERIZED, validate_args=validate_args, allow_nan_stats=allow_nan_stats, parameters=parameters, graph_parents=[self._df, self._loc, self._scale], name=name)
def __init__(self, concentration1=None, concentration0=None, validate_args=False, allow_nan_stats=True, name="Beta"): """Initialize a batch of Beta distributions. Args: concentration1: Positive floating-point `Tensor` indicating mean number of successes; aka "alpha". Implies `self.dtype` and `self.batch_shape`, i.e., `concentration1.shape = [N1, N2, ..., Nm] = self.batch_shape`. concentration0: Positive floating-point `Tensor` indicating mean number of failures; aka "beta". Otherwise has same semantics as `concentration1`. 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. """ parameters = dict(locals()) with tf.name_scope(name, values=[concentration1, concentration0]) as name: dtype = dtype_util.common_dtype([concentration1, concentration0], tf.float32) self._concentration1 = self._maybe_assert_valid_concentration( tf.convert_to_tensor( concentration1, name="concentration1", dtype=dtype), validate_args) self._concentration0 = self._maybe_assert_valid_concentration( tf.convert_to_tensor( concentration0, name="concentration0", dtype=dtype), validate_args) tf.assert_same_float_dtype([self._concentration1, self._concentration0]) self._total_concentration = self._concentration1 + self._concentration0 super(Beta, self).__init__( dtype=dtype, validate_args=validate_args, allow_nan_stats=allow_nan_stats, reparameterization_type=reparameterization.FULLY_REPARAMETERIZED, parameters=parameters, graph_parents=[ self._concentration1, self._concentration0, self._total_concentration ], name=name)
def __init__(self, concentration, rate, validate_args=False, allow_nan_stats=True, name="Gamma"): """Construct Gamma with `concentration` and `rate` parameters. The parameters `concentration` and `rate` must be shaped in a way that supports broadcasting (e.g. `concentration + rate` is a valid operation). Args: concentration: Floating point tensor, the concentration params of the distribution(s). Must contain only positive values. rate: Floating point tensor, the inverse scale params of the distribution(s). Must contain only positive values. 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: TypeError: if `concentration` and `rate` are different dtypes. """ parameters = dict(locals()) with tf.name_scope(name, values=[concentration, rate]) as name: dtype = dtype_util.common_dtype([concentration, rate], tf.float32) concentration = tf.convert_to_tensor(concentration, name="concentration", dtype=dtype) rate = tf.convert_to_tensor(rate, name="rate", dtype=dtype) with tf.control_dependencies([ tf.assert_positive(concentration), tf.assert_positive(rate), ] if validate_args else []): self._concentration = tf.identity(concentration) self._rate = tf.identity(rate) tf.assert_same_float_dtype([self._concentration, self._rate]) super(Gamma, self).__init__( dtype=dtype, validate_args=validate_args, allow_nan_stats=allow_nan_stats, reparameterization_type=reparameterization.FULLY_REPARAMETERIZED, parameters=parameters, graph_parents=[self._concentration, self._rate], name=name)
def __init__(self, amplitude=None, length_scale=None, period=None, feature_ndims=1, validate_args=False, name='ExpSinSquared'): """Construct a ExpSinSquared kernel instance. Args: amplitude: Positive floating point `Tensor` that controls the maximum value of the kernel. Must be broadcastable with `period`, `length_scale` and inputs to `apply` and `matrix` methods. A value of `None` is treated like 1. length_scale: Positive floating point `Tensor` that controls how sharp or wide the kernel shape is. This provides a characteristic "unit" of length against which `|x - y|` can be compared for scale. Must be broadcastable with `amplitude`, `period` and inputs to `apply` and `matrix` methods. A value of `None` is treated like 1. period: Positive floating point `Tensor` that controls the period of the kernel. Must be broadcastable with `amplitude`, `length_scale` and inputs to `apply` and `matrix` methods. A value of `None` is treated like 1. feature_ndims: Python `int` number of rightmost dims to include in kernel computation. validate_args: If `True`, parameters are checked for validity despite possibly degrading runtime performance name: Python `str` name prefixed to Ops created by this class. """ with tf.name_scope(name, values=[amplitude, period, length_scale]) as name: dtype = dtype_util.common_dtype([amplitude, period, length_scale], tf.float32) if amplitude is not None: amplitude = tf.convert_to_tensor( amplitude, name='amplitude', dtype=dtype) self._amplitude = _validate_arg_if_not_none( amplitude, tf.assert_positive, validate_args) if period is not None: period = tf.convert_to_tensor(period, name='period', dtype=dtype) self._period = _validate_arg_if_not_none( period, tf.assert_positive, validate_args) if length_scale is not None: length_scale = tf.convert_to_tensor( length_scale, name='length_scale', dtype=dtype) self._length_scale = _validate_arg_if_not_none( length_scale, tf.assert_positive, validate_args) tf.assert_same_float_dtype( [self._amplitude, self._length_scale, self._period]) super(ExpSinSquared, self).__init__(feature_ndims, dtype=dtype, name=name)
def __init__(self, low=0., high=1., validate_args=False, allow_nan_stats=True, name="Uniform"): """Initialize a batch of Uniform distributions. Args: low: Floating point tensor, lower boundary of the output interval. Must have `low < high`. high: Floating point tensor, upper boundary of the output interval. Must have `low < high`. 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: InvalidArgumentError: if `low >= high` and `validate_args=False`. """ parameters = dict(locals()) with tf.name_scope(name, values=[low, high]) as name: dtype = dtype_util.common_dtype([low, high], tf.float32) low = tf.convert_to_tensor(low, name="low", dtype=dtype) high = tf.convert_to_tensor(high, name="high", dtype=dtype) with tf.control_dependencies([ tf.assert_less( low, high, message="uniform not defined when low >= high.") ] if validate_args else []): self._low = tf.identity(low) self._high = tf.identity(high) tf.assert_same_float_dtype([self._low, self._high]) super(Uniform, self).__init__( dtype=self._low.dtype, reparameterization_type=reparameterization.FULLY_REPARAMETERIZED, validate_args=validate_args, allow_nan_stats=allow_nan_stats, parameters=parameters, graph_parents=[self._low, self._high], name=name)
def __init__(self, loc, scale, validate_args=False, allow_nan_stats=True, name="Laplace"): """Construct Laplace distribution with parameters `loc` and `scale`. The parameters `loc` and `scale` must be shaped in a way that supports broadcasting (e.g., `loc / scale` is a valid operation). Args: loc: Floating point tensor which characterizes the location (center) of the distribution. scale: Positive floating point tensor which characterizes the spread of the distribution. 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: TypeError: if `loc` and `scale` are of different dtype. """ parameters = dict(locals()) with tf.name_scope(name, values=[loc, scale]) as name: dtype = dtype_util.common_dtype([loc, scale], tf.float32) loc = tf.convert_to_tensor(loc, name="loc", dtype=dtype) scale = tf.convert_to_tensor(scale, name="scale", dtype=dtype) with tf.control_dependencies( [tf.assert_positive(scale)] if validate_args else []): self._loc = tf.identity(loc) self._scale = tf.identity(scale) tf.assert_same_float_dtype([self._loc, self._scale]) super(Laplace, self).__init__(dtype=dtype, reparameterization_type=reparameterization. FULLY_REPARAMETERIZED, validate_args=validate_args, allow_nan_stats=allow_nan_stats, parameters=parameters, graph_parents=[self._loc, self._scale], name=name)
def __init__(self, loc, concentration, validate_args=False, allow_nan_stats=True, name="InverseGaussian"): """Constructs inverse Gaussian distribution with `loc` and `concentration`. Args: loc: Floating-point `Tensor`, the loc params. Must contain only positive values. concentration: Floating-point `Tensor`, the concentration params. Must contain only positive values. 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. Default value: `False` (i.e. do not validate args). 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. Default value: `True`. name: Python `str` name prefixed to Ops created by this class. Default value: 'InverseGaussian'. """ parameters = dict(locals()) with tf.name_scope(name, values=[loc, concentration]): dtype = dtype_util.common_dtype([loc, concentration], tf.float32) loc = tf.convert_to_tensor(loc, name="loc", dtype=dtype) concentration = tf.convert_to_tensor(concentration, name="concentration", dtype=dtype) with tf.control_dependencies( [tf.assert_positive(loc), tf.assert_positive(concentration)] if validate_args else []): self._loc = tf.identity(loc, name="loc") self._concentration = tf.identity(concentration, name="concentration") tf.assert_same_float_dtype([self._loc, self._concentration]) super(InverseGaussian, self).__init__( dtype=self._loc.dtype, reparameterization_type=reparameterization.NOT_REPARAMETERIZED, validate_args=validate_args, allow_nan_stats=allow_nan_stats, parameters=parameters, graph_parents=[self._loc, self._concentration], name=name)
def __init__(self, loc, scale, validate_args=False, allow_nan_stats=True, name="Laplace"): """Construct Laplace distribution with parameters `loc` and `scale`. The parameters `loc` and `scale` must be shaped in a way that supports broadcasting (e.g., `loc / scale` is a valid operation). Args: loc: Floating point tensor which characterizes the location (center) of the distribution. scale: Positive floating point tensor which characterizes the spread of the distribution. 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: TypeError: if `loc` and `scale` are of different dtype. """ parameters = dict(locals()) with tf.name_scope(name, values=[loc, scale]) as name: dtype = dtype_util.common_dtype([loc, scale], tf.float32) loc = tf.convert_to_tensor(loc, name="loc", dtype=dtype) scale = tf.convert_to_tensor(scale, name="scale", dtype=dtype) with tf.control_dependencies([tf.assert_positive(scale)] if validate_args else []): self._loc = tf.identity(loc) self._scale = tf.identity(scale) tf.assert_same_float_dtype([self._loc, self._scale]) super(Laplace, self).__init__( dtype=dtype, reparameterization_type=reparameterization.FULLY_REPARAMETERIZED, validate_args=validate_args, allow_nan_stats=allow_nan_stats, parameters=parameters, graph_parents=[self._loc, self._scale], name=name)
def __init__(self, loc, scale, validate_args=False, allow_nan_stats=True, name="HalfCauchy"): """Construct a half-Cauchy distribution with `loc` and `scale`. Args: loc: Floating-point `Tensor`; the location(s) of the distribution(s). scale: Floating-point `Tensor`; the scale(s) of the distribution(s). Must contain only positive values. 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. Default value: `False` (i.e. do not validate args). 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. Default value: `True`. name: Python `str` name prefixed to Ops created by this class. Default value: 'HalfCauchy'. Raises: TypeError: if `loc` and `scale` have different `dtype`. """ parameters = dict(locals()) with tf.name_scope(name, values=[loc, scale]) as name: dtype = dtype_util.common_dtype([loc, scale], preferred_dtype=tf.float32) loc = tf.convert_to_tensor(loc, name="loc", dtype=dtype) scale = tf.convert_to_tensor(scale, name="scale", dtype=dtype) with tf.control_dependencies( [tf.assert_positive(scale)] if validate_args else []): self._loc = tf.identity(loc, name="loc") self._scale = tf.identity(scale, name="loc") tf.assert_same_float_dtype([self._loc, self._scale]) super(HalfCauchy, self).__init__( dtype=self._scale.dtype, reparameterization_type=reparameterization.FULLY_REPARAMETERIZED, validate_args=validate_args, allow_nan_stats=allow_nan_stats, parameters=parameters, graph_parents=[self._loc, self._scale], name=name)
def __init__(self, loc, scale, validate_args=False, allow_nan_stats=True, name="Logistic"): """Construct Logistic distributions with mean and scale `loc` and `scale`. The parameters `loc` and `scale` must be shaped in a way that supports broadcasting (e.g. `loc + scale` is a valid operation). Args: loc: Floating point tensor, the means of the distribution(s). scale: Floating point tensor, the scales of the distribution(s). Must contain only positive values. 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: The name to give Ops created by the initializer. Raises: TypeError: if loc and scale are different dtypes. """ parameters = dict(locals()) with tf.name_scope(name, values=[loc, scale]) as name: with tf.control_dependencies( [tf.assert_positive(scale)] if validate_args else []): dtype = dtype_util.common_dtype([loc, scale], tf.float32) self._loc = tf.convert_to_tensor(loc, name="loc", dtype=dtype) self._scale = tf.convert_to_tensor(scale, name="scale", dtype=dtype) tf.assert_same_float_dtype([self._loc, self._scale]) super(Logistic, self).__init__( dtype=self._scale.dtype, reparameterization_type=reparameterization.FULLY_REPARAMETERIZED, validate_args=validate_args, allow_nan_stats=allow_nan_stats, parameters=parameters, graph_parents=[self._loc, self._scale], name=name)
def __init__(self, loc, scale, validate_args=False, allow_nan_stats=True, name="HalfCauchy"): """Construct a half-Cauchy distribution with `loc` and `scale`. Args: loc: Floating-point `Tensor`; the location(s) of the distribution(s). scale: Floating-point `Tensor`; the scale(s) of the distribution(s). Must contain only positive values. 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. Default value: `False` (i.e. do not validate args). 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. Default value: `True`. name: Python `str` name prefixed to Ops created by this class. Default value: 'HalfCauchy'. Raises: TypeError: if `loc` and `scale` have different `dtype`. """ parameters = dict(locals()) with tf.name_scope(name, values=[loc, scale]) as name: dtype = dtype_util.common_dtype([loc, scale], preferred_dtype=tf.float32) loc = tf.convert_to_tensor(loc, name="loc", dtype=dtype) scale = tf.convert_to_tensor(scale, name="scale", dtype=dtype) with tf.control_dependencies([tf.assert_positive(scale)] if validate_args else []): self._loc = tf.identity(loc, name="loc") self._scale = tf.identity(scale, name="loc") tf.assert_same_float_dtype([self._loc, self._scale]) super(HalfCauchy, self).__init__( dtype=self._scale.dtype, reparameterization_type=reparameterization.FULLY_REPARAMETERIZED, validate_args=validate_args, allow_nan_stats=allow_nan_stats, parameters=parameters, graph_parents=[self._loc, self._scale], name=name)
def __init__(self, loc, scale, validate_args=False, allow_nan_stats=True, name="Cauchy"): """Construct Cauchy distributions. The parameters `loc` and `scale` must be shaped in a way that supports broadcasting (e.g. `loc + scale` is a valid operation). Args: loc: Floating point tensor; the modes of the distribution(s). scale: Floating point tensor; the locations of the distribution(s). Must contain only positive values. 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: TypeError: if `loc` and `scale` have different `dtype`. """ parameters = dict(locals()) with tf.name_scope(name, values=[loc, scale]) as name: with tf.control_dependencies([tf.assert_positive(scale)] if validate_args else []): self._loc = tf.identity(loc, name="loc") self._scale = tf.identity(scale, name="scale") tf.assert_same_float_dtype([self._loc, self._scale]) super(Cauchy, self).__init__( dtype=self._scale.dtype, reparameterization_type=tf.distributions.FULLY_REPARAMETERIZED, validate_args=validate_args, allow_nan_stats=allow_nan_stats, parameters=parameters, graph_parents=[self._loc, self._scale], name=name)
def __init__(self, amplitude=None, length_scale=None, period=None, feature_ndims=1, validate_args=False, name="ExpSinSquared"): """Construct a ExpSinSquared kernel instance. Args: amplitude: Positive floating point `Tensor` that controls the maximum value of the kernel. Must be broadcastable with `period`, `length_scale` and inputs to `apply` and `matrix` methods. A value of `None` is treated like 1. length_scale: Positive floating point `Tensor` that controls how sharp or wide the kernel shape is. This provides a characteristic "unit" of length against which `|x - y|` can be compared for scale. Must be broadcastable with `amplitude`, `period` and inputs to `apply` and `matrix` methods. A value of `None` is treated like 1. period: Positive floating point `Tensor` that controls the period of the kernel. Must be broadcastable with `amplitude`, `length_scale` and inputs to `apply` and `matrix` methods. A value of `None` is treated like 1. feature_ndims: Python `int` number of rightmost dims to include in kernel computation. validate_args: If `True`, parameters are checked for validity despite possibly degrading runtime performance name: Python `str` name prefixed to Ops created by this class. """ with tf.name_scope(name, values=[amplitude, period, length_scale]) as name: self._amplitude = _validate_arg_if_not_none( amplitude, tf.assert_positive, validate_args) self._period = _validate_arg_if_not_none(period, tf.assert_positive, validate_args) self._length_scale = _validate_arg_if_not_none( length_scale, tf.assert_positive, validate_args) tf.assert_same_float_dtype( [self._amplitude, self._length_scale, self._period]) super(ExpSinSquared, self).__init__(feature_ndims, name)
def __init__(self, amplitude=None, length_scale=None, feature_ndims=1, validate_args=False, name='ExponentiatedQuadratic'): """Construct an ExponentiatedQuadratic kernel instance. Args: amplitude: floating point `Tensor` that controls the maximum value of the kernel. Must be broadcastable with `length_scale` and inputs to `apply` and `matrix` methods. Must be greater than zero. length_scale: floating point `Tensor` that controls how sharp or wide the kernel shape is. This provides a characteristic "unit" of length against which `||x - y||` can be compared for scale. Must be broadcastable with `amplitude` and inputs to `apply` and `matrix` methods. feature_ndims: Python `int` number of rightmost dims to include in the squared difference norm in the exponential. validate_args: If `True`, parameters are checked for validity despite possibly degrading runtime performance name: Python `str` name prefixed to Ops created by this class. """ with tf.name_scope(name, values=[amplitude, length_scale]) as name: dtype = dtype_util.common_dtype([amplitude, length_scale], tf.float32) if amplitude is not None: amplitude = tf.convert_to_tensor(amplitude, name='amplitude', dtype=dtype) self._amplitude = _validate_arg_if_not_none( amplitude, tf.assert_positive, validate_args) if length_scale is not None: length_scale = tf.convert_to_tensor(length_scale, name='length_scale', dtype=dtype) self._length_scale = _validate_arg_if_not_none( length_scale, tf.assert_positive, validate_args) tf.assert_same_float_dtype([self._amplitude, self._length_scale]) super(ExponentiatedQuadratic, self).__init__(feature_ndims, dtype=dtype, name=name)
def __init__(self, scale=1., concentration=1., validate_args=False, name="weibull"): """Instantiates the `Weibull` bijector. Args: scale: Positive Float-type `Tensor` that is the same dtype and is broadcastable with `concentration`. This is `l` in `Y = g(X) = 1 - exp((-x / l) ** k)`. concentration: Positive Float-type `Tensor` that is the same dtype and is broadcastable with `scale`. This is `k` in `Y = g(X) = 1 - exp((-x / l) ** k)`. validate_args: Python `bool` indicating whether arguments should be checked for correctness. name: Python `str` name given to ops managed by this object. """ self._graph_parents = [] self._name = name self._validate_args = validate_args with self._name_scope("init", values=[scale, concentration]): self._scale = tf.convert_to_tensor(scale, name="scale") self._concentration = tf.convert_to_tensor( concentration, name="concentration") tf.assert_same_float_dtype([self._scale, self._concentration]) if validate_args: self._scale = control_flow_ops.with_dependencies([ tf.assert_positive( self._scale, message="Argument scale was not positive") ], self._scale) self._concentration = control_flow_ops.with_dependencies([ tf.assert_positive( self._concentration, message="Argument concentration was not positive") ], self._concentration) super(Weibull, self).__init__( forward_min_event_ndims=0, validate_args=validate_args, name=name)
def __init__(self, scale=1., concentration=1., validate_args=False, name="weibull"): """Instantiates the `Weibull` bijector. Args: scale: Positive Float-type `Tensor` that is the same dtype and is broadcastable with `concentration`. This is `l` in `Y = g(X) = 1 - exp((-x / l) ** k)`. concentration: Positive Float-type `Tensor` that is the same dtype and is broadcastable with `scale`. This is `k` in `Y = g(X) = 1 - exp((-x / l) ** k)`. validate_args: Python `bool` indicating whether arguments should be checked for correctness. name: Python `str` name given to ops managed by this object. """ self._graph_parents = [] self._name = name self._validate_args = validate_args with self._name_scope("init", values=[scale, concentration]): self._scale = tf.convert_to_tensor(scale, name="scale") self._concentration = tf.convert_to_tensor(concentration, name="concentration") tf.assert_same_float_dtype([self._scale, self._concentration]) if validate_args: self._scale = control_flow_ops.with_dependencies([ tf.assert_positive( self._scale, message="Argument scale was not positive") ], self._scale) self._concentration = control_flow_ops.with_dependencies([ tf.assert_positive( self._concentration, message="Argument concentration was not positive") ], self._concentration) super(Weibull, self).__init__(forward_min_event_ndims=0, validate_args=validate_args, name=name)
def _init_params(self, amplitude, length_scale, validate_args): """Shared init logic for `amplitude` and `length_scale` params. Args: amplitude: `Tensor` (or convertible) or `None` to convert, validate. length_scale: `Tensor` (or convertible) or `None` to convert, validate. validate_args: If `True`, parameters are checked for validity despite possibly degrading runtime performance Returns: dtype: The common `DType` of the parameters. """ dtype = dtype_util.common_dtype([amplitude, length_scale], tf.float32) if amplitude is not None: amplitude = tf.convert_to_tensor(amplitude, name='amplitude', dtype=dtype) self._amplitude = _validate_arg_if_not_none(amplitude, tf.assert_positive, validate_args) if length_scale is not None: length_scale = tf.convert_to_tensor( length_scale, name='length_scale', dtype=dtype) self._length_scale = _validate_arg_if_not_none( length_scale, tf.assert_positive, validate_args) tf.assert_same_float_dtype([self.amplitude, self.length_scale]) return dtype
def __init__(self, skewness=None, tailweight=None, validate_args=False, name="SinhArcsinh"): """Instantiates the `SinhArcsinh` bijector. Args: skewness: Skewness parameter. Float-type `Tensor`. Default is `0` of type `float32`. tailweight: Tailweight parameter. Positive `Tensor` of same `dtype` as `skewness` and broadcastable `shape`. Default is `1` of type `float32`. validate_args: Python `bool` indicating whether arguments should be checked for correctness. name: Python `str` name given to ops managed by this object. """ self._graph_parents = [] self._name = name self._validate_args = validate_args with self._name_scope("init", values=[skewness, tailweight]): tailweight = 1. if tailweight is None else tailweight skewness = 0. if skewness is None else skewness self._skewness = tf.convert_to_tensor(skewness, name="skewness") self._tailweight = tf.convert_to_tensor(tailweight, name="tailweight", dtype=self._skewness.dtype) tf.assert_same_float_dtype([self._skewness, self._tailweight]) if validate_args: self._tailweight = control_flow_ops.with_dependencies([ tf.assert_positive( self._tailweight, message="Argument tailweight was not positive") ], self._tailweight) super(SinhArcsinh, self).__init__(forward_min_event_ndims=0, validate_args=validate_args, name=name)
def __init__(self, skewness=None, tailweight=None, validate_args=False, name="SinhArcsinh"): """Instantiates the `SinhArcsinh` bijector. Args: skewness: Skewness parameter. Float-type `Tensor`. Default is `0` of type `float32`. tailweight: Tailweight parameter. Positive `Tensor` of same `dtype` as `skewness` and broadcastable `shape`. Default is `1` of type `float32`. validate_args: Python `bool` indicating whether arguments should be checked for correctness. name: Python `str` name given to ops managed by this object. """ self._graph_parents = [] self._name = name self._validate_args = validate_args with self._name_scope("init", values=[skewness, tailweight]): tailweight = 1. if tailweight is None else tailweight skewness = 0. if skewness is None else skewness self._skewness = tf.convert_to_tensor(skewness, name="skewness") self._tailweight = tf.convert_to_tensor( tailweight, name="tailweight", dtype=self._skewness.dtype) tf.assert_same_float_dtype([self._skewness, self._tailweight]) if validate_args: self._tailweight = control_flow_ops.with_dependencies([ tf.assert_positive( self._tailweight, message="Argument tailweight was not positive") ], self._tailweight) super(SinhArcsinh, self).__init__( forward_min_event_ndims=0, validate_args=validate_args, name=name)
def factored_joint_mvn(distributions): """Combine MultivariateNormals into a factored joint distribution. Given a list of multivariate normal distributions `dist[i] = Normal(loc[i], scale[i])`, construct the joint distribution given by concatenating independent samples from these distributions. This is multivariate normal with mean vector given by the concatenation of the component mean vectors, and block-diagonal covariance matrix in which the blocks are the component covariances. Note that for computational efficiency, multivariate normals are represented by a 'scale' (factored covariance) linear operator rather than the full covariance matrix. Args: distributions: Python `iterable` of MultivariateNormal distribution instances (e.g., `tfd.MultivariateNormalDiag`, `tfd.MultivariateNormalTriL`, etc.). These must be broadcastable to a consistent batch shape, but may have different event shapes (i.e., defined over spaces of different dimension). Returns: joint_distribution: An instance of `tfd.MultivariateNormalLinearOperator` representing the joint distribution constructed by concatenating an independent sample from each input distributions. """ graph_parents = [ tensor for distribution in distributions for tensor in distribution._graph_parents ] # pylint: disable=protected-access with tf.name_scope('factored_joint_mvn', values=graph_parents): # We explicitly broadcast the `locs` so that we can concatenate them. # We don't have direct numerical access to the `scales`, which are arbitrary # linear operators, but `LinearOperatorBlockDiag` appears to do the right # thing without further intervention. dtype = tf.assert_same_float_dtype(distributions) broadcast_ones = tf.ones(broadcast_batch_shape(distributions), dtype=dtype)[..., tf.newaxis] return MultivariateNormalLinearOperator( loc=tf.concat( [mvn.mean() * broadcast_ones for mvn in distributions], axis=-1), scale=tfl.LinearOperatorBlockDiag( [mvn.scale for mvn in distributions], is_square=True))
def factored_joint_mvn(distributions): """Combine MultivariateNormals into a factored joint distribution. Given a list of multivariate normal distributions `dist[i] = Normal(loc[i], scale[i])`, construct the joint distribution given by concatenating independent samples from these distributions. This is multivariate normal with mean vector given by the concatenation of the component mean vectors, and block-diagonal covariance matrix in which the blocks are the component covariances. Note that for computational efficiency, multivariate normals are represented by a 'scale' (factored covariance) linear operator rather than the full covariance matrix. Args: distributions: Python `iterable` of MultivariateNormal distribution instances (e.g., `tfd.MultivariateNormalDiag`, `tfd.MultivariateNormalTriL`, etc.). These must be broadcastable to a consistent batch shape, but may have different event shapes (i.e., defined over spaces of different dimension). Returns: joint_distribution: An instance of `tfd.MultivariateNormalLinearOperator` representing the joint distribution constructed by concatenating an independent sample from each input distributions. """ graph_parents = [tensor for distribution in distributions for tensor in distribution._graph_parents] # pylint: disable=protected-access with tf.name_scope('factored_joint_mvn', values=graph_parents): # We explicitly broadcast the `locs` so that we can concatenate them. # We don't have direct numerical access to the `scales`, which are arbitrary # linear operators, but `LinearOperatorBlockDiag` appears to do the right # thing without further intervention. dtype = tf.assert_same_float_dtype(distributions) broadcast_ones = tf.ones(broadcast_batch_shape(distributions), dtype=dtype)[..., tf.newaxis] return MultivariateNormalLinearOperator( loc=tf.concat([mvn.mean() * broadcast_ones for mvn in distributions], axis=-1), scale=tfl.LinearOperatorBlockDiag([mvn.scale for mvn in distributions], is_square=True))
def __init__(self, component_ssms, observation_noise_scale=None, initial_state_prior=None, initial_step=0, validate_args=False, allow_nan_stats=True, name=None): """Build a state space model representing the sum of component models. Args: component_ssms: Python `list` containing one or more `tfd.LinearGaussianStateSpaceModel` instances. The components will in general implement different time-series models, with possibly different `latent_size`, but they must have the same `dtype`, event shape (`num_timesteps` and `observation_size`), and their batch shapes must broadcast to a compatible batch shape. observation_noise_scale: Optional scalar `float` `Tensor` indicating the standard deviation of the observation noise. May contain additional batch dimensions, which must broadcast with the batch shape of elements in `component_ssms`. If `observation_noise_scale` is specified for the `AdditiveStateSpaceModel`, the observation noise scales of component models are ignored. If `None`, the observation noise scale is derived by summing the noise variances of the component models, i.e., `observation_noise_scale = sqrt(sum( [ssm.observation_noise_scale**2 for ssm in component_ssms]))`. initial_state_prior: Optional instance of `tfd.MultivariateNormal` representing a prior distribution on the latent state at time `initial_step`. If `None`, defaults to the independent priors from component models, i.e., `[component.initial_state_prior for component in component_ssms]`. Default value: `None`. initial_step: Optional scalar `int` `Tensor` specifying the starting timestep. Default value: 0. validate_args: Python `bool`. Whether to validate input with asserts. If `validate_args` is `False`, and the inputs are invalid, correct behavior is not guaranteed. Default value: `False`. allow_nan_stats: Python `bool`. 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. Default value: `True`. name: Python `str` name prefixed to ops created by this class. Default value: "AdditiveStateSpaceModel". Raises: ValueError: if components have different `num_timesteps`. """ with tf.name_scope(name, 'AdditiveStateSpaceModel', values=[observation_noise_scale, initial_step]) as name: assertions = [] # Check that all components have the same dtype tf.assert_same_float_dtype(component_ssms) # Construct an initial state prior as a block-diagonal combination # of the component state priors. if initial_state_prior is None: initial_state_prior = sts_util.factored_joint_mvn( [ssm.initial_state_prior for ssm in component_ssms]) dtype = initial_state_prior.dtype static_num_timesteps = [ distribution_util.static_value(ssm.num_timesteps) for ssm in component_ssms if distribution_util.static_value(ssm.num_timesteps) is not None ] # If any components have a static value for `num_timesteps`, use that # value for the additive model. (and check that all other static values # match it). if static_num_timesteps: num_timesteps = static_num_timesteps[0] if not all([component_timesteps == num_timesteps for component_timesteps in static_num_timesteps]): raise ValueError('Additive model components must all have the same ' 'number of timesteps ' '(saw: {})'.format(static_num_timesteps)) else: num_timesteps = component_ssms[0].num_timesteps if validate_args and len(static_num_timesteps) != len(component_ssms): assertions += [ tf.assert_equal(num_timesteps, ssm.num_timesteps, message='Additive model components must all have ' 'the same number of timesteps.') for ssm in component_ssms] # Define the transition and observation models for the additive SSM. # See the "mathematical details" section of the class docstring for # further information. Note that we define these as callables to # handle the fully general case in which some components have time- # varying dynamics. def transition_matrix_fn(t): return tfl.LinearOperatorBlockDiag( [ssm.get_transition_matrix_for_timestep(t) for ssm in component_ssms]) def transition_noise_fn(t): return sts_util.factored_joint_mvn( [ssm.get_transition_noise_for_timestep(t) for ssm in component_ssms]) # Build the observation matrix, concatenating (broadcast) observation # matrices from components. We also take this as an opportunity to enforce # any dynamic assertions we may have generated above. broadcast_batch_shape = tf.convert_to_tensor( sts_util.broadcast_batch_shape(component_ssms), dtype=tf.int32) broadcast_obs_matrix = tf.ones( tf.concat([broadcast_batch_shape, [1, 1]], axis=0), dtype=dtype) if assertions: with tf.control_dependencies(assertions): broadcast_obs_matrix = tf.identity(broadcast_obs_matrix) def observation_matrix_fn(t): return tfl.LinearOperatorFullMatrix( tf.concat([ssm.get_observation_matrix_for_timestep(t).to_dense() * broadcast_obs_matrix for ssm in component_ssms], axis=-1)) if observation_noise_scale is not None: observation_noise_scale = tf.convert_to_tensor( observation_noise_scale, name='observation_noise_scale', dtype=dtype) def observation_noise_fn(t): return tfd.MultivariateNormalDiag( loc=sum([ssm.get_observation_noise_for_timestep(t).mean() for ssm in component_ssms]), scale_diag=observation_noise_scale[..., tf.newaxis]) else: def observation_noise_fn(t): return sts_util.sum_mvns( [ssm.get_observation_noise_for_timestep(t) for ssm in component_ssms]) super(AdditiveStateSpaceModel, self).__init__( num_timesteps=num_timesteps, transition_matrix=transition_matrix_fn, transition_noise=transition_noise_fn, observation_matrix=observation_matrix_fn, observation_noise=observation_noise_fn, initial_state_prior=initial_state_prior, initial_step=initial_step, validate_args=validate_args, allow_nan_stats=allow_nan_stats, name=name)
def __init__(self, design_matrix, weights_prior=None, name=None): """Build a state space model implementing linear regression. Note: the statistical behavior of the regression is determined by the broadcasting behavior of the `weights` `Tensor`: * `weights_prior.batch_shape == []`: shares a single set of weights across all design matrices and observed time series. This may make sense if the features in each design matrix have the same semantics (e.g., grouping observations by country, with per-country design matrices capturing the same set of national economic indicators per country). * `weights_prior.batch_shape == `design_matrix.batch_shape`: fits separate weights for each design matrix. If there are multiple observed time series for each design matrix, this shares statistical strength over those observations. * `weights_prior.batch_shape == `observed_time_series.batch_shape`: fits a separate regression for each individual time series. When modeling batches of time series, you should think carefully about which behavior makes sense, and specify `weights_prior` accordingly: the defaults may not do what you want! Args: design_matrix: float `Tensor` of shape `concat([batch_shape, [num_timesteps, num_features]])`. This may also optionally be an instance of `tf.linalg.LinearOperator`. weights_prior: `tfd.Distribution` representing a prior over the regression weights. Must have event shape `[num_features]` and batch shape broadcastable to the design matrix's `batch_shape`. Alternately, `event_shape` may be scalar (`[]`), in which case the prior is internally broadcast as `TransformedDistribution(weights_prior, tfb.Identity(), event_shape=[num_features], batch_shape=design_matrix.batch_shape)`. If `None`, defaults to `StudentT(df=5, loc=0., scale=10.)`, a weakly-informative prior loosely inspired by the [Stan prior choice recommendations]( https://github.com/stan-dev/stan/wiki/Prior-Choice-Recommendations). Default value: `None`. name: the name of this model component. Default value: 'LinearRegression'. """ with tf.name_scope(name, 'LinearRegression', values=[design_matrix]) as name: if not isinstance(design_matrix, tfl.LinearOperator): design_matrix = tfl.LinearOperatorFullMatrix( tf.convert_to_tensor(design_matrix, name='design_matrix'), name='design_matrix_linop') if tf.dimension_value(design_matrix.shape[-1]) is not None: num_features = design_matrix.shape[-1] else: num_features = design_matrix.shape_tensor()[-1] # Default to a weakly-informative StudentT(df=5, 0., 10.) prior. if weights_prior is None: weights_prior = tfd.StudentT( df=5, loc=tf.zeros([], dtype=design_matrix.dtype), scale=10 * tf.ones([], dtype=design_matrix.dtype)) # Sugar: if prior is static scalar, broadcast it to a default shape. if weights_prior.event_shape.ndims == 0: if design_matrix.batch_shape.is_fully_defined(): design_matrix_batch_shape_ = design_matrix.batch_shape else: design_matrix_batch_shape_ = design_matrix.batch_shape_tensor( ) weights_prior = tfd.TransformedDistribution( weights_prior, bijector=tfb.Identity(), batch_shape=design_matrix_batch_shape_, event_shape=[num_features]) tf.assert_same_float_dtype([design_matrix, weights_prior]) self._design_matrix = design_matrix super(LinearRegression, self).__init__(parameters=[ Parameter('weights', weights_prior, tfb.Identity()), ], latent_size=0, name=name)
def __init__(self, level_scale_prior=None, slope_scale_prior=None, initial_level_prior=None, initial_slope_prior=None, observed_time_series=None, name=None): """Specify a local linear trend model. Args: level_scale_prior: optional `tfd.Distribution` instance specifying a prior on the `level_scale` parameter. If `None`, a heuristic default prior is constructed based on the provided `observed_time_series`. Default value: `None`. slope_scale_prior: optional `tfd.Distribution` instance specifying a prior on the `slope_scale` parameter. If `None`, a heuristic default prior is constructed based on the provided `observed_time_series`. Default value: `None`. initial_level_prior: optional `tfd.Distribution` instance specifying a prior on the initial level. If `None`, a heuristic default prior is constructed based on the provided `observed_time_series`. Default value: `None`. initial_slope_prior: optional `tfd.Distribution` instance specifying a prior on the initial slope. If `None`, a heuristic default prior is constructed based on the provided `observed_time_series`. Default value: `None`. observed_time_series: optional `float` `Tensor` of shape `batch_shape + [T, 1]` (omitting the trailing unit dimension is also supported when `T > 1`), specifying an observed time series. Any priors not explicitly set will be given default values according to the scale of the observed time series (or batch of time series). Default value: `None`. name: the name of this model component. Default value: 'LocalLinearTrend'. """ with tf.name_scope( name, 'LocalLinearTrend', values=[observed_time_series]) as name: observed_stddev, observed_initial = ( sts_util.empirical_statistics(observed_time_series) if observed_time_series is not None else (1., 0.)) # Heuristic default priors. Overriding these may dramatically # change inference performance and results. if level_scale_prior is None: level_scale_prior = tfd.LogNormal( loc=tf.log(.05 * observed_stddev), scale=3., name='level_scale_prior') if slope_scale_prior is None: slope_scale_prior = tfd.LogNormal( loc=tf.log(.05 * observed_stddev), scale=3., name='slope_scale_prior') if initial_level_prior is None: initial_level_prior = tfd.Normal( loc=observed_initial, scale=observed_stddev, name='initial_level_prior') if initial_slope_prior is None: initial_slope_prior = tfd.Normal( loc=0., scale=observed_stddev, name='initial_slope_prior') tf.assert_same_float_dtype([ level_scale_prior, slope_scale_prior, initial_level_prior, initial_slope_prior ]) self._initial_state_prior = tfd.MultivariateNormalDiag( loc=tf.stack( [initial_level_prior.mean(), initial_slope_prior.mean() ], axis=-1), scale_diag=tf.stack([ initial_level_prior.stddev(), initial_slope_prior.stddev() ], axis=-1)) super(LocalLinearTrend, self).__init__( parameters=[ Parameter('level_scale', level_scale_prior, tfb.Softplus()), Parameter('slope_scale', slope_scale_prior, tfb.Softplus()) ], latent_size=2, name=name)
def __init__(self, df, scale_operator, input_output_cholesky=False, validate_args=False, allow_nan_stats=True, name=None): """Construct Wishart distributions. Args: df: `float` or `double` tensor, the degrees of freedom of the distribution(s). `df` must be greater than or equal to `k`. scale_operator: `float` or `double` instance of `LinearOperator`. 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: TypeError: if scale is not floating-type TypeError: if scale.dtype != df.dtype ValueError: if df < k, where scale operator event shape is `(k, k)` """ parameters = dict(locals()) self._input_output_cholesky = input_output_cholesky with tf.name_scope(name) as name: with tf.name_scope("init", values=[df, scale_operator]): if not scale_operator.dtype.is_floating: raise TypeError( "scale_operator.dtype=%s is not a floating-point type" % scale_operator.dtype) if not scale_operator.is_square: print(scale_operator.to_dense().eval()) raise ValueError("scale_operator must be square.") self._scale_operator = scale_operator self._df = tf.convert_to_tensor(df, dtype=scale_operator.dtype, name="df") tf.assert_same_float_dtype([self._df, self._scale_operator]) if (self._scale_operator.shape.ndims is None or self._scale_operator.shape[-1].value is None): self._dimension = tf.cast( self._scale_operator.domain_dimension_tensor(), dtype=self._scale_operator.dtype, name="dimension") else: self._dimension = tf.convert_to_tensor( self._scale_operator.shape[-1].value, dtype=self._scale_operator.dtype, name="dimension") df_val = tensor_util.constant_value(self._df) dim_val = tensor_util.constant_value(self._dimension) if df_val is not None and dim_val is not None: df_val = np.asarray(df_val) if not df_val.shape: df_val = [df_val] if any(df_val < dim_val): raise ValueError( "Degrees of freedom (df = %s) cannot be less than " "dimension of scale matrix (scale.dimension = %s)" % (df_val, dim_val)) elif validate_args: assertions = tf.assert_less_equal( self._dimension, self._df, message=("Degrees of freedom (df = %s) cannot be " "less than dimension of scale matrix " "(scale.dimension = %s)" % (self._dimension, self._df))) self._df = control_flow_ops.with_dependencies([assertions], self._df) super(_WishartLinearOperator, self).__init__( dtype=self._scale_operator.dtype, validate_args=validate_args, allow_nan_stats=allow_nan_stats, reparameterization_type=reparameterization.FULLY_REPARAMETERIZED, parameters=parameters, graph_parents=([self._df, self._dimension] + self._scale_operator.graph_parents), name=name)
def __init__(self, mean_direction, concentration, validate_args=False, allow_nan_stats=True, name='VonMisesFisher'): """Creates a new `VonMisesFisher` instance. Args: mean_direction: Floating-point `Tensor` with shape [B1, ... Bn, D]. A unit vector indicating the mode of the distribution, or the unit-normalized direction of the mean. (This is *not* in general the mean of the distribution; the mean is not generally in the support of the distribution.) NOTE: `D` is currently restricted to <= 5. concentration: Floating-point `Tensor` having batch shape [B1, ... Bn] broadcastable with `mean_direction`. The level of concentration of samples around the `mean_direction`. `concentration=0` indicates a uniform distribution over the unit hypersphere, and `concentration=+inf` indicates a `Deterministic` distribution (delta function) at `mean_direction`. 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: For known-bad arguments, i.e. unsupported event dimension. """ parameters = dict(locals()) with tf.name_scope(name, values=[mean_direction, concentration]) as name: dtype = dtype_util.common_dtype([mean_direction, concentration], tf.float32) mean_direction = tf.convert_to_tensor( mean_direction, name='mean_direction', dtype=dtype) concentration = tf.convert_to_tensor( concentration, name='concentration', dtype=dtype) assertions = [ tf.assert_non_negative( concentration, message='`concentration` must be non-negative'), tf.assert_greater( tf.shape(mean_direction)[-1], 1, message='`mean_direction` may not have scalar event shape'), tf.assert_near( 1., tf.linalg.norm(mean_direction, axis=-1), message='`mean_direction` must be unit-length') ] if validate_args else [] if mean_direction.shape.with_rank_at_least(1)[-1].value is not None: if mean_direction.shape.with_rank_at_least(1)[-1].value > 5: raise ValueError('vMF ndims > 5 is not currently supported') elif validate_args: assertions += [tf.assert_less_equal( tf.shape(mean_direction)[-1], 5, message='vMF ndims > 5 is not currently supported')] with tf.control_dependencies(assertions): self._mean_direction = tf.identity(mean_direction) self._concentration = tf.identity(concentration) tf.assert_same_float_dtype([self._mean_direction, self._concentration]) # mean_direction is always reparameterized. # concentration is only for event_dim==3, via an inversion sampler. reparameterization_type = ( reparameterization.FULLY_REPARAMETERIZED if mean_direction.shape.with_rank_at_least(1)[-1].value == 3 else reparameterization.NOT_REPARAMETERIZED) super(VonMisesFisher, self).__init__( dtype=self._concentration.dtype, validate_args=validate_args, allow_nan_stats=allow_nan_stats, reparameterization_type=reparameterization_type, parameters=parameters, graph_parents=[self._mean_direction, self._concentration], name=name)
def __init__(self, level_scale_prior=None, slope_scale_prior=None, initial_level_prior=None, initial_slope_prior=None, observed_time_series=None, name=None): """Specify a local linear trend model. Args: level_scale_prior: optional `tfd.Distribution` instance specifying a prior on the `level_scale` parameter. If `None`, a heuristic default prior is constructed based on the provided `observed_time_series`. Default value: `None`. slope_scale_prior: optional `tfd.Distribution` instance specifying a prior on the `slope_scale` parameter. If `None`, a heuristic default prior is constructed based on the provided `observed_time_series`. Default value: `None`. initial_level_prior: optional `tfd.Distribution` instance specifying a prior on the initial level. If `None`, a heuristic default prior is constructed based on the provided `observed_time_series`. Default value: `None`. initial_slope_prior: optional `tfd.Distribution` instance specifying a prior on the initial slope. If `None`, a heuristic default prior is constructed based on the provided `observed_time_series`. Default value: `None`. observed_time_series: optional `float` `Tensor` of shape `batch_shape + [T, 1]` (omitting the trailing unit dimension is also supported when `T > 1`), specifying an observed time series. Any priors not explicitly set will be given default values according to the scale of the observed time series (or batch of time series). Default value: `None`. name: the name of this model component. Default value: 'LocalLinearTrend'. """ with tf.name_scope( name, 'LocalLinearTrend', values=[observed_time_series]) as name: observed_stddev, observed_initial = ( sts_util.empirical_statistics(observed_time_series) if observed_time_series is not None else (1., 0.)) # Heuristic default priors. Overriding these may dramatically # change inference performance and results. if level_scale_prior is None: level_scale_prior = tfd.LogNormal( loc=tf.log(.05 * observed_stddev), scale=3., name='level_scale_prior') if slope_scale_prior is None: slope_scale_prior = tfd.LogNormal( loc=tf.log(.05 * observed_stddev), scale=3., name='slope_scale_prior') if initial_level_prior is None: initial_level_prior = tfd.Normal( loc=observed_initial, scale=tf.abs(observed_initial) + observed_stddev, name='initial_level_prior') if initial_slope_prior is None: initial_slope_prior = tfd.Normal( loc=0., scale=observed_stddev, name='initial_slope_prior') tf.assert_same_float_dtype([ level_scale_prior, slope_scale_prior, initial_level_prior, initial_slope_prior ]) self._initial_state_prior = tfd.MultivariateNormalDiag( loc=tf.stack( [initial_level_prior.mean(), initial_slope_prior.mean() ], axis=-1), scale_diag=tf.stack([ initial_level_prior.stddev(), initial_slope_prior.stddev() ], axis=-1)) super(LocalLinearTrend, self).__init__( parameters=[ Parameter('level_scale', level_scale_prior, tfb.Softplus()), Parameter('slope_scale', slope_scale_prior, tfb.Softplus()) ], latent_size=2, name=name)
def __init__(self, distribution, low=None, high=None, validate_args=False, name="QuantizedDistribution"): """Construct a Quantized Distribution representing `Y = ceiling(X)`. Some properties are inherited from the distribution defining `X`. Example: `allow_nan_stats` is determined for this `QuantizedDistribution` by reading the `distribution`. Args: distribution: The base distribution class to transform. Typically an instance of `Distribution`. low: `Tensor` with same `dtype` as this distribution and shape able to be added to samples. Should be a whole number. Default `None`. If provided, base distribution's `prob` should be defined at `low`. high: `Tensor` with same `dtype` as this distribution and shape able to be added to samples. Should be a whole number. Default `None`. If provided, base distribution's `prob` should be defined at `high - 1`. `high` must be strictly greater than `low`. 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. name: Python `str` name prefixed to Ops created by this class. Raises: TypeError: If `dist_cls` is not a subclass of `Distribution` or continuous. NotImplementedError: If the base distribution does not implement `cdf`. """ parameters = dict(locals()) values = ( list(distribution.parameters.values()) + [low, high]) with tf.name_scope(name, values=values) as name: self._dist = distribution if low is not None: low = tf.convert_to_tensor(low, name="low") if high is not None: high = tf.convert_to_tensor(high, name="high") tf.assert_same_float_dtype(tensors=[self.distribution, low, high]) # We let QuantizedDistribution access _graph_parents since this class is # more like a baseclass. graph_parents = self._dist._graph_parents # pylint: disable=protected-access checks = [] if validate_args and low is not None and high is not None: message = "low must be strictly less than high." checks.append(tf.assert_less(low, high, message=message)) self._validate_args = validate_args # self._check_integer uses this. with tf.control_dependencies(checks if validate_args else []): if low is not None: self._low = self._check_integer(low) graph_parents += [self._low] else: self._low = None if high is not None: self._high = self._check_integer(high) graph_parents += [self._high] else: self._high = None super(QuantizedDistribution, self).__init__( dtype=self._dist.dtype, reparameterization_type=distributions.NOT_REPARAMETERIZED, validate_args=validate_args, allow_nan_stats=self._dist.allow_nan_stats, parameters=parameters, graph_parents=graph_parents, name=name)
def __init__(self, loc, scale, low, high, validate_args=False, allow_nan_stats=True, name="TruncatedNormal"): """Construct TruncatedNormal. All parameters of the distribution will be broadcast to the same shape, so the resulting distribution will have a batch_shape of the broadcast shape of all parameters. Args: loc: Floating point tensor; the mean of the normal distribution(s) ( note that the mean of the resulting distribution will be different since it is modified by the bounds). scale: Floating point tensor; the std deviation of the normal distribution(s). low: `float` `Tensor` representing lower bound of the distribution's support. Must be such that `low < high`. high: `float` `Tensor` representing upper bound of the distribution's support. Must be such that `low < high`. validate_args: Python `bool`, default `False`. When `True` distribution parameters are checked at run-time. 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. """ parameters = dict(locals()) with tf.name_scope(name, values=[scale]) as name: loc = tf.convert_to_tensor(loc, name="loc") dtype = loc.dtype scale = tf.convert_to_tensor(scale, name="scale", dtype=dtype) low = tf.convert_to_tensor(low, name="low", dtype=dtype) high = tf.convert_to_tensor(high, name="high", dtype=dtype) tf.assert_same_float_dtype([loc, scale, low, high]) self._broadcast_batch_shape = distribution_util.get_broadcast_shape( loc, scale, low, high) # Broadcast all parameters to the same shape broadcast_ones = tf.ones(shape=self._broadcast_batch_shape, dtype=scale.dtype) self._scale = scale * broadcast_ones self._loc = loc * broadcast_ones self._low = low * broadcast_ones self._high = high * broadcast_ones with tf.control_dependencies([self._validate()] if validate_args else []): self._loc = tf.identity(self._loc) super(TruncatedNormal, self).__init__( dtype=dtype, # This distribution is partial reparameterized. loc, scale have straight # through gradients but not the bounds. # TODO(mfigurnov): This could be extended to use implicit gradients to # compute derivatives for the bounds. # https://arxiv.org/pdf/1806.01851.pdf reparameterization_type=tf.distributions.NOT_REPARAMETERIZED, validate_args=validate_args, allow_nan_stats=allow_nan_stats, parameters=parameters, graph_parents=[loc, scale, low, high], name=name)
def __init__(self, distribution, low=None, high=None, validate_args=False, name="QuantizedDistribution"): """Construct a Quantized Distribution representing `Y = ceiling(X)`. Some properties are inherited from the distribution defining `X`. Example: `allow_nan_stats` is determined for this `QuantizedDistribution` by reading the `distribution`. Args: distribution: The base distribution class to transform. Typically an instance of `Distribution`. low: `Tensor` with same `dtype` as this distribution and shape able to be added to samples. Should be a whole number. Default `None`. If provided, base distribution's `prob` should be defined at `low`. high: `Tensor` with same `dtype` as this distribution and shape able to be added to samples. Should be a whole number. Default `None`. If provided, base distribution's `prob` should be defined at `high - 1`. `high` must be strictly greater than `low`. 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. name: Python `str` name prefixed to Ops created by this class. Raises: TypeError: If `dist_cls` is not a subclass of `Distribution` or continuous. NotImplementedError: If the base distribution does not implement `cdf`. """ parameters = dict(locals()) values = (list(distribution.parameters.values()) + [low, high]) with tf.name_scope(name, values=values) as name: self._dist = distribution if low is not None: low = tf.convert_to_tensor(low, name="low", dtype=distribution.dtype) if high is not None: high = tf.convert_to_tensor(high, name="high", dtype=distribution.dtype) tf.assert_same_float_dtype(tensors=[self.distribution, low, high]) # We let QuantizedDistribution access _graph_parents since this class is # more like a baseclass. graph_parents = self._dist._graph_parents # pylint: disable=protected-access checks = [] if validate_args and low is not None and high is not None: message = "low must be strictly less than high." checks.append(tf.assert_less(low, high, message=message)) self._validate_args = validate_args # self._check_integer uses this. with tf.control_dependencies(checks if validate_args else []): if low is not None: self._low = self._check_integer(low) graph_parents += [self._low] else: self._low = None if high is not None: self._high = self._check_integer(high) graph_parents += [self._high] else: self._high = None super(QuantizedDistribution, self).__init__( dtype=self._dist.dtype, reparameterization_type=reparameterization.NOT_REPARAMETERIZED, validate_args=validate_args, allow_nan_stats=self._dist.allow_nan_stats, parameters=parameters, graph_parents=graph_parents, name=name)
def __init__(self, bias_variance=None, slope_variance=None, shift=None, exponent=None, feature_ndims=1, validate_args=False, name='Polynomial'): """Construct a Polynomial kernel instance. Args: bias_variance: Positive floating point `Tensor` that controls the variance from the origin. If bias = 0, there is no variance and the fitted function goes through the origin. Must be broadcastable with `slope_variance`, `shift`, `exponent`, and inputs to `apply` and `matrix` methods. A value of `None` is treated like 0. Default Value: `None` slope_variance: Positive floating point `Tensor` that controls the variance of the regression line slope that is the basis for the polynomial. Must be broadcastable with `bias_variance`, `shift`, `exponent`, and inputs to `apply` and `matrix` methods. A value of `None` is treated like 1. Default Value: `None` shift: Floating point `Tensor` that contols the intercept with the x-axis of the linear function to be exponentiated to get this polynomial. Must be broadcastable with `bias_variance`, `slope_variance`, `exponent` and inputs to `apply` and `matrix` methods. A value of `None` is treated like 0, which results in having the intercept at the origin. Default Value: `None` exponent: Positive floating point `Tensor` that controls the exponent (also known as the degree) of the polynomial function. Must be broadcastable with `bias_variance`, `slope_variance`, `shift`, and inputs to `apply` and `matrix` methods. A value of `None` is treated like 1, which results in a linear kernel. Default Value: `None` feature_ndims: Python `int` number of rightmost dims to include in kernel computation. Default Value: 1 validate_args: If `True`, parameters are checked for validity despite possibly degrading runtime performance. Default Value: `False` name: Python `str` name prefixed to Ops created by this class. Default Value: `'Polynomial'` """ with tf.name_scope(name, values=[ bias_variance, slope_variance, shift, exponent]): dtype = dtype_util.common_dtype( [bias_variance, slope_variance, shift, exponent], tf.float32) if bias_variance is not None: bias_variance = tf.convert_to_tensor( bias_variance, name='bias_variance', dtype=dtype) self._bias_variance = _validate_arg_if_not_none( bias_variance, tf.assert_positive, validate_args) if slope_variance is not None: slope_variance = tf.convert_to_tensor( slope_variance, name='slope_variance', dtype=dtype) self._slope_variance = _validate_arg_if_not_none( slope_variance, tf.assert_positive, validate_args) if shift is not None: shift = tf.convert_to_tensor( shift, name='shift', dtype=dtype) self._shift = shift if exponent is not None: exponent = tf.convert_to_tensor( exponent, name='exponent', dtype=dtype) self._exponent = _validate_arg_if_not_none( exponent, tf.assert_positive, validate_args) tf.assert_same_float_dtype( [self._bias_variance, self._slope_variance, self._shift, self._exponent]) super(Polynomial, self).__init__( feature_ndims, dtype=dtype, name=name)
def __init__(self, mean_direction, concentration, validate_args=False, allow_nan_stats=True, name='VonMisesFisher'): """Creates a new `VonMisesFisher` instance. Args: mean_direction: Floating-point `Tensor` with shape [B1, ... Bn, D]. A unit vector indicating the mode of the distribution, or the unit-normalized direction of the mean. (This is *not* in general the mean of the distribution; the mean is not generally in the support of the distribution.) NOTE: `D` is currently restricted to <= 5. concentration: Floating-point `Tensor` having batch shape [B1, ... Bn] broadcastable with `mean_direction`. The level of concentration of samples around the `mean_direction`. `concentration=0` indicates a uniform distribution over the unit hypersphere, and `concentration=+inf` indicates a `Deterministic` distribution (delta function) at `mean_direction`. 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: For known-bad arguments, i.e. unsupported event dimension. """ parameters = dict(locals()) with tf.name_scope(name, values=[mean_direction, concentration]) as name: assertions = [ tf.assert_non_negative( concentration, message='`concentration` must be non-negative'), tf.assert_greater( tf.shape(mean_direction)[-1], 1, message='`mean_direction` may not have scalar event shape' ), tf.assert_near(1., tf.linalg.norm(mean_direction, axis=-1), message='`mean_direction` must be unit-length') ] if validate_args else [] if mean_direction.shape.with_rank_at_least( 1)[-1].value is not None: if mean_direction.shape.with_rank_at_least(1)[-1].value > 5: raise ValueError( 'vMF ndims > 5 is not currently supported') elif validate_args: assertions += [ tf.assert_less_equal( tf.shape(mean_direction)[-1], 5, message='vMF ndims > 5 is not currently supported') ] with tf.control_dependencies(assertions): self._mean_direction = tf.convert_to_tensor( mean_direction, name='mean_direction') self._concentration = tf.convert_to_tensor( concentration, name='concentration') tf.assert_same_float_dtype( [self._mean_direction, self._concentration]) # mean_direction is always reparameterized. # concentration is only for event_dim==3, via an inversion sampler. reparameterization_type = ( tf.distributions.FULLY_REPARAMETERIZED if mean_direction.shape.with_rank_at_least(1)[-1].value == 3 else tf.distributions.NOT_REPARAMETERIZED) super(VonMisesFisher, self).__init__( dtype=self._concentration.dtype, validate_args=validate_args, allow_nan_stats=allow_nan_stats, reparameterization_type=reparameterization_type, parameters=parameters, graph_parents=[self._mean_direction, self._concentration], name=name)
def __init__(self, num_seasons, num_steps_per_season=1, drift_scale_prior=None, initial_effect_prior=None, observed_time_series=None, name=None): """Specify a seasonal effects model. Args: num_seasons: Scalar Python `int` number of seasons. num_steps_per_season: Python `int` number of steps in each season. This may be either a scalar (shape `[]`), in which case all seasons have the same length, or a NumPy array of shape `[num_seasons]`. Default value: 1. drift_scale_prior: optional `tfd.Distribution` instance specifying a prior on the `drift_scale` parameter. If `None`, a heuristic default prior is constructed based on the provided `observed_time_series`. Default value: `None`. initial_effect_prior: optional `tfd.Distribution` instance specifying a normal prior on the initial effect of each season. This may be either a scalar `tfd.Normal` prior, in which case it applies independently to every season, or it may be multivariate normal (e.g., `tfd.MultivariateNormalDiag`) with event shape `[num_seasons]`, in which case it specifies a joint prior across all seasons. If `None`, a heuristic default prior is constructed based on the provided `observed_time_series`. Default value: `None`. observed_time_series: optional `float` `Tensor` of shape `batch_shape + [T, 1]` (omitting the trailing unit dimension is also supported when `T > 1`), specifying an observed time series. Any priors not explicitly set will be given default values according to the scale of the observed time series (or batch of time series). Default value: `None`. name: the name of this model component. Default value: 'Seasonal'. """ with tf.name_scope(name, 'Seasonal', values=[observed_time_series]) as name: observed_stddev, observed_initial = ( sts_util.empirical_statistics(observed_time_series) if observed_time_series is not None else (1., 0.)) # Heuristic default priors. Overriding these may dramatically # change inference performance and results. if drift_scale_prior is None: drift_scale_prior = tfd.LogNormal(loc=tf.log(.01 * observed_stddev), scale=3.) if initial_effect_prior is None: initial_effect_prior = tfd.Normal(loc=observed_initial, scale=observed_stddev) self._num_seasons = num_seasons self._num_steps_per_season = num_steps_per_season tf.assert_same_float_dtype([drift_scale_prior, initial_effect_prior]) if isinstance(initial_effect_prior, tfd.Normal): self._initial_state_prior = tfd.MultivariateNormalDiag( loc=tf.stack([initial_effect_prior.mean()] * num_seasons, axis=-1), scale_diag=tf.stack([initial_effect_prior.stddev()] * num_seasons, axis=-1)) else: self._initial_state_prior = initial_effect_prior super(Seasonal, self).__init__( parameters=[ Parameter('drift_scale', drift_scale_prior, tfb.Softplus()), ], latent_size=num_seasons, name=name)
def __init__(self, loc, scale, concentration, rate, validate_args=False, allow_nan_stats=True, name="NormalGamma"): """Initializes a batch of Normal-Gamma distributions. Args: loc: Floating point tensor; the means of the distribution(s). scale: Floating point tensor; the stddevs of the distribution(s). Must contain only positive values. (`scale = sqrt(lambda)` according to the wikipedia article) concentration: Floating point tensor, the concentration params of the distribution(s). Must contain only positive values. rate: Floating point tensor, the inverse scale params of the distribution(s). Must contain only positive values. 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: TypeError: if `concentration` and `rate` are different dtypes. """ parameters = dict(locals()) with tf.name_scope( name, values=[loc, scale, concentration, rate]): dtype = dtype_util.common_dtype( [loc, scale, concentration, rate], preferred_dtype=tf.float32) loc = tf.convert_to_tensor(loc, name="loc", dtype=dtype) scale = tf.convert_to_tensor( scale, name="scale", dtype=dtype) concentration = tf.convert_to_tensor( concentration, name="concentration", dtype=dtype) rate = tf.convert_to_tensor(rate, name="rate", dtype=dtype) with tf.control_dependencies([ tf.assert_positive(scale), tf.assert_positive(concentration), tf.assert_positive(rate), ] if validate_args else []): self._loc = tf.identity(loc) self._scale = tf.identity(scale) self._concentration = tf.identity(concentration) self._rate = tf.identity(rate) tf.assert_same_float_dtype( [self._loc, self._scale, self._concentration, self._rate]) # the coefficient for the precision self._lambda = tf.square(self._scale) super(NormalGamma, self).__init__( dtype=self._loc.dtype, validate_args=validate_args, allow_nan_stats=allow_nan_stats, reparameterization_type=reparameterization.FULLY_REPARAMETERIZED, parameters=parameters, graph_parents=[self._loc, self._scale, self._concentration, self._rate], name=name)
def __init__(self, heights, edgescales=None, lengthscales=None, feature_ndims=1, validate_args=False, name='Histogram'): """Construct an Histogram kernel instance. Gives the histogram kernel on the isotropic distance from a point. Args: heights: floating point `Tensor` heights of spectum histogram. Must be broadcastable with `edgescales` and inputs to `apply` and `matrix` methods. edgescales: floating point `Tensor` that controls how wide the spectrum bins are. These are lengthscales, and edges are actually 1/``edgescales``. Must be broadcastable with `heights` and inputs to `apply` and `matrix` methods. lengthscales: floating point `Tensor` that controls how wide the spectrum bins are. The edges are actually 1/``lengthscales``. Must be broadcastable with `heights` and inputs to `apply` and `matrix` methods. feature_ndims: Python `int` number of rightmost dims to include in the squared difference norm in the exponential. validate_args: If `True`, parameters are checked for validity despite possibly degrading runtime performance name: Python `str` name prefixed to Ops created by this class. """ with tf.name_scope(name, values=[heights, edgescales]) as name: dtype = dtype_util.common_dtype([heights, edgescales], float_type) if heights is not None: heights = tf.convert_to_tensor(heights, name='heights', dtype=dtype) self._heights = _validate_arg_if_not_none(heights, tf.assert_positive, validate_args) if lengthscales is not None: lengthscales = tf.convert_to_tensor(lengthscales, dtype=dtype, name='lengthscales') lengthscales = tf.nn.top_k(lengthscales, k=tf.shape(lengthscales)[-1], sorted=True)[0] edgescales = tf.reciprocal(lengthscales) if edgescales is not None: edgescales = tf.convert_to_tensor(edgescales, dtype=dtype, name='edgescales') edgescales = tf.reverse(tf.nn.top_k(edgescales, k=tf.shape(edgescales)[-1], sorted=True)[0], axis=[-1]) lengthscales = tf.reciprocal(edgescales) self._edgescales = _validate_arg_if_not_none( edgescales, tf.assert_positive, validate_args) self._lengthscales = _validate_arg_if_not_none( lengthscales, tf.assert_positive, validate_args) tf.assert_same_float_dtype( [self._heights, self._edgescales, self._lengthscales]) super(Histogram, self).__init__(feature_ndims, dtype=dtype, name=name)
def __init__(self, num_seasons, num_steps_per_season=1, drift_scale_prior=None, initial_effect_prior=None, observed_time_series=None, name=None): """Specify a seasonal effects model. Args: num_seasons: Scalar Python `int` number of seasons. num_steps_per_season: Python `int` number of steps in each season. This may be either a scalar (shape `[]`), in which case all seasons have the same length, or a NumPy array of shape `[num_seasons]`. Default value: 1. drift_scale_prior: optional `tfd.Distribution` instance specifying a prior on the `drift_scale` parameter. If `None`, a heuristic default prior is constructed based on the provided `observed_time_series`. Default value: `None`. initial_effect_prior: optional `tfd.Distribution` instance specifying a normal prior on the initial effect of each season. This may be either a scalar `tfd.Normal` prior, in which case it applies independently to every season, or it may be multivariate normal (e.g., `tfd.MultivariateNormalDiag`) with event shape `[num_seasons]`, in which case it specifies a joint prior across all seasons. If `None`, a heuristic default prior is constructed based on the provided `observed_time_series`. Default value: `None`. observed_time_series: optional `float` `Tensor` of shape `batch_shape + [T, 1]` (omitting the trailing unit dimension is also supported when `T > 1`), specifying an observed time series. Any priors not explicitly set will be given default values according to the scale of the observed time series (or batch of time series). Default value: `None`. name: the name of this model component. Default value: 'Seasonal'. """ with tf.name_scope(name, 'Seasonal', values=[observed_time_series]) as name: observed_stddev, observed_initial = ( sts_util.empirical_statistics(observed_time_series) if observed_time_series is not None else (1., 0.)) # Heuristic default priors. Overriding these may dramatically # change inference performance and results. if drift_scale_prior is None: drift_scale_prior = tfd.LogNormal(loc=tf.log(.01 * observed_stddev), scale=3.) if initial_effect_prior is None: initial_effect_prior = tfd.Normal(loc=observed_initial, scale=observed_stddev) self._num_seasons = num_seasons self._num_steps_per_season = num_steps_per_season tf.assert_same_float_dtype( [drift_scale_prior, initial_effect_prior]) if isinstance(initial_effect_prior, tfd.Normal): self._initial_state_prior = tfd.MultivariateNormalDiag( loc=tf.stack([initial_effect_prior.mean()] * num_seasons, axis=-1), scale_diag=tf.stack([initial_effect_prior.stddev()] * num_seasons, axis=-1)) else: self._initial_state_prior = initial_effect_prior super(Seasonal, self).__init__(parameters=[ Parameter('drift_scale', drift_scale_prior, tfb.Softplus()), ], latent_size=num_seasons, name=name)
def __init__(self, loc, scale, low, high, validate_args=False, allow_nan_stats=True, name="TruncatedNormal"): """Construct TruncatedNormal. All parameters of the distribution will be broadcast to the same shape, so the resulting distribution will have a batch_shape of the broadcast shape of all parameters. Args: loc: Floating point tensor; the mean of the normal distribution(s) ( note that the mean of the resulting distribution will be different since it is modified by the bounds). scale: Floating point tensor; the std deviation of the normal distribution(s). low: `float` `Tensor` representing lower bound of the distribution's support. Must be such that `low < high`. high: `float` `Tensor` representing upper bound of the distribution's support. Must be such that `low < high`. validate_args: Python `bool`, default `False`. When `True` distribution parameters are checked at run-time. 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. """ parameters = dict(locals()) with tf.name_scope(name, values=[loc, scale, low, high]) as name: dtype = dtype_util.common_dtype([loc, scale, low, high], tf.float32) loc = tf.convert_to_tensor(loc, name="loc", dtype=dtype) scale = tf.convert_to_tensor(scale, name="scale", dtype=dtype) low = tf.convert_to_tensor(low, name="low", dtype=dtype) high = tf.convert_to_tensor(high, name="high", dtype=dtype) tf.assert_same_float_dtype([loc, scale, low, high]) self._broadcast_batch_shape = distribution_util.get_broadcast_shape( loc, scale, low, high) # Broadcast all parameters to the same shape broadcast_ones = tf.ones(shape=self._broadcast_batch_shape, dtype=scale.dtype) self._scale = scale * broadcast_ones self._loc = loc * broadcast_ones self._low = low * broadcast_ones self._high = high * broadcast_ones with tf.control_dependencies( [self._validate()] if validate_args else []): self._loc = tf.identity(self._loc) super(TruncatedNormal, self).__init__( dtype=dtype, # This distribution is fully reparameterized. loc, scale have straight # through gradients. The gradients for the bounds are implemented using # custom derived expressions based on implicit gradients. # For the special case of lower bound zero and a positive upper bound # an equivalent expression can also be found in Sec 9.1.1. # of https://arxiv.org/pdf/1806.01851.pdf. The implementation here # handles arbitrary bounds. reparameterization_type=reparameterization.FULLY_REPARAMETERIZED, validate_args=validate_args, allow_nan_stats=allow_nan_stats, parameters=parameters, graph_parents=[loc, scale, low, high], name=name)
def __init__(self, df, scale_operator, input_output_cholesky=False, validate_args=False, allow_nan_stats=True, name=None): """Construct Wishart distributions. Args: df: `float` or `double` tensor, the degrees of freedom of the distribution(s). `df` must be greater than or equal to `k`. scale_operator: `float` or `double` instance of `LinearOperator`. 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: TypeError: if scale is not floating-type TypeError: if scale.dtype != df.dtype ValueError: if df < k, where scale operator event shape is `(k, k)` """ parameters = dict(locals()) self._input_output_cholesky = input_output_cholesky with tf.name_scope(name) as name: with tf.name_scope("init", values=[df, scale_operator]): if not scale_operator.dtype.is_floating: raise TypeError( "scale_operator.dtype=%s is not a floating-point type" % scale_operator.dtype) if not scale_operator.is_square: print(scale_operator.to_dense().eval()) raise ValueError("scale_operator must be square.") self._scale_operator = scale_operator self._df = tf.convert_to_tensor( df, dtype=scale_operator.dtype, name="df") tf.assert_same_float_dtype([self._df, self._scale_operator]) if (self._scale_operator.shape.ndims is None or self._scale_operator.shape[-1].value is None): self._dimension = tf.cast( self._scale_operator.domain_dimension_tensor(), dtype=self._scale_operator.dtype, name="dimension") else: self._dimension = tf.convert_to_tensor( self._scale_operator.shape[-1].value, dtype=self._scale_operator.dtype, name="dimension") df_val = tf.contrib.util.constant_value(self._df) dim_val = tf.contrib.util.constant_value(self._dimension) if df_val is not None and dim_val is not None: df_val = np.asarray(df_val) if not df_val.shape: df_val = [df_val] if any(df_val < dim_val): raise ValueError( "Degrees of freedom (df = %s) cannot be less than " "dimension of scale matrix (scale.dimension = %s)" % (df_val, dim_val)) elif validate_args: assertions = tf.assert_less_equal( self._dimension, self._df, message=("Degrees of freedom (df = %s) cannot be " "less than dimension of scale matrix " "(scale.dimension = %s)" % (self._dimension, self._df))) self._df = control_flow_ops.with_dependencies( [assertions], self._df) super(_WishartLinearOperator, self).__init__( dtype=self._scale_operator.dtype, validate_args=validate_args, allow_nan_stats=allow_nan_stats, reparameterization_type=reparameterization.FULLY_REPARAMETERIZED, parameters=parameters, graph_parents=( [self._df, self._dimension] + self._scale_operator.graph_parents), name=name)