def _testLegalInputs(self, shift=None, scale_params=None, x=None): def _powerset(x): s = list(x) return itertools.chain.from_iterable( itertools.combinations(s, r) for r in range(len(s) + 1)) for args in _powerset(scale_params.items()): with self.test_session(): args = dict(args) scale_args = dict({"x": x}, **args) scale = self._makeScale(**scale_args) bijector_args = dict({"event_ndims": 1}, **args) # We haven't specified enough information for the scale. if scale is None: with self.assertRaisesRegexp(ValueError, ("must be specified.")): bijector = affine_lib.Affine(shift=shift, **bijector_args) else: bijector = affine_lib.Affine(shift=shift, **bijector_args) np_x = x # For the case a vector is passed in, we need to make the shape # match the matrix for matmul to work. if x.ndim == scale.ndim - 1: np_x = np.expand_dims(x, axis=-1) forward = np.matmul(scale, np_x) + shift if x.ndim == scale.ndim - 1: forward = np.squeeze(forward, axis=-1) self.assertAllClose(forward, bijector.forward(x).eval()) backward = np.linalg.solve(scale, np_x - shift) if x.ndim == scale.ndim - 1: backward = np.squeeze(backward, axis=-1) self.assertAllClose(backward, bijector.inverse(x).eval()) ildj = -np.log(np.abs(np.linalg.det(scale))) # TODO(jvdillon): We need to make it so the scale_identity_multiplier # case does not deviate in expected shape. Fixing this will get rid of # these special cases. if (ildj.ndim > 0 and (len(scale_args) == 1 or (len(scale_args) == 2 and scale_args.get( "scale_identity_multiplier", None) is not None))): ildj = np.squeeze(ildj[0]) elif ildj.ndim < scale.ndim - 2: ildj = np.reshape(ildj, scale.shape[0:-2]) self.assertAllClose( ildj, bijector.inverse_log_det_jacobian(x).eval())
def testWeirdSampleNoBatchScalarViaIdentity(self): with self.test_session() as sess: def static_run(fun, x): return fun(x).eval() def dynamic_run(fun, x_value): x_value = np.array(x_value) x = array_ops.placeholder(dtypes.float32, name="x") return sess.run(fun(x), feed_dict={x: x_value}) for run in (static_run, dynamic_run): mu = -1. # Corresponds to scale = 2. bijector = affine_lib.Affine(shift=mu, scale_identity_multiplier=2., event_ndims=0) self.assertEqual(0, bijector.event_ndims.eval()) # "is scalar" x = [[1., 2, 3], [4, 5, 6]] # Weird sample shape. self.assertAllClose([[1., 3, 5], [7, 9, 11]], run(bijector.forward, x)) self.assertAllClose([[1., 1.5, 2.], [2.5, 3, 3.5]], run(bijector.inverse, x)) self.assertAllClose(-np.log(2.), run(bijector.inverse_log_det_jacobian, x))
def testIdentityAndDiagWithTriL(self): with self.test_session() as sess: def static_run(fun, x): return fun(x).eval() def dynamic_run(fun, x_value): x_value = np.array(x_value) x = array_ops.placeholder(dtypes.float32, name="x") return sess.run(fun(x), feed_dict={x: x_value}) for run in (static_run, dynamic_run): mu = -1. # scale = [[3., 0], [2, 4]] bijector = affine_lib.Affine(shift=mu, scale_identity_multiplier=1.0, scale_diag=[1., 2.], scale_tril=[[1., 0], [2., 1]]) self.assertEqual(1, bijector.event_ndims.eval()) # "is vector" x = [[1., 2]] # One multivariate sample. self.assertAllClose([[2., 9]], run(bijector.forward, x)) self.assertAllClose([[2 / 3., 5 / 12.]], run(bijector.inverse, x)) self.assertAllClose(-np.log(12.), run(bijector.inverse_log_det_jacobian, x))
def testBatchMultivariateFullDynamic(self): with self.test_session() as sess: x = array_ops.placeholder(dtypes.float32, name="x") mu = array_ops.placeholder(dtypes.float32, name="mu") scale_diag = array_ops.placeholder(dtypes.float32, name="scale_diag") event_ndims = array_ops.placeholder(dtypes.int32, name="event_ndims") x_value = np.array([[[1., 1]]], dtype=np.float32) mu_value = np.array([[1., -1]], dtype=np.float32) scale_diag_value = np.array([[2., 2]], dtype=np.float32) event_ndims_value = 1 feed_dict = { x: x_value, mu: mu_value, scale_diag: scale_diag_value, event_ndims: event_ndims_value } bijector = affine_lib.Affine(shift=mu, scale_diag=scale_diag, event_ndims=event_ndims) self.assertEqual(1, sess.run(bijector.event_ndims, feed_dict)) self.assertAllClose([[[3., 1]]], sess.run(bijector.forward(x), feed_dict)) self.assertAllClose([[[0., 1]]], sess.run(bijector.inverse(x), feed_dict)) self.assertAllClose([-np.log(4)], sess.run(bijector.inverse_log_det_jacobian(x), feed_dict))
def testNoBatchMultivariateDiag(self): with self.test_session() as sess: def static_run(fun, x): return fun(x).eval() def dynamic_run(fun, x_value): x_value = np.array(x_value) x = array_ops.placeholder(dtypes.float32, name="x") return sess.run(fun(x), feed_dict={x: x_value}) for run in (static_run, dynamic_run): mu = [1., -1] # Multivariate # Corresponds to scale = [[2., 0], [0, 1.]] bijector = affine_lib.Affine(shift=mu, scale_diag=[2., 1]) self.assertEqual(1, bijector.event_ndims.eval()) # "is vector" x = [1., 1] # matmul(sigma, x) + shift # = [-1, -1] + [1, -1] self.assertAllClose([3., 0], run(bijector.forward, x)) self.assertAllClose([0., 2], run(bijector.inverse, x)) self.assertAllClose(-np.log(2.), run(bijector.inverse_log_det_jacobian, x)) # x is a 2-batch of 2-vectors. # The first vector is [1, 1], the second is [-1, -1]. # Each undergoes matmul(sigma, x) + shift. x = [[1., 1], [-1., -1]] self.assertAllClose([[3., 0], [-1., -2]], run(bijector.forward, x)) self.assertAllClose([[0., 2], [-1., 0]], run(bijector.inverse, x)) self.assertAllClose(-np.log(2.), run(bijector.inverse_log_det_jacobian, x))
def testScalarCongruency(self): with self.test_session(): bijector = affine_lib.Affine(shift=3.6, scale_identity_multiplier=0.42, event_ndims=0) bijector_test_util.assert_scalar_congruency(bijector, lower_x=-2., upper_x=2.)
def testEventNdimsLargerThanOneRaises(self): with self.test_session(): mu = [1., -1] # Scale corresponds to 2x2 identity matrix. bijector = affine_lib.Affine(shift=mu, event_ndims=2, validate_args=True) bijector.forward([1., 1.]).eval()
def testScaleZeroScalarRaises(self): with self.test_session(): mu = -1. # Check Identity matrix with zero scaling. bijector = affine_lib.Affine(shift=mu, scale_identity_multiplier=0.0, event_ndims=0, validate_args=True) with self.assertRaisesOpError("Condition x > 0"): bijector.forward(1.).eval() # Check Diag matrix with zero scaling. bijector = affine_lib.Affine(shift=mu, scale_diag=[0.0], event_ndims=0, validate_args=True) with self.assertRaisesOpError("Condition x > 0"): bijector.forward(1.).eval()
def testNoBatchMultivariateRaisesWhenSingular(self): with self.test_session(): mu = [1., -1] bijector = affine_lib.Affine( shift=mu, # Has zero on the diagonal. scale_diag=[0., 1], validate_args=True) with self.assertRaisesOpError("Condition x > 0"): bijector.forward([1., 1.]).eval()
def testTriLWithVDVTUpdateNoDiagonal(self): with self.test_session() as sess: def static_run(fun, x): return fun(x).eval() def dynamic_run(fun, x_value): x_value = np.array(x_value) x = array_ops.placeholder(dtypes.float32, name="x") return sess.run(fun(x), feed_dict={x: x_value}) for run in (static_run, dynamic_run): mu = -1. # Corresponds to scale = [[6, 0, 0], [1, 3, 0], [2, 3, 5]] bijector = affine_lib.Affine(shift=mu, scale_tril=[[2., 0, 0], [1, 3, 0], [2, 3, 4]], scale_perturb_diag=None, scale_perturb_factor=[[2., 0], [0., 0], [0, 1]]) bijector_ref = affine_lib.Affine(shift=mu, scale_tril=[[6., 0, 0], [1, 3, 0], [2, 3, 5]]) self.assertEqual(1, bijector.event_ndims.eval()) # "is vector" x = [1., 2, 3] # Vector. self.assertAllClose([5., 6, 22], run(bijector.forward, x)) self.assertAllClose(run(bijector_ref.forward, x), run(bijector.forward, x)) self.assertAllClose([1 / 3., 8 / 9., 4 / 30.], run(bijector.inverse, x)) self.assertAllClose(run(bijector_ref.inverse, x), run(bijector.inverse, x)) self.assertAllClose(-np.log(90.), run(bijector.inverse_log_det_jacobian, x)) self.assertAllClose( run(bijector.inverse_log_det_jacobian, x), run(bijector_ref.inverse_log_det_jacobian, x))
def testIdentityWithVDVTUpdate(self): with self.test_session() as sess: def static_run(fun, x): return fun(x).eval() def dynamic_run(fun, x_value): x_value = np.array(x_value) x = array_ops.placeholder(dtypes.float32, name="x") return sess.run(fun(x), feed_dict={x: x_value}) for run in (static_run, dynamic_run): mu = -1. # Corresponds to scale = [[10, 0, 0], [0, 2, 0], [0, 0, 3]] bijector = affine_lib.Affine(shift=mu, scale_identity_multiplier=2., scale_perturb_diag=[2., 1], scale_perturb_factor=[[2., 0], [0., 0], [0, 1]]) bijector_ref = affine_lib.Affine(shift=mu, scale_diag=[10., 2, 3]) self.assertEqual(1, bijector.event_ndims.eval()) # "is vector" x = [1., 2, 3] # Vector. self.assertAllClose([9., 3, 8], run(bijector.forward, x)) self.assertAllClose(run(bijector_ref.forward, x), run(bijector.forward, x)) self.assertAllClose([0.2, 1.5, 4 / 3.], run(bijector.inverse, x)) self.assertAllClose(run(bijector_ref.inverse, x), run(bijector.inverse, x)) self.assertAllClose(-np.log(60.), run(bijector.inverse_log_det_jacobian, x)) self.assertAllClose( run(bijector.inverse_log_det_jacobian, x), run(bijector_ref.inverse_log_det_jacobian, x))
def testBatchMultivariateDiag(self): with self.test_session() as sess: def static_run(fun, x): return fun(x).eval() def dynamic_run(fun, x_value): x_value = np.array(x_value, dtype=np.float32) x = array_ops.placeholder(dtypes.float32, name="x") return sess.run(fun(x), feed_dict={x: x_value}) for run in (static_run, dynamic_run): mu = [[1., -1]] # Corresponds to 1 2x2 matrix, with twos on the diagonal. scale_diag = [[2., 2]] bijector = affine_lib.Affine(shift=mu, scale_diag=scale_diag) self.assertEqual(1, bijector.event_ndims.eval()) # "is vector" x = [[[1., 1]]] self.assertAllClose([[[3., 1]]], run(bijector.forward, x)) self.assertAllClose([[[0., 1]]], run(bijector.inverse, x)) self.assertAllClose([-np.log(4)], run(bijector.inverse_log_det_jacobian, x))
def testTwoBatchScalarIdentityViaIdentity(self): with self.test_session() as sess: def static_run(fun, x): return fun(x).eval() def dynamic_run(fun, x_value): x_value = np.array(x_value) x = array_ops.placeholder(dtypes.float32, name="x") return sess.run(fun(x), feed_dict={x: x_value}) for run in (static_run, dynamic_run): mu = [1., -1] # Univariate, two batches. # Corresponds to scale = 1. bijector = affine_lib.Affine(shift=mu, event_ndims=0) self.assertEqual(0, bijector.event_ndims.eval()) # "is scalar" x = [1., 1] # One sample from each of two batches. self.assertAllClose([2., 0], run(bijector.forward, x)) self.assertAllClose([0., 2], run(bijector.inverse, x)) self.assertAllClose(0., run(bijector.inverse_log_det_jacobian, x))
def testNoBatchScalarViaDiag(self): with self.test_session() as sess: def static_run(fun, x): return fun(x).eval() def dynamic_run(fun, x_value): x_value = np.array(x_value) x = array_ops.placeholder(dtypes.float32, name="x") return sess.run(fun(x), feed_dict={x: x_value}) for run in (static_run, dynamic_run): mu = -1. # Corresponds to scale = 2 bijector = affine_lib.Affine(shift=mu, scale_diag=[2.], event_ndims=0) self.assertEqual(0, bijector.event_ndims.eval()) # "is scalar" x = [1., 2, 3] # Three scalar samples (no batches). self.assertAllClose([1., 3, 5], run(bijector.forward, x)) self.assertAllClose([1., 1.5, 2.], run(bijector.inverse, x)) self.assertAllClose(-np.log(2.), run(bijector.inverse_log_det_jacobian, x))
def testScalePropertyAssertsCorrectly(self): with self.test_session(): with self.assertRaises(NotImplementedError): scale = affine_lib.Affine( # pylint:disable=unused-variable scale_tril=[[1., 0], [2, 1]], scale_perturb_factor=[2., 1.]).scale
def testProperties(self): with self.test_session(): mu = -1. # scale corresponds to 1. bijector = affine_lib.Affine(shift=mu, event_ndims=0) self.assertEqual("affine", bijector.name)