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 16 from __future__ import absolute_import 17 from __future__ import division 18 from __future__ import print_function 19 20 import numpy as np 21 from scipy import stats 22 from tensorflow.contrib.distributions.python.ops import inverse_gamma 23 from tensorflow.python.client import session 24 from tensorflow.python.framework import constant_op 25 from tensorflow.python.framework import tensor_shape 26 from tensorflow.python.ops import nn_ops 27 from tensorflow.python.platform import test 28 29 30 class InverseGammaTest(test.TestCase): 31 32 def testInverseGammaShape(self): 33 with self.test_session(): 34 alpha = constant_op.constant([3.0] * 5) 35 beta = constant_op.constant(11.0) 36 inv_gamma = inverse_gamma.InverseGamma(concentration=alpha, rate=beta) 37 38 self.assertEqual(inv_gamma.batch_shape_tensor().eval(), (5,)) 39 self.assertEqual(inv_gamma.batch_shape, 40 tensor_shape.TensorShape([5])) 41 self.assertAllEqual(inv_gamma.event_shape_tensor().eval(), []) 42 self.assertEqual(inv_gamma.event_shape, tensor_shape.TensorShape( 43 [])) 44 45 def testInverseGammaLogPDF(self): 46 with self.test_session(): 47 batch_size = 6 48 alpha = constant_op.constant([2.0] * batch_size) 49 beta = constant_op.constant([3.0] * batch_size) 50 alpha_v = 2.0 51 beta_v = 3.0 52 x = np.array([2.5, 2.5, 4.0, 0.1, 1.0, 2.0], dtype=np.float32) 53 inv_gamma = inverse_gamma.InverseGamma(concentration=alpha, rate=beta) 54 expected_log_pdf = stats.invgamma.logpdf(x, alpha_v, scale=beta_v) 55 log_pdf = inv_gamma.log_prob(x) 56 self.assertEqual(log_pdf.get_shape(), (6,)) 57 self.assertAllClose(log_pdf.eval(), expected_log_pdf) 58 59 pdf = inv_gamma.prob(x) 60 self.assertEqual(pdf.get_shape(), (6,)) 61 self.assertAllClose(pdf.eval(), np.exp(expected_log_pdf)) 62 63 def testInverseGammaLogPDFMultidimensional(self): 64 with self.test_session(): 65 batch_size = 6 66 alpha = constant_op.constant([[2.0, 4.0]] * batch_size) 67 beta = constant_op.constant([[3.0, 4.0]] * batch_size) 68 alpha_v = np.array([2.0, 4.0]) 69 beta_v = np.array([3.0, 4.0]) 70 x = np.array([[2.5, 2.5, 4.0, 0.1, 1.0, 2.0]], dtype=np.float32).T 71 inv_gamma = inverse_gamma.InverseGamma(concentration=alpha, rate=beta) 72 expected_log_pdf = stats.invgamma.logpdf(x, alpha_v, scale=beta_v) 73 log_pdf = inv_gamma.log_prob(x) 74 log_pdf_values = log_pdf.eval() 75 self.assertEqual(log_pdf.get_shape(), (6, 2)) 76 self.assertAllClose(log_pdf_values, expected_log_pdf) 77 78 pdf = inv_gamma.prob(x) 79 pdf_values = pdf.eval() 80 self.assertEqual(pdf.get_shape(), (6, 2)) 81 self.assertAllClose(pdf_values, np.exp(expected_log_pdf)) 82 83 def testInverseGammaLogPDFMultidimensionalBroadcasting(self): 84 with self.test_session(): 85 batch_size = 6 86 alpha = constant_op.constant([[2.0, 4.0]] * batch_size) 87 beta = constant_op.constant(3.0) 88 alpha_v = np.array([2.0, 4.0]) 89 beta_v = 3.0 90 x = np.array([[2.5, 2.5, 4.0, 0.1, 1.0, 2.0]], dtype=np.float32).T 91 inv_gamma = inverse_gamma.InverseGamma(concentration=alpha, rate=beta) 92 expected_log_pdf = stats.invgamma.logpdf(x, alpha_v, scale=beta_v) 93 log_pdf = inv_gamma.log_prob(x) 94 log_pdf_values = log_pdf.eval() 95 self.assertEqual(log_pdf.get_shape(), (6, 2)) 96 self.assertAllClose(log_pdf_values, expected_log_pdf) 97 98 pdf = inv_gamma.prob(x) 99 pdf_values = pdf.eval() 100 self.assertEqual(pdf.get_shape(), (6, 2)) 101 self.assertAllClose(pdf_values, np.exp(expected_log_pdf)) 102 103 def testInverseGammaCDF(self): 104 with self.test_session(): 105 batch_size = 6 106 alpha_v = 2.0 107 beta_v = 3.0 108 alpha = constant_op.constant([alpha_v] * batch_size) 109 beta = constant_op.constant([beta_v] * batch_size) 110 x = np.array([2.5, 2.5, 4.0, 0.1, 1.0, 2.0], dtype=np.float32) 111 112 inv_gamma = inverse_gamma.InverseGamma(concentration=alpha, rate=beta) 113 expected_cdf = stats.invgamma.cdf(x, alpha_v, scale=beta_v) 114 115 cdf = inv_gamma.cdf(x) 116 self.assertEqual(cdf.get_shape(), (batch_size,)) 117 self.assertAllClose(cdf.eval(), expected_cdf) 118 119 def testInverseGammaMode(self): 120 with self.test_session(): 121 alpha_v = np.array([5.5, 3.0, 2.5]) 122 beta_v = np.array([1.0, 4.0, 5.0]) 123 inv_gamma = inverse_gamma.InverseGamma(concentration=alpha_v, rate=beta_v) 124 expected_modes = beta_v / (alpha_v + 1) 125 self.assertEqual(inv_gamma.mode().get_shape(), (3,)) 126 self.assertAllClose(inv_gamma.mode().eval(), expected_modes) 127 128 def testInverseGammaMeanAllDefined(self): 129 with self.test_session(): 130 alpha_v = np.array([5.5, 3.0, 2.5]) 131 beta_v = np.array([1.0, 4.0, 5.0]) 132 inv_gamma = inverse_gamma.InverseGamma(concentration=alpha_v, rate=beta_v) 133 expected_means = stats.invgamma.mean(alpha_v, scale=beta_v) 134 self.assertEqual(inv_gamma.mean().get_shape(), (3,)) 135 self.assertAllClose(inv_gamma.mean().eval(), expected_means) 136 137 def testInverseGammaMeanAllowNanStats(self): 138 with self.test_session(): 139 # Mean will not be defined for the first entry. 140 alpha_v = np.array([1.0, 3.0, 2.5]) 141 beta_v = np.array([1.0, 4.0, 5.0]) 142 inv_gamma = inverse_gamma.InverseGamma( 143 concentration=alpha_v, rate=beta_v, allow_nan_stats=False) 144 with self.assertRaisesOpError("x < y"): 145 inv_gamma.mean().eval() 146 147 def testInverseGammaMeanNanStats(self): 148 with self.test_session(): 149 # Mode will not be defined for the first two entries. 150 alpha_v = np.array([0.5, 1.0, 3.0, 2.5]) 151 beta_v = np.array([1.0, 2.0, 4.0, 5.0]) 152 inv_gamma = inverse_gamma.InverseGamma( 153 concentration=alpha_v, rate=beta_v, allow_nan_stats=True) 154 expected_means = beta_v / (alpha_v - 1) 155 expected_means[0] = np.nan 156 expected_means[1] = np.nan 157 self.assertEqual(inv_gamma.mean().get_shape(), (4,)) 158 self.assertAllClose(inv_gamma.mean().eval(), expected_means) 159 160 def testInverseGammaVarianceAllDefined(self): 161 with self.test_session(): 162 alpha_v = np.array([7.0, 3.0, 2.5]) 163 beta_v = np.array([1.0, 4.0, 5.0]) 164 inv_gamma = inverse_gamma.InverseGamma(concentration=alpha_v, rate=beta_v) 165 expected_variances = stats.invgamma.var(alpha_v, scale=beta_v) 166 self.assertEqual(inv_gamma.variance().get_shape(), (3,)) 167 self.assertAllClose(inv_gamma.variance().eval(), expected_variances) 168 169 def testInverseGammaVarianceAllowNanStats(self): 170 with self.test_session(): 171 alpha_v = np.array([1.5, 3.0, 2.5]) 172 beta_v = np.array([1.0, 4.0, 5.0]) 173 inv_gamma = inverse_gamma.InverseGamma( 174 concentration=alpha_v, rate=beta_v, allow_nan_stats=False) 175 with self.assertRaisesOpError("x < y"): 176 inv_gamma.variance().eval() 177 178 def testInverseGammaVarianceNanStats(self): 179 with self.test_session(): 180 alpha_v = np.array([1.5, 3.0, 2.5]) 181 beta_v = np.array([1.0, 4.0, 5.0]) 182 inv_gamma = inverse_gamma.InverseGamma( 183 concentration=alpha_v, rate=beta_v, allow_nan_stats=True) 184 expected_variances = stats.invgamma.var(alpha_v, scale=beta_v) 185 expected_variances[0] = np.nan 186 self.assertEqual(inv_gamma.variance().get_shape(), (3,)) 187 self.assertAllClose(inv_gamma.variance().eval(), expected_variances) 188 189 def testInverseGammaEntropy(self): 190 with self.test_session(): 191 alpha_v = np.array([1.0, 3.0, 2.5]) 192 beta_v = np.array([1.0, 4.0, 5.0]) 193 expected_entropy = stats.invgamma.entropy(alpha_v, scale=beta_v) 194 inv_gamma = inverse_gamma.InverseGamma(concentration=alpha_v, rate=beta_v) 195 self.assertEqual(inv_gamma.entropy().get_shape(), (3,)) 196 self.assertAllClose(inv_gamma.entropy().eval(), expected_entropy) 197 198 def testInverseGammaSample(self): 199 with session.Session(): 200 alpha_v = 4.0 201 beta_v = 3.0 202 alpha = constant_op.constant(alpha_v) 203 beta = constant_op.constant(beta_v) 204 n = 100000 205 inv_gamma = inverse_gamma.InverseGamma(concentration=alpha, rate=beta) 206 samples = inv_gamma.sample(n, seed=137) 207 sample_values = samples.eval() 208 self.assertEqual(samples.get_shape(), (n,)) 209 self.assertEqual(sample_values.shape, (n,)) 210 self.assertAllClose( 211 sample_values.mean(), 212 stats.invgamma.mean( 213 alpha_v, scale=beta_v), 214 atol=.0025) 215 self.assertAllClose( 216 sample_values.var(), 217 stats.invgamma.var(alpha_v, scale=beta_v), 218 atol=.15) 219 self.assertTrue(self._kstest(alpha_v, beta_v, sample_values)) 220 221 def testInverseGammaSampleMultiDimensional(self): 222 with session.Session(): 223 alpha_v = np.array([np.arange(3, 103, dtype=np.float32)]) # 1 x 100 224 beta_v = np.array([np.arange(1, 11, dtype=np.float32)]).T # 10 x 1 225 inv_gamma = inverse_gamma.InverseGamma(concentration=alpha_v, rate=beta_v) 226 n = 10000 227 samples = inv_gamma.sample(n, seed=137) 228 sample_values = samples.eval() 229 self.assertEqual(samples.get_shape(), (n, 10, 100)) 230 self.assertEqual(sample_values.shape, (n, 10, 100)) 231 zeros = np.zeros_like(alpha_v + beta_v) # 10 x 100 232 alpha_bc = alpha_v + zeros 233 beta_bc = beta_v + zeros 234 self.assertAllClose( 235 sample_values.mean(axis=0), 236 stats.invgamma.mean( 237 alpha_bc, scale=beta_bc), 238 atol=.25) 239 self.assertAllClose( 240 sample_values.var(axis=0), 241 stats.invgamma.var(alpha_bc, scale=beta_bc), 242 atol=4.5) 243 fails = 0 244 trials = 0 245 for ai, a in enumerate(np.reshape(alpha_v, [-1])): 246 for bi, b in enumerate(np.reshape(beta_v, [-1])): 247 s = sample_values[:, bi, ai] 248 trials += 1 249 fails += 0 if self._kstest(a, b, s) else 1 250 self.assertLess(fails, trials * 0.03) 251 252 def _kstest(self, alpha, beta, samples): 253 # Uses the Kolmogorov-Smirnov test for goodness of fit. 254 ks, _ = stats.kstest(samples, stats.invgamma(alpha, scale=beta).cdf) 255 # Return True when the test passes. 256 return ks < 0.02 257 258 def testInverseGammaPdfOfSampleMultiDims(self): 259 with session.Session() as sess: 260 inv_gamma = inverse_gamma.InverseGamma( 261 concentration=[7., 11.], 262 rate=[[5.], [6.]]) 263 num = 50000 264 samples = inv_gamma.sample(num, seed=137) 265 pdfs = inv_gamma.prob(samples) 266 sample_vals, pdf_vals = sess.run([samples, pdfs]) 267 self.assertEqual(samples.get_shape(), (num, 2, 2)) 268 self.assertEqual(pdfs.get_shape(), (num, 2, 2)) 269 self.assertAllClose( 270 stats.invgamma.mean( 271 [[7., 11.], [7., 11.]], scale=np.array([[5., 5.], [6., 6.]])), 272 sample_vals.mean(axis=0), 273 atol=.1) 274 self.assertAllClose( 275 stats.invgamma.var([[7., 11.], [7., 11.]], 276 scale=np.array([[5., 5.], [6., 6.]])), 277 sample_vals.var(axis=0), 278 atol=.1) 279 self._assertIntegral(sample_vals[:, 0, 0], pdf_vals[:, 0, 0], err=0.02) 280 self._assertIntegral(sample_vals[:, 0, 1], pdf_vals[:, 0, 1], err=0.02) 281 self._assertIntegral(sample_vals[:, 1, 0], pdf_vals[:, 1, 0], err=0.02) 282 self._assertIntegral(sample_vals[:, 1, 1], pdf_vals[:, 1, 1], err=0.02) 283 284 def _assertIntegral(self, sample_vals, pdf_vals, err=1e-3): 285 s_p = zip(sample_vals, pdf_vals) 286 prev = (0, 0) 287 total = 0 288 for k in sorted(s_p, key=lambda x: x[0]): 289 pair_pdf = (k[1] + prev[1]) / 2 290 total += (k[0] - prev[0]) * pair_pdf 291 prev = k 292 self.assertNear(1., total, err=err) 293 294 def testInverseGammaNonPositiveInitializationParamsRaises(self): 295 with self.test_session(): 296 alpha_v = constant_op.constant(0.0, name="alpha") 297 beta_v = constant_op.constant(1.0, name="beta") 298 inv_gamma = inverse_gamma.InverseGamma( 299 concentration=alpha_v, rate=beta_v, validate_args=True) 300 with self.assertRaisesOpError("alpha"): 301 inv_gamma.mean().eval() 302 alpha_v = constant_op.constant(1.0, name="alpha") 303 beta_v = constant_op.constant(0.0, name="beta") 304 inv_gamma = inverse_gamma.InverseGamma( 305 concentration=alpha_v, rate=beta_v, validate_args=True) 306 with self.assertRaisesOpError("beta"): 307 inv_gamma.mean().eval() 308 309 def testInverseGammaWithSoftplusConcentrationRate(self): 310 with self.test_session(): 311 alpha = constant_op.constant([-0.1, -2.9], name="alpha") 312 beta = constant_op.constant([1.0, -4.8], name="beta") 313 inv_gamma = inverse_gamma.InverseGammaWithSoftplusConcentrationRate( 314 concentration=alpha, rate=beta, validate_args=True) 315 self.assertAllClose(nn_ops.softplus(alpha).eval(), 316 inv_gamma.concentration.eval()) 317 self.assertAllClose(nn_ops.softplus(beta).eval(), 318 inv_gamma.rate.eval()) 319 320 321 if __name__ == "__main__": 322 test.main() 323