From a024c5e27e89a3ac7d011ff19772150083fe8b5f Mon Sep 17 00:00:00 2001 From: Alp Kucukelbir Date: Tue, 28 Feb 2017 07:51:53 -0500 Subject: [PATCH] Implement a few inference tests (#487) * basic test file structure * klpq and map tests * cleanup vi tests, add mh test * more MCMC tests * found magic combination for SGLD to converge * fixed map, disabled sgld and klpq tests * fix test_sgld.py * fix test_klpq.py --- tests/test-inferences/test_hmc.py | 33 +++++++++++++++++ tests/test-inferences/test_klpq.py | 35 ++++++++++++++++++ tests/test-inferences/test_klqp.py | 35 ++++++++++++++++++ tests/test-inferences/test_map.py | 31 ++++++++++++++++ .../test_metropolishastings.py | 36 +++++++++++++++++++ tests/test-inferences/test_sgld.py | 33 +++++++++++++++++ 6 files changed, 203 insertions(+) create mode 100644 tests/test-inferences/test_hmc.py create mode 100644 tests/test-inferences/test_klpq.py create mode 100644 tests/test-inferences/test_klqp.py create mode 100644 tests/test-inferences/test_map.py create mode 100644 tests/test-inferences/test_metropolishastings.py create mode 100644 tests/test-inferences/test_sgld.py diff --git a/tests/test-inferences/test_hmc.py b/tests/test-inferences/test_hmc.py new file mode 100644 index 000000000..7200aae3f --- /dev/null +++ b/tests/test-inferences/test_hmc.py @@ -0,0 +1,33 @@ +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import edward as ed +import numpy as np +import tensorflow as tf + +from edward.models import Normal, Empirical + + +class test_hmc_class(tf.test.TestCase): + + def test_normalnormal_run(self): + with self.test_session() as sess: + x_data = np.array([0.0] * 50, dtype=np.float32) + + mu = Normal(mu=0.0, sigma=1.0) + x = Normal(mu=tf.ones(50) * mu, sigma=1.0) + + qmu = Empirical(params=tf.Variable(tf.ones(2000))) + + # analytic solution: N(mu=0.0, sigma=\sqrt{1/51}=0.140) + inference = ed.HMC({mu: qmu}, data={x: x_data}) + inference.run() + + self.assertAllClose(qmu.mean().eval(), 0, rtol=1e-2, atol=1e-2) + self.assertAllClose(qmu.std().eval(), np.sqrt(1 / 51), + rtol=1e-2, atol=1e-2) + +if __name__ == '__main__': + ed.set_seed(42) + tf.test.main() diff --git a/tests/test-inferences/test_klpq.py b/tests/test-inferences/test_klpq.py new file mode 100644 index 000000000..9396ed7c0 --- /dev/null +++ b/tests/test-inferences/test_klpq.py @@ -0,0 +1,35 @@ +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import edward as ed +import numpy as np +import tensorflow as tf + +from edward.models import Normal + + +class test_klpq_class(tf.test.TestCase): + + def test_normalnormal_run(self): + with self.test_session() as sess: + x_data = np.array([0.0] * 50, dtype=np.float32) + + mu = Normal(mu=0.0, sigma=1.0) + x = Normal(mu=tf.ones(50) * mu, sigma=1.0) + + qmu_mu = tf.Variable(tf.random_normal([])) + qmu_sigma = tf.nn.softplus(tf.Variable(tf.random_normal([]))) + qmu = Normal(mu=qmu_mu, sigma=qmu_sigma) + + # analytic solution: N(mu=0.0, sigma=\sqrt{1/51}=0.140) + inference = ed.KLpq({mu: qmu}, data={x: x_data}) + inference.run(n_samples=25, n_iter=100) + + self.assertAllClose(qmu.mean().eval(), 0, rtol=1e-1, atol=1e-1) + self.assertAllClose(qmu.std().eval(), np.sqrt(1 / 51), + rtol=1e-1, atol=1e-1) + +if __name__ == '__main__': + ed.set_seed(42) + tf.test.main() diff --git a/tests/test-inferences/test_klqp.py b/tests/test-inferences/test_klqp.py new file mode 100644 index 000000000..3284645f7 --- /dev/null +++ b/tests/test-inferences/test_klqp.py @@ -0,0 +1,35 @@ +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import edward as ed +import numpy as np +import tensorflow as tf + +from edward.models import Normal + + +class test_klqp_class(tf.test.TestCase): + + def test_normalnormal_run(self): + with self.test_session() as sess: + x_data = np.array([0.0] * 50, dtype=np.float32) + + mu = Normal(mu=0.0, sigma=1.0) + x = Normal(mu=tf.ones(50) * mu, sigma=1.0) + + qmu_mu = tf.Variable(tf.random_normal([])) + qmu_sigma = tf.nn.softplus(tf.Variable(tf.random_normal([]))) + qmu = Normal(mu=qmu_mu, sigma=qmu_sigma) + + # analytic solution: N(mu=0.0, sigma=\sqrt{1/51}=0.140) + inference = ed.KLqp({mu: qmu}, data={x: x_data}) + inference.run(n_iter=5000) + + self.assertAllClose(qmu.mean().eval(), 0, rtol=1e-2, atol=1e-2) + self.assertAllClose(qmu.std().eval(), np.sqrt(1 / 51), + rtol=1e-2, atol=1e-2) + +if __name__ == '__main__': + ed.set_seed(42) + tf.test.main() diff --git a/tests/test-inferences/test_map.py b/tests/test-inferences/test_map.py new file mode 100644 index 000000000..4ddeafd19 --- /dev/null +++ b/tests/test-inferences/test_map.py @@ -0,0 +1,31 @@ +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import edward as ed +import numpy as np +import tensorflow as tf + +from edward.models import Normal, PointMass + + +class test_map_class(tf.test.TestCase): + + def test_normalnormal_run(self): + with self.test_session() as sess: + x_data = np.array([0.0] * 50, dtype=np.float32) + + mu = Normal(mu=0.0, sigma=1.0) + x = Normal(mu=tf.ones(50) * mu, sigma=1.0) + + qmu = PointMass(params=tf.Variable(tf.ones([]))) + + # analytic solution: N(mu=0.0, sigma=\sqrt{1/51}=0.140) + inference = ed.MAP({mu: qmu}, data={x: x_data}) + inference.run(n_iter=1000) + + self.assertAllClose(qmu.mean().eval(), 0) + +if __name__ == '__main__': + ed.set_seed(42) + tf.test.main() diff --git a/tests/test-inferences/test_metropolishastings.py b/tests/test-inferences/test_metropolishastings.py new file mode 100644 index 000000000..ad5b2d963 --- /dev/null +++ b/tests/test-inferences/test_metropolishastings.py @@ -0,0 +1,36 @@ +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import edward as ed +import numpy as np +import tensorflow as tf + +from edward.models import Normal, Empirical + + +class test_metropolishastings_class(tf.test.TestCase): + + def test_normalnormal_run(self): + with self.test_session() as sess: + x_data = np.array([0.0] * 50, dtype=np.float32) + + mu = Normal(mu=0.0, sigma=1.0) + x = Normal(mu=tf.ones(50) * mu, sigma=1.0) + + qmu = Empirical(params=tf.Variable(tf.ones(2000))) + proposal_mu = Normal(mu=0.0, sigma=1.0) + + # analytic solution: N(mu=0.0, sigma=\sqrt{1/51}=0.140) + inference = ed.MetropolisHastings({mu: qmu}, + {mu: proposal_mu}, + data={x: x_data}) + inference.run() + + self.assertAllClose(qmu.mean().eval(), 0, rtol=1e-2, atol=1e-2) + self.assertAllClose(qmu.std().eval(), np.sqrt(1 / 51), + rtol=1e-2, atol=1e-2) + +if __name__ == '__main__': + ed.set_seed(42) + tf.test.main() diff --git a/tests/test-inferences/test_sgld.py b/tests/test-inferences/test_sgld.py new file mode 100644 index 000000000..cf6d457d4 --- /dev/null +++ b/tests/test-inferences/test_sgld.py @@ -0,0 +1,33 @@ +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import edward as ed +import numpy as np +import tensorflow as tf + +from edward.models import Normal, Empirical + + +class test_sgld_class(tf.test.TestCase): + + def test_normalnormal_run(self): + with self.test_session() as sess: + x_data = np.array([0.0] * 50, dtype=np.float32) + + mu = Normal(mu=0.0, sigma=1.0) + x = Normal(mu=tf.ones(50) * mu, sigma=1.0) + + qmu = Empirical(params=tf.Variable(tf.ones(5000))) + + # analytic solution: N(mu=0.0, sigma=\sqrt{1/51}=0.140) + inference = ed.SGLD({mu: qmu}, data={x: x_data}) + inference.run(step_size=0.2) + + self.assertAllClose(qmu.mean().eval(), 0, rtol=1e-2, atol=1e-2) + self.assertAllClose(qmu.std().eval(), np.sqrt(1 / 51), + rtol=5e-2, atol=5e-2) + +if __name__ == '__main__': + ed.set_seed(42) + tf.test.main()