From e35433f6536fd71abae6e34f9f8e7a2fde93d3ec Mon Sep 17 00:00:00 2001 From: karita Date: Fri, 7 Aug 2015 19:26:43 +0900 Subject: [PATCH] migrate functions --- .travis.yml | 1 - test/functions/__init__.py | 1 + test/functions/test_gaussian_mixture_2d.py | 95 ++++++++++++ test/functions/test_gradient_clip.py | 56 +++++++ test/functions/test_peephole_lstm.py | 166 +++++++++++++++++++++ test/functions/test_split_axis.py | 51 +++++++ test/functions/test_sqrt.py | 89 +++++++++++ test/functions/test_sum_axis.py | 44 ++++++ test/functions/test_vec_sub_mat.py | 47 ++++++ 9 files changed, 549 insertions(+), 1 deletion(-) create mode 100644 test/functions/__init__.py create mode 100644 test/functions/test_gaussian_mixture_2d.py create mode 100644 test/functions/test_gradient_clip.py create mode 100644 test/functions/test_peephole_lstm.py create mode 100644 test/functions/test_split_axis.py create mode 100644 test/functions/test_sqrt.py create mode 100644 test/functions/test_sum_axis.py create mode 100644 test/functions/test_vec_sub_mat.py diff --git a/.travis.yml b/.travis.yml index 55c63aa..7bcf2b9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,6 @@ install: - pip install coveralls script: - - ls - nosetests test/functions -a '!gpu,!local' --with-xunit --with-coverage --cover-erase --cover-package=src.functions --verbose after_success: diff --git a/test/functions/__init__.py b/test/functions/__init__.py new file mode 100644 index 0000000..176ba83 --- /dev/null +++ b/test/functions/__init__.py @@ -0,0 +1 @@ +__author__ = 'karita' diff --git a/test/functions/test_gaussian_mixture_2d.py b/test/functions/test_gaussian_mixture_2d.py new file mode 100644 index 0000000..b9f9865 --- /dev/null +++ b/test/functions/test_gaussian_mixture_2d.py @@ -0,0 +1,95 @@ +import unittest + +import numpy +from numpy.random import uniform, binomial + +import chainer +from chainer import cuda +from chainer import gradient_check +from chainer import testing +from chainer.testing import attr, condition + +from src.functions.gaussian_mixture_2d import gaussian_mixture_2d +from src.functions.gaussian_mixture_2d_ref import gaussian_mixture_2d_ref +from src import gravesnet + + +if cuda.available: + cuda.init() + + +class TestGaussianMixture2d(unittest.TestCase): + + def setUp(self): + # each 2D-Gaussian contains 6 params: weight, mean(2), stddev(2), corr + self.ngauss = numpy.random.randint(1, 5) + input_size = 6 * self.ngauss + 1 + mini_batch = numpy.random.randint(1, 5) + self.x = uniform(-1, 1, (mini_batch, input_size)).astype(numpy.float32) + self.t_x = uniform(-1, 1, (mini_batch, 2)).astype(numpy.float32) + b_rand = [[binomial(1, 0.9) for _ in range(mini_batch)]] + self.t_e = numpy.array(b_rand).astype(numpy.int32).reshape((mini_batch, 1)) + self.g = uniform(-1, 1, (mini_batch, self.ngauss)).astype(numpy.float32) + + def check(self): + t_x = chainer.Variable(self.context(self.t_x)) + t_e = chainer.Variable(self.context(self.t_e)) + x = chainer.Variable(self.context(self.x)) + + loss = gravesnet.loss_func(self.ngauss, x, t_x, t_e) + loss.backward() + self.assertEqual(None, t_x.grad) + self.assertEqual(None, t_e.grad) + + func = loss.creator + f = lambda: func.forward((self.ngauss, x.data, t_x.data, t_e.data)) + loss.grad *= 10.0 + # gx, = gradient_check.numerical_grad(f, (x.data,), (loss.grad,), eps=1e-2) + return x.grad, loss.data + + def check_ref(self): + t_x = chainer.Variable(self.context(self.t_x)) + t_e = chainer.Variable(self.context(self.t_e)) + x = chainer.Variable(self.context(self.x)) + y, e = gravesnet.split_args(self.ngauss, x, t_x, t_e) + p = gaussian_mixture_2d(*y) + q = gaussian_mixture_2d_ref(*y) + gradient_check.assert_allclose(p.data, q.data) + + + # TODO: Check and pass backward + # x.grad = None + # p_loss = gravesnet.concat_losses(p, e, t_e) + # q_loss = gravesnet.concat_losses(q, e, t_e) + # p_loss.backward() + # p_xg = x.grad.copy() + # x.grad = None + # q_loss.backward() + # q_xg = x.grad.copy() + # print(p_xg, q_xg) + # gradient_check.assert_allclose(p_loss.data, q_loss.data) + # gradient_check.assert_allclose(p_xg, q_xg) + + @condition.retry(3) + def test_original_versus_chainer_cpu(self): + self.context = lambda x: x + self.check_ref() + + @condition.retry(3) + @attr.gpu + def test_original_versus_chainer_gpu(self): + self.context = cuda.to_gpu + self.check_ref() + + @condition.retry(3) + @attr.gpu + def test_cpu_versus_gpu(self): + self.context = lambda x: x + cpu, closs = self.check() + self.context = cuda.to_gpu + gpu, gloss = self.check() + numpy.testing.assert_almost_equal(closs, cuda.to_cpu(gloss)) + gradient_check.assert_allclose(gpu, cpu) + + +testing.run_module(__name__, __file__) diff --git a/test/functions/test_gradient_clip.py b/test/functions/test_gradient_clip.py new file mode 100644 index 0000000..9100880 --- /dev/null +++ b/test/functions/test_gradient_clip.py @@ -0,0 +1,56 @@ +import unittest + +import chainer +from chainer import cuda +from chainer.gradient_check import assert_allclose +from chainer.testing import attr, condition, run_module +import numpy + +from src.functions.gradient_clip import gradient_clip + + +if cuda.available: + cuda.init() + + +class TestGradientClip(unittest.TestCase): + + def setUp(self): + self.a = numpy.random.random() + self.b = numpy.random.random() + self.x = numpy.random.randn(4, 3).astype(numpy.float32) + self.y_grad = numpy.random.randn(4, 3).astype(numpy.float32) + lower = min(self.a, self.b) + upper = max(self.a, self.b) + self.x_grad_ab = numpy.clip(self.y_grad, lower, upper) + self.x_grad_a = numpy.clip(self.y_grad, -abs(self.a), abs(self.a)) + + def check_backward(self, f): + x = chainer.Variable(f(self.x)) + + y = gradient_clip(x, self.a, self.b) + y.creator.forward((x.data,)) + y.grad = f(self.y_grad) + y.backward() + assert_allclose(y.data, x.data) + assert_allclose(x.grad, f(self.x_grad_ab)) + + y = gradient_clip(x, self.a) + y.creator.forward((x.data,)) + y.grad = f(self.y_grad) + y.backward() + assert_allclose(y.data, x.data) + assert_allclose(x.grad, f(self.x_grad_a)) + + + @condition.retry(100) + def test_backward_cpu(self): + self.check_backward(lambda x: x) + + @attr.gpu + @condition.retry(100) + def test_backward_gpu(self): + self.check_backward(cuda.to_gpu) + + +run_module(__name__, __file__) \ No newline at end of file diff --git a/test/functions/test_peephole_lstm.py b/test/functions/test_peephole_lstm.py new file mode 100644 index 0000000..bb2461e --- /dev/null +++ b/test/functions/test_peephole_lstm.py @@ -0,0 +1,166 @@ +import unittest + +import numpy + +import chainer +from chainer import cuda +from chainer import gradient_check +from chainer import testing +from chainer.testing import attr +from chainer.testing import condition + +from src.functions.peephole_lstm import peephole_lstm + +if cuda.available: + cuda.init() + + +def _sigmoid(x): + return 1 / (1 + numpy.exp(-x)) + + +class TestPeepholeLSTM(unittest.TestCase): + + def setUp(self): + self.c_prev = numpy.random.uniform(-1, + 1, (3, 2, 4)).astype(numpy.float32) + self.a = numpy.random.uniform(-1, 1, (3, 2, 4)).astype(numpy.float32) + self.x = numpy.random.uniform(-1, 1, (3, 6, 4)).astype(numpy.float32) + + self.gc = numpy.random.uniform(-1, 1, (3, 2, 4)).astype(numpy.float32) + self.gh = numpy.random.uniform(-1, 1, (3, 2, 4)).astype(numpy.float32) + + def flat(self): + self.c_prev = self.c_prev[:, :, 0].copy() + self.a = self.a[:, :, 0].copy() + self.x = self.x[:, :, 0].copy() + self.gc = self.gc[:, :, 0].copy() + self.gh = self.gh[:, :, 0].copy() + + def check_forward(self, c_prev_data, a_data, x_data): + c_prev = chainer.Variable(c_prev_data) + a = chainer.Variable(a_data) + x = chainer.Variable(x_data) + c, h = peephole_lstm(c_prev, a, x) + self.assertEqual(c.data.dtype, numpy.float32) + self.assertEqual(h.data.dtype, numpy.float32) + + # Compute expected out + a_in = self.a + i_in = self.x[:, [0, 3]] + f_in = self.x[:, [1, 4]] + o_in = self.x[:, [2, 5]] + + c_expect = _sigmoid(i_in) * numpy.tanh(a_in) + \ + _sigmoid(f_in) * self.c_prev + h_expect = _sigmoid(o_in) * numpy.tanh(c_expect) + + gradient_check.assert_allclose(c_expect, c.data) + gradient_check.assert_allclose(h_expect, h.data) + + @condition.retry(3) + def test_forward_cpu(self): + self.check_forward(self.c_prev, self.a, self.x) + + @condition.retry(3) + def test_flat_forward_cpu(self): + self.flat() + self.test_forward_cpu() + + @attr.gpu + @condition.retry(3) + def test_forward_gpu(self): + self.check_forward(cuda.to_gpu(self.c_prev), cuda.to_gpu(self.a), cuda.to_gpu(self.x)) + + @attr.gpu + @condition.retry(3) + def test_flat_forward_gpu(self): + self.flat() + self.test_forward_gpu() + + def check_backward(self, c_prev_data, a_data, x_data, c_grad, h_grad): + c_prev = chainer.Variable(c_prev_data) + a = chainer.Variable(a_data) + x = chainer.Variable(x_data) + c, h = peephole_lstm(c_prev, a, x) + c.grad = c_grad + h.grad = h_grad + c.backward() + + func = c.creator + f = lambda: func.forward((c_prev.data, a.data, x.data)) + gc_prev, ga, gx = gradient_check.numerical_grad( + f, (c_prev.data, a.data, x.data), (c_grad, h_grad), eps=1e-2) + + gradient_check.assert_allclose(gc_prev, c_prev.grad) + gradient_check.assert_allclose(ga, a.grad) + gradient_check.assert_allclose(gx, x.grad) + + @condition.retry(3) + def test_full_backward_cpu(self): + self.check_backward(self.c_prev, self.a, self.x, self.gc, self.gh) + + @condition.retry(3) + def test_flat_full_backward_cpu(self): + self.flat() + self.test_full_backward_cpu() + + @condition.retry(3) + def test_no_gc_backward_cpu(self): + self.check_backward(self.c_prev, self.a, self.x, None, self.gh) + + @condition.retry(3) + def test_flat_no_gc_backward_cpu(self): + self.flat() + self.test_no_gc_backward_cpu() + + @condition.retry(3) + def test_no_gh_backward_cpu(self): + self.check_backward(self.c_prev, self.a, self.x, self.gc, None) + + @condition.retry(3) + def test_flat_no_gh_backward_cpu(self): + self.flat() + self.test_no_gh_backward_cpu() + + @attr.gpu + @condition.retry(3) + def test_full_backward_gpu(self): + self.check_backward( + cuda.to_gpu(self.c_prev), cuda.to_gpu(self.a), cuda.to_gpu(self.x), + cuda.to_gpu(self.gc), cuda.to_gpu(self.gh)) + + @attr.gpu + @condition.retry(3) + def test_flat_full_backward_gpu(self): + self.flat() + self.test_full_backward_gpu() + + @attr.gpu + @condition.retry(3) + def test_no_gc_backward_gpu(self): + self.check_backward( + cuda.to_gpu(self.c_prev), cuda.to_gpu(self.a), cuda.to_gpu(self.x), + None, cuda.to_gpu(self.gh)) + + @attr.gpu + @condition.retry(3) + def test_flat_no_gc_backward_gpu(self): + self.flat() + self.test_no_gc_backward_gpu() + + @attr.gpu + @condition.retry(3) + def test_no_gh_backward_gpu(self): + self.check_backward( + cuda.to_gpu(self.c_prev), cuda.to_gpu(self.a), cuda.to_gpu(self.x), + cuda.to_gpu(self.gc), None) + + @attr.gpu + @condition.retry(3) + def test_flat_no_gh_backward_gpu(self): + self.flat() + self.test_no_gh_backward_gpu() + + +testing.run_module(__name__, __file__) diff --git a/test/functions/test_split_axis.py b/test/functions/test_split_axis.py new file mode 100644 index 0000000..d505897 --- /dev/null +++ b/test/functions/test_split_axis.py @@ -0,0 +1,51 @@ +from unittest import TestCase + +import chainer +from chainer import cuda +from chainer.functions import concat +from chainer.gradient_check import assert_allclose +from chainer import testing +from chainer.testing import attr, condition +import numpy + +from src.functions.spilit_axis import split_axis_by_widths + + +if cuda.available: + cuda.init() + + +class TestSplitAxis(TestCase): + + def setUp(self): + # self.ws = [2, 4] + h = numpy.random.randint(1, 5) + l = h * numpy.random.randint(1, 5) + self.ws = [numpy.random.randint(1, 5)] * l + self.ws[0] = h + self.mini_batch = numpy.random.randint(1, 5) + + def check(self, widths): + x_size = sum(self.ws) + x = numpy.arange(self.mini_batch * x_size, + dtype=numpy.float32).reshape(self.mini_batch, x_size) + x = chainer.Variable(self.context(x)) + y = split_axis_by_widths(x, widths) + z = concat(y) + assert_allclose(x.data, z.data) + + @condition.retry(100) + def test_split_axis_cpu(self): + self.context = lambda x: x + self.check(self.ws) + self.check(self.ws[0]) + + @condition.retry(100) + @attr.gpu + def test_split_axis_gpu(self): + self.context = cuda.to_gpu + self.check(self.ws) + self.check(self.ws[0]) + + +testing.run_module(__name__, __file__) \ No newline at end of file diff --git a/test/functions/test_sqrt.py b/test/functions/test_sqrt.py new file mode 100644 index 0000000..e6e70d3 --- /dev/null +++ b/test/functions/test_sqrt.py @@ -0,0 +1,89 @@ +import unittest + +import chainer +from chainer import testing +from chainer import cuda +from chainer import gradient_check +from chainer.testing import attr, condition +import numpy + +from src.functions.sqrt import mysqrt + +if cuda.available: + cuda.init() + + + +class UnaryFunctionsTestBase(object): + + def make_data(self): + raise NotImplementedError() + + def setUp(self): + self.x, self.gy = self.make_data() + + def check_forward(self, op, op_np, x_data): + x = chainer.Variable(x_data) + y = op(x) + gradient_check.assert_allclose( + op_np(self.x), y.data, atol=1e-7, rtol=1e-7) + + def forward_cpu(self, op, op_np): + self.check_forward(op, op_np, self.x) + + def forward_gpu(self, op, op_np): + self.check_forward(op, op_np, cuda.to_gpu(self.x)) + + def check_backward(self, op, x_data, y_grad): + x = chainer.Variable(x_data) + y = op(x) + y.grad = y_grad + y.backward() + + func = y.creator + f = lambda: func.forward((x.data,)) + gx, = gradient_check.numerical_grad(f, (x.data,), (y.grad,)) + + gradient_check.assert_allclose(gx, x.grad) + + def backward_cpu(self, op): + self.check_backward(op, self.x, self.gy) + + def backward_gpu(self, op): + self.check_backward(op, cuda.to_gpu(self.x), cuda.to_gpu(self.gy)) + + @condition.retry(3) + def test_sqrt_forward_cpu(self): + self.forward_cpu(mysqrt, numpy.sqrt) + + @condition.retry(3) + @attr.gpu + def test_sqrt_forward_gpu(self): + self.forward_cpu(mysqrt, numpy.sqrt) + + @condition.retry(3) + def test_sqrt_backward_cpu(self): + self.backward_cpu(mysqrt) + + @attr.gpu + @condition.retry(3) + def test_sqrt_backward_gpu(self): + self.backward_gpu(mysqrt) + + +class TestUnaryFunctionsSimple(UnaryFunctionsTestBase, unittest.TestCase): + def make_data(self): + x = numpy.random.uniform(.5, 1, (3, 2)).astype(numpy.float32) + gy = numpy.random.uniform(-1, 1, (3, 2)).astype(numpy.float32) + return x, gy + + +class TestUnaryFunctionsZeroDimension(UnaryFunctionsTestBase, + unittest.TestCase): + def make_data(self): + x = numpy.random.uniform(.5, 1, ()).astype(numpy.float32) + gy = numpy.random.uniform(-1, 1, ()).astype(numpy.float32) + return x, gy + + +testing.run_module(__name__, __file__) \ No newline at end of file diff --git a/test/functions/test_sum_axis.py b/test/functions/test_sum_axis.py new file mode 100644 index 0000000..54690fa --- /dev/null +++ b/test/functions/test_sum_axis.py @@ -0,0 +1,44 @@ +from unittest import TestCase + +from chainer import testing +import chainer +from chainer import cuda +from chainer.gradient_check import assert_allclose +from chainer.testing import attr, condition +import numpy + +from src.functions.sum_axis import sum_axis + +if cuda.available: + cuda.init() + + +class TestSumAxis(TestCase): + + def setUp(self): + r = numpy.random.randint(2, 5) + c = numpy.random.randint(2, 5) + self.w = numpy.arange(r).reshape(r, 1).astype(numpy.float32) + self.x = numpy.full((r, c), self.w).astype(numpy.float32) + self.y = c * self.w + + def check(self, context): + x = chainer.Variable(context(self.x)) + y = sum_axis(x) + assert_allclose(y.data, context(self.y)) + + y.grad = context(self.w) + y.backward() + assert_allclose(x.grad, context(self.x)) + + @condition.retry(100) + def test_cpu(self): + self.check(lambda x: x) + + @condition.retry(100) + @attr.gpu + def test_gpu(self): + self.check(cuda.to_gpu) + + +testing.run_module(__name__, __file__) \ No newline at end of file diff --git a/test/functions/test_vec_sub_mat.py b/test/functions/test_vec_sub_mat.py new file mode 100644 index 0000000..1d6abc7 --- /dev/null +++ b/test/functions/test_vec_sub_mat.py @@ -0,0 +1,47 @@ +from unittest import TestCase + +import chainer +from chainer import testing +from chainer.gradient_check import assert_allclose +from chainer import cuda +from chainer.testing import attr, condition +import numpy + +from src.functions.vec_sub_mat import vec_sub_mat + +if cuda.available: + cuda.init() + + +class TestVecSubMat(TestCase): + + def setUp(self): + r = numpy.random.randint(2, 5) + c = numpy.random.randint(2, 5) + self.v = numpy.arange(r).reshape(r, 1).astype(numpy.float32) + self.n = numpy.random.uniform(-1, 1, (r, c)).astype(numpy.float32) + self.m = numpy.full_like(self.n, self.v) - self.n + self.g = numpy.arange(r * c).reshape(r, c).astype(numpy.float32) + self.h = self.g.sum(1).reshape(r, 1) + + def check(self, context): + v = chainer.Variable(context(self.v)) + m = chainer.Variable(context(self.m)) + n = vec_sub_mat(v, m) + assert_allclose(n.data, context(self.n)) + + n.grad = context(self.g) + n.backward() + assert_allclose(m.grad, -n.grad) + assert_allclose(v.grad, context(self.h)) + + @condition.retry(100) + def test_cpu(self): + self.check(lambda x: x) + + @condition.retry(100) + @attr.gpu + def test_gpu(self): + self.check(cuda.to_gpu) + +testing.run_module(__name__, __file__) \ No newline at end of file