Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/tensorflow/python/ops/distributions/laplace.py: 57%
84 statements
« prev ^ index » next coverage.py v7.4.0, created at 2024-01-03 07:57 +0000
« prev ^ index » next coverage.py v7.4.0, created at 2024-01-03 07:57 +0000
1# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14# ==============================================================================
15"""The Laplace distribution class."""
17import math
19import numpy as np
21from tensorflow.python.framework import constant_op
22from tensorflow.python.framework import dtypes
23from tensorflow.python.framework import ops
24from tensorflow.python.framework import tensor_shape
25from tensorflow.python.ops import array_ops
26from tensorflow.python.ops import check_ops
27from tensorflow.python.ops import math_ops
28from tensorflow.python.ops import nn
29from tensorflow.python.ops import random_ops
30from tensorflow.python.ops.distributions import distribution
31from tensorflow.python.ops.distributions import special_math
32from tensorflow.python.util import deprecation
33from tensorflow.python.util.tf_export import tf_export
36__all__ = [
37 "Laplace",
38 "LaplaceWithSoftplusScale",
39]
42@tf_export(v1=["distributions.Laplace"])
43class Laplace(distribution.Distribution):
44 """The Laplace distribution with location `loc` and `scale` parameters.
46 #### Mathematical details
48 The probability density function (pdf) of this distribution is,
50 ```none
51 pdf(x; mu, sigma) = exp(-|x - mu| / sigma) / Z
52 Z = 2 sigma
53 ```
55 where `loc = mu`, `scale = sigma`, and `Z` is the normalization constant.
57 Note that the Laplace distribution can be thought of two exponential
58 distributions spliced together "back-to-back."
60 The Lpalce distribution is a member of the [location-scale family](
61 https://en.wikipedia.org/wiki/Location-scale_family), i.e., it can be
62 constructed as,
64 ```none
65 X ~ Laplace(loc=0, scale=1)
66 Y = loc + scale * X
67 ```
69 """
71 @deprecation.deprecated(
72 "2019-01-01",
73 "The TensorFlow Distributions library has moved to "
74 "TensorFlow Probability "
75 "(https://github.com/tensorflow/probability). You "
76 "should update all references to use `tfp.distributions` "
77 "instead of `tf.distributions`.",
78 warn_once=True)
79 def __init__(self,
80 loc,
81 scale,
82 validate_args=False,
83 allow_nan_stats=True,
84 name="Laplace"):
85 """Construct Laplace distribution with parameters `loc` and `scale`.
87 The parameters `loc` and `scale` must be shaped in a way that supports
88 broadcasting (e.g., `loc / scale` is a valid operation).
90 Args:
91 loc: Floating point tensor which characterizes the location (center)
92 of the distribution.
93 scale: Positive floating point tensor which characterizes the spread of
94 the distribution.
95 validate_args: Python `bool`, default `False`. When `True` distribution
96 parameters are checked for validity despite possibly degrading runtime
97 performance. When `False` invalid inputs may silently render incorrect
98 outputs.
99 allow_nan_stats: Python `bool`, default `True`. When `True`,
100 statistics (e.g., mean, mode, variance) use the value "`NaN`" to
101 indicate the result is undefined. When `False`, an exception is raised
102 if one or more of the statistic's batch members are undefined.
103 name: Python `str` name prefixed to Ops created by this class.
105 Raises:
106 TypeError: if `loc` and `scale` are of different dtype.
107 """
108 parameters = dict(locals())
109 with ops.name_scope(name, values=[loc, scale]) as name:
110 with ops.control_dependencies([check_ops.assert_positive(scale)] if
111 validate_args else []):
112 self._loc = array_ops.identity(loc, name="loc")
113 self._scale = array_ops.identity(scale, name="scale")
114 check_ops.assert_same_float_dtype([self._loc, self._scale])
115 super(Laplace, self).__init__(
116 dtype=self._loc.dtype,
117 reparameterization_type=distribution.FULLY_REPARAMETERIZED,
118 validate_args=validate_args,
119 allow_nan_stats=allow_nan_stats,
120 parameters=parameters,
121 graph_parents=[self._loc, self._scale],
122 name=name)
124 @staticmethod
125 def _param_shapes(sample_shape):
126 return dict(
127 zip(("loc", "scale"), ([ops.convert_to_tensor(
128 sample_shape, dtype=dtypes.int32)] * 2)))
130 @property
131 def loc(self):
132 """Distribution parameter for the location."""
133 return self._loc
135 @property
136 def scale(self):
137 """Distribution parameter for scale."""
138 return self._scale
140 def _batch_shape_tensor(self):
141 return array_ops.broadcast_dynamic_shape(
142 array_ops.shape(self.loc), array_ops.shape(self.scale))
144 def _batch_shape(self):
145 return array_ops.broadcast_static_shape(
146 self.loc.get_shape(), self.scale.get_shape())
148 def _event_shape_tensor(self):
149 return constant_op.constant([], dtype=dtypes.int32)
151 def _event_shape(self):
152 return tensor_shape.TensorShape([])
154 def _sample_n(self, n, seed=None):
155 shape = array_ops.concat([[n], self.batch_shape_tensor()], 0)
156 # Uniform variates must be sampled from the open-interval `(-1, 1)` rather
157 # than `[-1, 1)`. In the case of `(0, 1)` we'd use
158 # `np.finfo(self.dtype.as_numpy_dtype).tiny` because it is the smallest,
159 # positive, "normal" number. However, the concept of subnormality exists
160 # only at zero; here we need the smallest usable number larger than -1,
161 # i.e., `-1 + eps/2`.
162 uniform_samples = random_ops.random_uniform(
163 shape=shape,
164 minval=np.nextafter(self.dtype.as_numpy_dtype(-1.),
165 self.dtype.as_numpy_dtype(0.)),
166 maxval=1.,
167 dtype=self.dtype,
168 seed=seed)
169 return (self.loc - self.scale * math_ops.sign(uniform_samples) *
170 math_ops.log1p(-math_ops.abs(uniform_samples)))
172 def _log_prob(self, x):
173 return self._log_unnormalized_prob(x) - self._log_normalization()
175 def _prob(self, x):
176 return math_ops.exp(self._log_prob(x))
178 def _log_cdf(self, x):
179 return special_math.log_cdf_laplace(self._z(x))
181 def _log_survival_function(self, x):
182 return special_math.log_cdf_laplace(-self._z(x))
184 def _cdf(self, x):
185 z = self._z(x)
186 return (0.5 + 0.5 * math_ops.sign(z) *
187 (1. - math_ops.exp(-math_ops.abs(z))))
189 def _log_unnormalized_prob(self, x):
190 return -math_ops.abs(self._z(x))
192 def _log_normalization(self):
193 return math.log(2.) + math_ops.log(self.scale)
195 def _entropy(self):
196 # Use broadcasting rules to calculate the full broadcast scale.
197 scale = self.scale + array_ops.zeros_like(self.loc)
198 return math.log(2.) + 1. + math_ops.log(scale)
200 def _mean(self):
201 return self.loc + array_ops.zeros_like(self.scale)
203 def _stddev(self):
204 return math.sqrt(2.) * self.scale + array_ops.zeros_like(self.loc)
206 def _median(self):
207 return self._mean()
209 def _mode(self):
210 return self._mean()
212 def _z(self, x):
213 return (x - self.loc) / self.scale
216class LaplaceWithSoftplusScale(Laplace):
217 """Laplace with softplus applied to `scale`."""
219 @deprecation.deprecated(
220 "2019-01-01",
221 "Use `tfd.Laplace(loc, tf.nn.softplus(scale)) "
222 "instead.",
223 warn_once=True)
224 def __init__(self,
225 loc,
226 scale,
227 validate_args=False,
228 allow_nan_stats=True,
229 name="LaplaceWithSoftplusScale"):
230 parameters = dict(locals())
231 with ops.name_scope(name, values=[loc, scale]) as name:
232 super(LaplaceWithSoftplusScale, self).__init__(
233 loc=loc,
234 scale=nn.softplus(scale, name="softplus_scale"),
235 validate_args=validate_args,
236 allow_nan_stats=allow_nan_stats,
237 name=name)
238 self._parameters = parameters