1# Copyright 2015 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"""Tests for Uniform distribution.""" 16 17from __future__ import absolute_import 18from __future__ import division 19from __future__ import print_function 20 21import importlib 22 23import numpy as np 24 25from tensorflow.python.eager import backprop 26from tensorflow.python.framework import constant_op 27from tensorflow.python.framework import errors 28from tensorflow.python.framework import tensor_shape 29from tensorflow.python.framework import test_util 30from tensorflow.python.ops import array_ops 31from tensorflow.python.ops import math_ops 32from tensorflow.python.ops.distributions import uniform as uniform_lib 33from tensorflow.python.platform import test 34from tensorflow.python.platform import tf_logging 35 36 37def try_import(name): # pylint: disable=invalid-name 38 module = None 39 try: 40 module = importlib.import_module(name) 41 except ImportError as e: 42 tf_logging.warning("Could not import %s: %s" % (name, str(e))) 43 return module 44 45 46stats = try_import("scipy.stats") 47 48 49class UniformTest(test.TestCase): 50 51 @test_util.run_in_graph_and_eager_modes 52 def testUniformRange(self): 53 a = 3.0 54 b = 10.0 55 uniform = uniform_lib.Uniform(low=a, high=b) 56 self.assertAllClose(a, self.evaluate(uniform.low)) 57 self.assertAllClose(b, self.evaluate(uniform.high)) 58 self.assertAllClose(b - a, self.evaluate(uniform.range())) 59 60 @test_util.run_in_graph_and_eager_modes 61 def testUniformPDF(self): 62 a = constant_op.constant([-3.0] * 5 + [15.0]) 63 b = constant_op.constant([11.0] * 5 + [20.0]) 64 uniform = uniform_lib.Uniform(low=a, high=b) 65 66 a_v = -3.0 67 b_v = 11.0 68 x = np.array([-10.5, 4.0, 0.0, 10.99, 11.3, 17.0], dtype=np.float32) 69 70 def _expected_pdf(): 71 pdf = np.zeros_like(x) + 1.0 / (b_v - a_v) 72 pdf[x > b_v] = 0.0 73 pdf[x < a_v] = 0.0 74 pdf[5] = 1.0 / (20.0 - 15.0) 75 return pdf 76 77 expected_pdf = _expected_pdf() 78 79 pdf = uniform.prob(x) 80 self.assertAllClose(expected_pdf, self.evaluate(pdf)) 81 82 log_pdf = uniform.log_prob(x) 83 self.assertAllClose(np.log(expected_pdf), self.evaluate(log_pdf)) 84 85 @test_util.run_in_graph_and_eager_modes 86 def testUniformShape(self): 87 a = constant_op.constant([-3.0] * 5) 88 b = constant_op.constant(11.0) 89 uniform = uniform_lib.Uniform(low=a, high=b) 90 91 self.assertEqual(self.evaluate(uniform.batch_shape_tensor()), (5,)) 92 self.assertEqual(uniform.batch_shape, tensor_shape.TensorShape([5])) 93 self.assertAllEqual(self.evaluate(uniform.event_shape_tensor()), []) 94 self.assertEqual(uniform.event_shape, tensor_shape.TensorShape([])) 95 96 @test_util.run_in_graph_and_eager_modes 97 def testUniformPDFWithScalarEndpoint(self): 98 a = constant_op.constant([0.0, 5.0]) 99 b = constant_op.constant(10.0) 100 uniform = uniform_lib.Uniform(low=a, high=b) 101 102 x = np.array([0.0, 8.0], dtype=np.float32) 103 expected_pdf = np.array([1.0 / (10.0 - 0.0), 1.0 / (10.0 - 5.0)]) 104 105 pdf = uniform.prob(x) 106 self.assertAllClose(expected_pdf, self.evaluate(pdf)) 107 108 @test_util.run_in_graph_and_eager_modes 109 def testUniformCDF(self): 110 batch_size = 6 111 a = constant_op.constant([1.0] * batch_size) 112 b = constant_op.constant([11.0] * batch_size) 113 a_v = 1.0 114 b_v = 11.0 115 x = np.array([-2.5, 2.5, 4.0, 0.0, 10.99, 12.0], dtype=np.float32) 116 117 uniform = uniform_lib.Uniform(low=a, high=b) 118 119 def _expected_cdf(): 120 cdf = (x - a_v) / (b_v - a_v) 121 cdf[x >= b_v] = 1 122 cdf[x < a_v] = 0 123 return cdf 124 125 cdf = uniform.cdf(x) 126 self.assertAllClose(_expected_cdf(), self.evaluate(cdf)) 127 128 log_cdf = uniform.log_cdf(x) 129 self.assertAllClose(np.log(_expected_cdf()), self.evaluate(log_cdf)) 130 131 @test_util.run_in_graph_and_eager_modes 132 def testUniformEntropy(self): 133 a_v = np.array([1.0, 1.0, 1.0]) 134 b_v = np.array([[1.5, 2.0, 3.0]]) 135 uniform = uniform_lib.Uniform(low=a_v, high=b_v) 136 137 expected_entropy = np.log(b_v - a_v) 138 self.assertAllClose(expected_entropy, self.evaluate(uniform.entropy())) 139 140 @test_util.run_in_graph_and_eager_modes 141 def testUniformAssertMaxGtMin(self): 142 a_v = np.array([1.0, 1.0, 1.0], dtype=np.float32) 143 b_v = np.array([1.0, 2.0, 3.0], dtype=np.float32) 144 145 with self.assertRaisesWithPredicateMatch(errors.InvalidArgumentError, 146 "x < y"): 147 uniform = uniform_lib.Uniform(low=a_v, high=b_v, validate_args=True) 148 self.evaluate(uniform.low) 149 150 @test_util.run_in_graph_and_eager_modes 151 def testUniformSample(self): 152 a = constant_op.constant([3.0, 4.0]) 153 b = constant_op.constant(13.0) 154 a1_v = 3.0 155 a2_v = 4.0 156 b_v = 13.0 157 n = constant_op.constant(100000) 158 uniform = uniform_lib.Uniform(low=a, high=b) 159 160 samples = uniform.sample(n, seed=137) 161 sample_values = self.evaluate(samples) 162 self.assertEqual(sample_values.shape, (100000, 2)) 163 self.assertAllClose( 164 sample_values[::, 0].mean(), (b_v + a1_v) / 2, atol=1e-1, rtol=0.) 165 self.assertAllClose( 166 sample_values[::, 1].mean(), (b_v + a2_v) / 2, atol=1e-1, rtol=0.) 167 self.assertFalse( 168 np.any(sample_values[::, 0] < a1_v) or np.any(sample_values >= b_v)) 169 self.assertFalse( 170 np.any(sample_values[::, 1] < a2_v) or np.any(sample_values >= b_v)) 171 172 @test_util.run_in_graph_and_eager_modes 173 def _testUniformSampleMultiDimensional(self): 174 # DISABLED: Please enable this test once b/issues/30149644 is resolved. 175 batch_size = 2 176 a_v = [3.0, 22.0] 177 b_v = [13.0, 35.0] 178 a = constant_op.constant([a_v] * batch_size) 179 b = constant_op.constant([b_v] * batch_size) 180 181 uniform = uniform_lib.Uniform(low=a, high=b) 182 183 n_v = 100000 184 n = constant_op.constant(n_v) 185 samples = uniform.sample(n) 186 self.assertEqual(samples.get_shape(), (n_v, batch_size, 2)) 187 188 sample_values = self.evaluate(samples) 189 190 self.assertFalse( 191 np.any(sample_values[:, 0, 0] < a_v[0]) or 192 np.any(sample_values[:, 0, 0] >= b_v[0])) 193 self.assertFalse( 194 np.any(sample_values[:, 0, 1] < a_v[1]) or 195 np.any(sample_values[:, 0, 1] >= b_v[1])) 196 197 self.assertAllClose( 198 sample_values[:, 0, 0].mean(), (a_v[0] + b_v[0]) / 2, atol=1e-2) 199 self.assertAllClose( 200 sample_values[:, 0, 1].mean(), (a_v[1] + b_v[1]) / 2, atol=1e-2) 201 202 @test_util.run_in_graph_and_eager_modes 203 def testUniformMean(self): 204 a = 10.0 205 b = 100.0 206 uniform = uniform_lib.Uniform(low=a, high=b) 207 if not stats: 208 return 209 s_uniform = stats.uniform(loc=a, scale=b - a) 210 self.assertAllClose(self.evaluate(uniform.mean()), s_uniform.mean()) 211 212 @test_util.run_in_graph_and_eager_modes 213 def testUniformVariance(self): 214 a = 10.0 215 b = 100.0 216 uniform = uniform_lib.Uniform(low=a, high=b) 217 if not stats: 218 return 219 s_uniform = stats.uniform(loc=a, scale=b - a) 220 self.assertAllClose(self.evaluate(uniform.variance()), s_uniform.var()) 221 222 @test_util.run_in_graph_and_eager_modes 223 def testUniformStd(self): 224 a = 10.0 225 b = 100.0 226 uniform = uniform_lib.Uniform(low=a, high=b) 227 if not stats: 228 return 229 s_uniform = stats.uniform(loc=a, scale=b - a) 230 self.assertAllClose(self.evaluate(uniform.stddev()), s_uniform.std()) 231 232 @test_util.run_in_graph_and_eager_modes 233 def testUniformNans(self): 234 a = 10.0 235 b = [11.0, 100.0] 236 uniform = uniform_lib.Uniform(low=a, high=b) 237 238 no_nans = constant_op.constant(1.0) 239 nans = constant_op.constant(0.0) / constant_op.constant(0.0) 240 self.assertTrue(self.evaluate(math_ops.is_nan(nans))) 241 with_nans = array_ops.stack([no_nans, nans]) 242 243 pdf = uniform.prob(with_nans) 244 245 is_nan = self.evaluate(math_ops.is_nan(pdf)) 246 self.assertFalse(is_nan[0]) 247 self.assertTrue(is_nan[1]) 248 249 @test_util.run_in_graph_and_eager_modes 250 def testUniformSamplePdf(self): 251 a = 10.0 252 b = [11.0, 100.0] 253 uniform = uniform_lib.Uniform(a, b) 254 self.assertTrue( 255 self.evaluate( 256 math_ops.reduce_all(uniform.prob(uniform.sample(10)) > 0))) 257 258 @test_util.run_in_graph_and_eager_modes 259 def testUniformBroadcasting(self): 260 a = 10.0 261 b = [11.0, 20.0] 262 uniform = uniform_lib.Uniform(a, b) 263 264 pdf = uniform.prob([[10.5, 11.5], [9.0, 19.0], [10.5, 21.0]]) 265 expected_pdf = np.array([[1.0, 0.1], [0.0, 0.1], [1.0, 0.0]]) 266 self.assertAllClose(expected_pdf, self.evaluate(pdf)) 267 268 @test_util.run_in_graph_and_eager_modes 269 def testUniformSampleWithShape(self): 270 a = 10.0 271 b = [11.0, 20.0] 272 uniform = uniform_lib.Uniform(a, b) 273 274 pdf = uniform.prob(uniform.sample((2, 3))) 275 # pylint: disable=bad-continuation 276 expected_pdf = [ 277 [[1.0, 0.1], [1.0, 0.1], [1.0, 0.1]], 278 [[1.0, 0.1], [1.0, 0.1], [1.0, 0.1]], 279 ] 280 # pylint: enable=bad-continuation 281 self.assertAllClose(expected_pdf, self.evaluate(pdf)) 282 283 pdf = uniform.prob(uniform.sample()) 284 expected_pdf = [1.0, 0.1] 285 self.assertAllClose(expected_pdf, self.evaluate(pdf)) 286 287 def testFullyReparameterized(self): 288 a = constant_op.constant(0.1) 289 b = constant_op.constant(0.8) 290 with backprop.GradientTape() as tape: 291 tape.watch(a) 292 tape.watch(b) 293 uniform = uniform_lib.Uniform(a, b) 294 samples = uniform.sample(100) 295 grad_a, grad_b = tape.gradient(samples, [a, b]) 296 self.assertIsNotNone(grad_a) 297 self.assertIsNotNone(grad_b) 298 299 # Eager doesn't pass due to a type mismatch in one of the ops. 300 def testUniformFloat64(self): 301 uniform = uniform_lib.Uniform( 302 low=np.float64(0.), high=np.float64(1.)) 303 304 self.assertAllClose( 305 [1., 1.], 306 self.evaluate(uniform.prob(np.array([0.5, 0.6], dtype=np.float64)))) 307 308 self.assertAllClose( 309 [0.5, 0.6], 310 self.evaluate(uniform.cdf(np.array([0.5, 0.6], dtype=np.float64)))) 311 312 self.assertAllClose(0.5, self.evaluate(uniform.mean())) 313 self.assertAllClose(1 / 12., self.evaluate(uniform.variance())) 314 self.assertAllClose(0., self.evaluate(uniform.entropy())) 315 316 317if __name__ == "__main__": 318 test.main() 319