def testInvalidP(self): invalid_ps = [-.01, 0., -2.,] with self.assertRaisesOpError('`probs` has components less than 0.'): negbinom = tfd.NegativeBinomial(5., probs=invalid_ps, validate_args=True) self.evaluate(negbinom.sample(seed=test_util.test_seed())) invalid_ps = [1.01, 2., 1.001,] with self.assertRaisesOpError('`probs` has components greater than 1.'): negbinom = tfd.NegativeBinomial(5., probs=invalid_ps, validate_args=True) self.evaluate(negbinom.sample(seed=test_util.test_seed()))
def testInvalidNegativeCount(self): invalid_rs = [-3., 0., -2.,] with self.assertRaisesOpError( '`total_count` has components less than or equal to 0.'): negbinom = tfd.NegativeBinomial( total_count=invalid_rs, probs=0.1, validate_args=True) self.evaluate(negbinom.sample(seed=test_util.test_seed())) invalid_rs = [3., 2., 0.] with self.assertRaisesOpError( '`total_count` has components less than or equal to 0.'): negbinom = tfd.NegativeBinomial( total_count=invalid_rs, probs=0.1, validate_args=True) self.evaluate(negbinom.sample(seed=test_util.test_seed()))
def testAssertionsTotalCount(self): x = tf.Variable([-5., 3., -1.]) d = tfd.NegativeBinomial(total_count=x, probs=0.7, validate_args=True) self.evaluate(x.initializer) with self.assertRaisesOpError( '`total_count` has components less than or equal to 0.'): self.evaluate(d.sample(seed=test_util.test_seed())) x = tf.Variable([5., 3.7, 1.]) d = tfd.NegativeBinomial(total_count=x, probs=0.7, validate_args=True) self.evaluate(x.initializer) with self.assertRaisesOpError( '`total_count` has fractional components.'): self.evaluate(d.sample(seed=test_util.test_seed()))
def _as_distribution(self, r): total_count = DeferredTensor(self._total_count, lambda x: tf.cast(x, r.dtype), dtype=r.dtype) return tfd.NegativeBinomial( total_count=total_count, logits=DeferredTensor(r, lambda x: x - tf.math.log(total_count)))
def testNegativeBinomialStddev(self): total_count = 5. probs = np.array([.1, .3, .25], dtype=np.float32) negbinom = tfd.NegativeBinomial(total_count=total_count, probs=probs) expected_stds = stats.nbinom.std(n=total_count, p=1 - probs) self.assertEqual([3], negbinom.stddev().shape) self.assertAllClose(expected_stds, self.evaluate(negbinom.stddev()))
def new(params, event_shape=(), count_activation=tf.exp, validate_args=False, name="NegativeBinomialLayer", disp=None): r"""Create the distribution instance from a `params` vector.""" params = tf.convert_to_tensor(value=params, name='params') event_shape = dist_util.expand_to_vector( tf.convert_to_tensor(value=event_shape, name='event_shape', dtype=tf.int32), tensor_name='event_shape', ) output_shape = tf.concat( [tf.shape(input=params)[:-1], event_shape], axis=0, ) if disp is None: total_count, logits = tf.split(params, 2, axis=-1) logits = tf.reshape(logits, output_shape) else: total_count = params logits = disp total_count = tf.reshape(total_count, output_shape) total_count = count_activation(total_count) return tfd.Independent( tfd.NegativeBinomial(total_count=total_count, logits=logits, validate_args=validate_args), reinterpreted_batch_ndims=tf.size(input=event_shape), name=name, )
def testLogits(self): logits = [[0., 9., -0.5]] negbinom = tfd.NegativeBinomial( total_count=3., logits=logits, validate_args=True) self.assertEqual([1, 3], negbinom.probs_parameter().shape) self.assertEqual([1, 3], negbinom.logits.shape) self.assertAllClose(logits, self.evaluate(negbinom.logits))
def new(params, event_shape=(), given_log_count=True, validate_args=False, name=None): """Create the distribution instance from a `params` vector.""" from odin.bay.distributions import ZeroInflated with tf.compat.v1.name_scope(name, 'ZeroInflatedNegativeBinomial', [params, event_shape]): params = tf.convert_to_tensor(value=params, name='params') event_shape = dist_util.expand_to_vector(tf.convert_to_tensor( value=event_shape, name='event_shape', dtype=tf.int32), tensor_name='event_shape') output_shape = tf.concat([ tf.shape(input=params)[:-1], event_shape, ], axis=0) (total_count_params, logits_params, rate_params) = tf.split(params, 3, axis=-1) if given_log_count: total_count_params = tf.exp(total_count_params, name='total_count') nb = tfd.NegativeBinomial( total_count=tf.reshape(total_count_params, output_shape), logits=tf.reshape(logits_params, output_shape), validate_args=validate_args) zinb = ZeroInflated(count_distribution=nb, logits=tf.reshape(rate_params, output_shape), validate_args=validate_args) return tfd.Independent( zinb, reinterpreted_batch_ndims=tf.size(input=event_shape), validate_args=validate_args)
def testNegativeBinomialSample(self): probs = [.3, .9] total_count = [4., 11.] n = int(100e3) negbinom = tfd.NegativeBinomial(total_count=total_count, probs=probs, validate_args=True) samples = negbinom.sample(n, seed=test_util.test_seed()) self.assertEqual([n, 2], samples.shape) sample_mean = tf.reduce_mean(samples, axis=0) sample_var = tf.reduce_mean( (samples - sample_mean[tf.newaxis, ...])**2., axis=0) sample_min = tf.reduce_min(samples) [sample_mean_, sample_var_, sample_min_] = self.evaluate([sample_mean, sample_var, sample_min]) self.assertAllEqual(np.ones(sample_min_.shape, dtype=np.bool), sample_min_ >= 0.0) for i in range(2): self.assertAllClose(sample_mean_[i], stats.nbinom.mean(total_count[i], 1 - probs[i]), atol=0., rtol=.02) self.assertAllClose(sample_var_[i], stats.nbinom.var(total_count[i], 1 - probs[i]), atol=0., rtol=.02)
def testAssertionProbsGreaterThanOne(self): x = tf.Variable([0.1, 1.07, 0.0]) d = tfd.NegativeBinomial(total_count=8., probs=x, validate_args=True) self.evaluate(x.initializer) with self.assertRaisesOpError( '`probs` has components greater than 1.'): self.evaluate(d.sample(seed=test_util.test_seed()))
def testNegativeBinomialVariance(self): total_count = 5. probs = np.array([.1, .3, .25], dtype=np.float32) negbinom = tfd.NegativeBinomial( total_count=total_count, probs=probs, validate_args=True) expected_vars = stats.nbinom.var(n=total_count, p=1 - probs) self.assertEqual([3], negbinom.variance().shape) self.assertAllClose(expected_vars, self.evaluate(negbinom.variance()))
def testZeroP(self): prob = 0. negbinom = tfd.NegativeBinomial( total_count=3., probs=prob, validate_args=True) self.assertAllClose(prob, self.evaluate(negbinom.probs)) self.assertAllClose(0., negbinom.prob(3)) self.assertAllClose(1., negbinom.prob(0)) self.assertAllClose(0., negbinom.log_prob(0))
def testNegativeBinomialLogCdfValidateArgs(self): batch_size = 6 probs = [.9] * batch_size total_count = 5. with self.assertRaisesOpError('Condition x >= 0'): negbinom = tfd.NegativeBinomial( total_count=total_count, probs=probs, validate_args=True) self.evaluate(negbinom.log_cdf(-1.))
def testLogProbUnderflow(self): logits = np.float32([-90, -100, -110]) total_count = np.float32(1.) x = np.float32(0.) nb = tfd.NegativeBinomial(total_count=total_count, logits=logits) log_prob_ = self.evaluate(nb.log_prob(x)) self.assertAllEqual(np.ones_like(log_prob_, dtype=np.bool), np.isfinite(log_prob_))
def testLogProbOverflow(self): logits = np.float32([20., 30., 40.]) total_count = np.float32(1.) x = np.float32(0.) nb = tfd.NegativeBinomial( total_count=total_count, logits=logits, validate_args=True) log_prob_ = self.evaluate(nb.log_prob(x)) self.assertAllEqual( np.ones_like(log_prob_, dtype=np.bool), np.isfinite(log_prob_))
def testNegativeBinomialShape(self): probs = [.1] * 5 total_count = [2.0] * 5 negbinom = tfd.NegativeBinomial(total_count=total_count, probs=probs) self.assertEqual([5], self.evaluate(negbinom.batch_shape_tensor())) self.assertEqual(tf.TensorShape([5]), negbinom.batch_shape) self.assertAllEqual([], self.evaluate(negbinom.event_shape_tensor())) self.assertEqual(tf.TensorShape([]), negbinom.event_shape)
def setUp(self): super(NegativeBinomialSoftplusTest, self).setUp() self.dtype = np.float32 n = 2.1 self.model = tfp.glm.NegativeBinomialSoftplus(n) self.expected = tfp.glm.CustomExponentialFamily( lambda mean: tfd.NegativeBinomial( # pylint: disable=g-long-lambda total_count=n, logits=tf.math.log(mean) - tf.math.log(n)), tf.math.softplus)
def testNegativeBinomialShapeBroadcast(self): probs = [[.1, .2, .3]] * 5 total_count = [[2.]] * 5 negbinom = tfd.NegativeBinomial( total_count=total_count, probs=probs, validate_args=True) self.assertAllEqual([5, 3], self.evaluate(negbinom.batch_shape_tensor())) self.assertAllEqual(tf.TensorShape([5, 3]), negbinom.batch_shape) self.assertAllEqual([], self.evaluate(negbinom.event_shape_tensor())) self.assertAllEqual(tf.TensorShape([]), negbinom.event_shape)
def _as_distribution(self, r): total_count = DeferredTensor(self._total_count, lambda x: tf.cast(x, r.dtype), dtype=r.dtype) return tfd.NegativeBinomial( total_count=total_count, logits=DeferredTensor( r, lambda x: tf.math.log( # pylint: disable=g-long-lambda tf.math.softplus(x)) - tf.math.log(total_count)))
def testParamTensorFromProbs(self): x = tf.constant([0.1, 0.5, 0.4]) d = tfd.NegativeBinomial(total_count=1, probs=x, validate_args=True) logit = lambda x: tf.math.log(x) - tf.math.log1p(-x) self.assertAllClose( *self.evaluate([-logit(d.prob(0.)), d.logits_parameter()]), atol=1e-5, rtol=1e-4) self.assertAllClose( *self.evaluate([1. - d.prob(0.), d.probs_parameter()]), atol=0, rtol=1e-4)
def testNegativeBinomialLogPmfValidateArgs(self): batch_size = 6 probs = [.9] * batch_size total_count = 5. x = tf1.placeholder_with_default([2.5, 3.2, 4.3, 5.1, 6., 7.], shape=[6]) negbinom = tfd.NegativeBinomial( total_count=total_count, probs=probs, validate_args=True) with self.assertRaisesOpError('cannot contain fractional components'): self.evaluate(negbinom.log_prob(x)) with self.assertRaisesOpError('Condition x >= 0'): self.evaluate(negbinom.log_prob([-1.])) negbinom = tfd.NegativeBinomial( total_count=total_count, probs=probs, validate_args=False) log_pmf = negbinom.log_prob(x) self.assertEqual([6], log_pmf.shape) pmf = negbinom.prob(x) self.assertEqual([6], pmf.shape)
def testAssertionsProbsMutation(self): x = tf.Variable([0.1, 0.7, 0.0]) d = tfd.NegativeBinomial(total_count=8., probs=x, validate_args=True) self.evaluate(x.initializer) self.evaluate(d.sample(seed=test_util.test_seed())) with tf.control_dependencies([x.assign([0.1, -0.7, 0.0])]): with self.assertRaisesOpError('`probs` has components less than 0.'): self.evaluate(d.sample(seed=test_util.test_seed())) with tf.control_dependencies([x.assign([0.1, 1.02, 0.0])]): with self.assertRaisesOpError('`probs` has components greater than 1.'): self.evaluate(d.sample(seed=test_util.test_seed()))
def testAssertionsTotalCountMutation(self): x = tf.Variable([5., 3., 1.], dtype=tf.float32) d = tfd.NegativeBinomial(total_count=x, probs=0.7, validate_args=True) self.evaluate(x.initializer) self.evaluate(d.sample(seed=test_util.test_seed())) with tf.control_dependencies([x.assign([-5., 3., 1.])]): with self.assertRaisesOpError( '`total_count` has components less than or equal to 0.'): self.evaluate(d.sample(seed=test_util.test_seed())) with tf.control_dependencies([x.assign([5., 3.2, 1.])]): with self.assertRaisesOpError( '`total_count` has fractional components.'): self.evaluate(d.sample(seed=test_util.test_seed()))
def testNegativeBinomialLogPmf(self): batch_size = 6 probs = [.2] * batch_size probs_v = .2 total_count = 5. x = np.array([2., 3., 4., 5., 6., 7.], dtype=np.float32) negbinom = tfd.NegativeBinomial(total_count=total_count, probs=probs) expected_log_pmf = stats.nbinom.logpmf(x, n=total_count, p=1 - probs_v) log_pmf = negbinom.log_prob(x) self.assertEqual([6], log_pmf.shape) self.assertAllClose(expected_log_pmf, self.evaluate(log_pmf)) pmf = negbinom.prob(x) self.assertEqual([6], pmf.shape) self.assertAllClose(np.exp(expected_log_pmf), self.evaluate(pmf))
def testNegativeBinomialLogCdf(self): batch_size = 6 probs = [.2] * batch_size probs_v = .2 total_count = 5. x = np.array([2., 3., 4., 5., 6., 7.], dtype=np.float32) negbinom = tfd.NegativeBinomial( total_count=total_count, probs=probs, validate_args=True) expected_log_cdf = stats.nbinom.logcdf(x, n=total_count, p=1 - probs_v) log_cdf = negbinom.log_cdf(x) self.assertEqual([6], log_cdf.shape) self.assertAllClose(expected_log_cdf, self.evaluate(log_cdf)) cdf = negbinom.cdf(x) self.assertEqual([6], cdf.shape) self.assertAllClose(np.exp(expected_log_cdf), self.evaluate(cdf))
def testNegativeBinomialLogPmfMultidimensional(self): batch_size = 6 probs = tf.constant([[.2, .3, .5]] * batch_size) probs_v = np.array([.2, .3, .5]) total_count = 5. x = np.array([[2., 3., 4., 5., 6., 7.]], dtype=np.float32).T negbinom = tfd.NegativeBinomial(total_count=total_count, probs=probs) expected_log_pmf = stats.nbinom.logpmf(x, n=total_count, p=1 - probs_v) log_pmf = negbinom.log_prob(x) log_pmf_values = self.evaluate(log_pmf) self.assertEqual([6, 3], log_pmf.shape) self.assertAllClose(expected_log_pmf, log_pmf_values) pmf = negbinom.prob(x) pmf_values = self.evaluate(pmf) self.assertEqual([6, 3], pmf.shape) self.assertAllClose(np.exp(expected_log_pmf), pmf_values)
def new(params, event_shape=(), count_activation=tf.exp, validate_args=False, name="ZINegativeBinomialLayer", disp=None, rate=None): r"""Create the distribution instance from a `params` vector.""" params = tf.convert_to_tensor(value=params, name='params') event_shape = dist_util.expand_to_vector( tf.convert_to_tensor(value=event_shape, name='event_shape', dtype=tf.int32), tensor_name='event_shape', ) output_shape = tf.concat((tf.shape(input=params)[:-1], event_shape), axis=0) if disp is None: # full dispersion if rate is None: total_count, logits, rate = tf.split(params, 3, axis=-1) rate = tf.reshape(rate, output_shape) else: total_count, logits = tf.split(params, 2, axis=-1) logits = tf.reshape(logits, output_shape) else: # share dispersion if rate is None: total_count, rate = tf.split(params, 2, axis=-1) rate = tf.reshape(rate, output_shape) else: total_count = params logits = disp total_count = tf.reshape(total_count, output_shape) total_count = count_activation(total_count) nb = tfd.NegativeBinomial(total_count=total_count, logits=logits, validate_args=validate_args) zinb = ZeroInflated(count_distribution=nb, logits=rate, validate_args=validate_args) return tfd.Independent( zinb, reinterpreted_batch_ndims=tf.size(input=event_shape), name=name)
def new(params, event_shape=(), count_activation=tf.exp, dispersion='full', validate_args=False, name="ZINegativeBinomialLayer"): r"""Create the distribution instance from a `params` vector.""" params = tf.convert_to_tensor(value=params, name='params') event_shape = dist_util.expand_to_vector( tf.convert_to_tensor(value=event_shape, name='event_shape', dtype=tf.int32), tensor_name='event_shape', ) output_shape = tf.concat( [tf.shape(input=params)[:-1], event_shape], axis=0, ) ndims = output_shape.shape[0] (total_count_params, logits_params, rate_params) = tf.split(params, 3, axis=-1) if dispersion == 'single': logits_params = tf.reduce_mean(logits_params) elif dispersion == 'share': logits_params = tf.reduce_mean(logits_params, axis=tf.range(0, ndims - 1, dtype='int32'), keepdims=True) total_count_params = count_activation(total_count_params) nb = tfd.NegativeBinomial(total_count=tf.reshape(total_count_params, output_shape), logits=tf.reshape(logits_params, output_shape) if dispersion == 'full' else logits_params, validate_args=validate_args) zinb = ZeroInflated(count_distribution=nb, logits=tf.reshape(rate_params, output_shape), validate_args=validate_args) return tfd.Independent(zinb, reinterpreted_batch_ndims=tf.size(input=event_shape), name=name)
def testAssertionProbsLessThanZero(self): x = tf.Variable([-0.1, 0.7, 0.0]) d = tfd.NegativeBinomial(total_count=8., probs=x, validate_args=True) self.evaluate(x.initializer) with self.assertRaisesOpError('`probs` has components less than 0.'): self.evaluate(d.sample(seed=test_util.test_seed()))
def testGradientOfLogProbEvaluates(self): self.evaluate( tfp.math.value_and_gradient( tfd.NegativeBinomial(0.1, 0.).log_prob, [0.1]))