Repository: chainer/chainer

Issue:
Check type of a return value in unit test for each function
Some functions return `numpy.ndarray` of `float64`, which is not supported now. We need to check return values and fix functions when they return `float64`.



Discussion:

Resolving patch:
diff --git a/chainer/functions/hierarchical_softmax.py b/chainer/functions/hierarchical_softmax.py
--- a/chainer/functions/hierarchical_softmax.py
+++ b/chainer/functions/hierarchical_softmax.py
@@ -115,17 +115,17 @@ def forward_cpu(self, args):
         assert t.ndim == 1 and t.dtype.kind == 'i'
         assert len(x) == len(t)
 
-        loss = 0.0
+        loss = numpy.float32(0.0)
         for ix, it in six.moves.zip(x, t):
             loss += self._forward_cpu_one(ix, it)
-        return numpy.array([loss]),
+        return numpy.array(loss),
 
     def _forward_cpu_one(self, x, t):
         assert t in self.paths
 
         w = self.W[self.paths[t]]
         wxy = w.dot(x) * self.codes[t]
-        loss = numpy.logaddexp(0, -wxy)  # == log(1 + exp(-wxy))
+        loss = numpy.logaddexp(0.0, -wxy)  # == log(1 + exp(-wxy))
         return numpy.sum(loss)
 
     def backward_cpu(self, args, loss):
diff --git a/chainer/functions/negative_sampling.py b/chainer/functions/negative_sampling.py
--- a/chainer/functions/negative_sampling.py
+++ b/chainer/functions/negative_sampling.py
@@ -88,13 +88,13 @@ def forward_cpu(self, inputs):
         x, t = inputs
         self._make_samples(t)
 
-        loss = 0
+        loss = numpy.float32(0.0)
         for i, (ix, k) in enumerate(six.moves.zip(x, self.samples)):
             w = self.W[k]
             f = w.dot(ix)
             f[0] *= -1  # positive sample
             loss += numpy.sum(numpy.logaddexp(f, 0))
-        return numpy.array([loss], numpy.float32),
+        return numpy.array(loss, numpy.float32),
 
     def forward_gpu(self, inputs):
         x, t = inputs
diff --git a/chainer/functions/sigmoid_cross_entropy.py b/chainer/functions/sigmoid_cross_entropy.py
--- a/chainer/functions/sigmoid_cross_entropy.py
+++ b/chainer/functions/sigmoid_cross_entropy.py
@@ -19,7 +19,7 @@ def forward_cpu(self, inputs):
         # stable computation of the cross entropy.
         loss = -numpy.sum(
             x * (t - (x >= 0)) - numpy.log1p(numpy.exp(-numpy.abs(x))))
-        return numpy.array((loss / t.shape[0],), dtype=numpy.float32),
+        return numpy.array(loss / t.shape[0], dtype=numpy.float32),
 
     def forward_gpu(self, inputs):
         x, t = inputs


Test patch:
diff --git a/tests/functions_tests/test_accuracy.py b/tests/functions_tests/test_accuracy.py
--- a/tests/functions_tests/test_accuracy.py
+++ b/tests/functions_tests/test_accuracy.py
@@ -23,6 +23,7 @@ def check_forward(self, x_data, t_data):
         x = chainer.Variable(x_data)
         t = chainer.Variable(t_data)
         y = chainer.functions.accuracy(x, t)
+        self.assertEqual(y.data.dtype, numpy.float32)
         self.assertEqual((), y.data.shape)
 
         count = 0
diff --git a/tests/functions_tests/test_batch_normalization.py b/tests/functions_tests/test_batch_normalization.py
--- a/tests/functions_tests/test_batch_normalization.py
+++ b/tests/functions_tests/test_batch_normalization.py
@@ -36,6 +36,7 @@ def setUp(self):
     def check_forward(self, x_data):
         x = chainer.Variable(x_data)
         y = self.func(x)
+        self.assertEqual(y.data.dtype, numpy.float32)
 
         mean = self.x.mean(axis=self.aggr_axes, keepdims=True)
         std = numpy.sqrt(
@@ -43,6 +44,7 @@ def check_forward(self, x_data):
         y_expect = self.gamma * (self.x - mean) / std + self.beta
 
         gradient_check.assert_allclose(y_expect, y.data)
+        self.assertEqual(numpy.float32, y.data.dtype)
 
     def test_forward_cpu(self):
         self.check_forward(self.x)
diff --git a/tests/functions_tests/test_convolution_2d.py b/tests/functions_tests/test_convolution_2d.py
--- a/tests/functions_tests/test_convolution_2d.py
+++ b/tests/functions_tests/test_convolution_2d.py
@@ -49,10 +49,12 @@ def test_col2im_consistency(self):
     def test_forward_consistency(self):
         x_cpu = chainer.Variable(self.x)
         y_cpu = self.func(x_cpu)
+        self.assertEqual(y_cpu.data.dtype, numpy.float32)
 
         self.func.to_gpu()
         x_gpu = chainer.Variable(cuda.to_gpu(self.x))
         y_gpu = self.func(x_gpu)
+        self.assertEqual(y_gpu.data.dtype, numpy.float32)
 
         for i in six.moves.range(y_cpu.data.shape[0]):
             print(i, numpy.abs(y_cpu.data[i] - y_gpu.data[i].get()).max())
diff --git a/tests/functions_tests/test_embed_id.py b/tests/functions_tests/test_embed_id.py
--- a/tests/functions_tests/test_embed_id.py
+++ b/tests/functions_tests/test_embed_id.py
@@ -31,6 +31,7 @@ def to_gpu(self):
     def check_forward(self, x_data):
         x = chainer.Variable(x_data)
         y = self.func(x)
+        self.assertEqual(y.data.dtype, numpy.float32)
 
         y_expect = numpy.empty_like(self.gy)
         for i in six.moves.range(self.x.size):
diff --git a/tests/functions_tests/test_hierarchical_softmax.py b/tests/functions_tests/test_hierarchical_softmax.py
--- a/tests/functions_tests/test_hierarchical_softmax.py
+++ b/tests/functions_tests/test_hierarchical_softmax.py
@@ -33,11 +33,13 @@ def setUp(self):
         self.W = self.func.W.copy()
 
     def test_sum(self):
-        x = numpy.array([[1.0, 2.0, 3.0]])
+        x = numpy.array([[1.0, 2.0, 3.0]], numpy.float32)
         total = 0
         for i in range(5):
             t = numpy.array([i])
             loss, = self.func.forward_cpu((x, t))
+            self.assertEqual(loss.dtype, numpy.float32)
+            self.assertEqual(loss.shape, ())
             total += numpy.exp(-loss)
         self.assertAlmostEqual(1.0, float(total))
 
diff --git a/tests/functions_tests/test_leaky_relu.py b/tests/functions_tests/test_leaky_relu.py
--- a/tests/functions_tests/test_leaky_relu.py
+++ b/tests/functions_tests/test_leaky_relu.py
@@ -26,6 +26,7 @@ def setUp(self):
     def check_forward(self, x_data):
         x = chainer.Variable(x_data)
         y = functions.leaky_relu(x, slope=self.slope)
+        self.assertEqual(y.data.dtype, numpy.float32)
 
         expected = self.x.copy()
         for i in numpy.ndindex(self.x.shape):
diff --git a/tests/functions_tests/test_linear.py b/tests/functions_tests/test_linear.py
--- a/tests/functions_tests/test_linear.py
+++ b/tests/functions_tests/test_linear.py
@@ -40,6 +40,7 @@ def setUp(self):
     def check_forward(self, x_data):
         x = chainer.Variable(x_data)
         y = self.func(x)
+        self.assertEqual(y.data.dtype, numpy.float32)
         gradient_check.assert_allclose(self.y, y.data)
 
     def test_forward_cpu(self):
diff --git a/tests/functions_tests/test_local_response_normalization.py b/tests/functions_tests/test_local_response_normalization.py
--- a/tests/functions_tests/test_local_response_normalization.py
+++ b/tests/functions_tests/test_local_response_normalization.py
@@ -25,6 +25,7 @@ def setUp(self):
     def check_forward(self, x_data):
         x = chainer.Variable(x_data)
         y = functions.local_response_normalization(x)
+        self.assertEqual(y.data.dtype, numpy.float32)
         y_data = cuda.to_cpu(y.data)
 
         # Naive implementation
diff --git a/tests/functions_tests/test_lstm.py b/tests/functions_tests/test_lstm.py
--- a/tests/functions_tests/test_lstm.py
+++ b/tests/functions_tests/test_lstm.py
@@ -37,6 +37,8 @@ def check_forward(self, c_prev_data, x_data):
         c_prev = chainer.Variable(c_prev_data)
         x = chainer.Variable(x_data)
         c, h = functions.lstm(c_prev, x)
+        self.assertEqual(c.data.dtype, numpy.float32)
+        self.assertEqual(h.data.dtype, numpy.float32)
 
         # Compute expected out
         a_in = self.x[:, [0, 4]]
diff --git a/tests/functions_tests/test_negative_sampling.py b/tests/functions_tests/test_negative_sampling.py
--- a/tests/functions_tests/test_negative_sampling.py
+++ b/tests/functions_tests/test_negative_sampling.py
@@ -42,10 +42,16 @@ def test_forward_gpu(self):
         self.func._make_samples(self.t)
         y = self.func(x, t)
 
+        self.assertEqual(y.data.dtype, numpy.float32)
+        self.assertEqual(y.data.shape, ())
+
         self.func.to_gpu()
         y_g = self.func(chainer.Variable(cuda.to_gpu(self.x)),
                         chainer.Variable(cuda.to_gpu(self.t)))
 
+        self.assertEqual(y_g.data.dtype, numpy.float32)
+        self.assertEqual(y_g.data.shape, ())
+
         gradient_check.assert_allclose(y.data, y_g.data, atol=1.e-4)
 
     def test_backward_cpu(self):
diff --git a/tests/functions_tests/test_parameter.py b/tests/functions_tests/test_parameter.py
--- a/tests/functions_tests/test_parameter.py
+++ b/tests/functions_tests/test_parameter.py
@@ -27,6 +27,7 @@ def to_gpu(self):
 
     def check_forward(self):
         y = self.func()
+        self.assertEqual(y.data.dtype, numpy.float32)
         self.assertTrue((self.W == cuda.to_cpu(y.data)).all())
 
     def test_forward_cpu(self):
diff --git a/tests/functions_tests/test_pooling_2d.py b/tests/functions_tests/test_pooling_2d.py
--- a/tests/functions_tests/test_pooling_2d.py
+++ b/tests/functions_tests/test_pooling_2d.py
@@ -32,6 +32,7 @@ def check_forward(self, x_data, use_cudnn=True):
         y = functions.max_pooling_2d(x, 3, stride=2, pad=1,
                                      cover_all=self.cover_all,
                                      use_cudnn=use_cudnn)
+        self.assertEqual(y.data.dtype, numpy.float32)
         y_data = cuda.to_cpu(y.data)
 
         self.assertEqual(self.gy.shape, y_data.shape)
diff --git a/tests/functions_tests/test_prelu.py b/tests/functions_tests/test_prelu.py
--- a/tests/functions_tests/test_prelu.py
+++ b/tests/functions_tests/test_prelu.py
@@ -31,6 +31,7 @@ def setUp(self):
     def check_forward(self, x_data):
         x = chainer.Variable(x_data)
         y = self.func(x)
+        self.assertEqual(y.data.dtype, numpy.float32)
 
         y_expect = self.x.copy()
         for i in numpy.ndindex(self.x.shape):
diff --git a/tests/functions_tests/test_relu.py b/tests/functions_tests/test_relu.py
--- a/tests/functions_tests/test_relu.py
+++ b/tests/functions_tests/test_relu.py
@@ -24,6 +24,7 @@ def setUp(self):
     def check_backward(self, x_data, y_grad, use_cudnn=True):
         x = chainer.Variable(x_data)
         y = functions.relu(x, use_cudnn=use_cudnn)
+        self.assertEqual(y.data.dtype, numpy.float32)
         y.grad = y_grad
         y.backward()
 
diff --git a/tests/functions_tests/test_reshape.py b/tests/functions_tests/test_reshape.py
--- a/tests/functions_tests/test_reshape.py
+++ b/tests/functions_tests/test_reshape.py
@@ -22,6 +22,7 @@ def check_forward(self, x_data):
         shape = self.gy.shape
         x = chainer.Variable(x_data)
         y = functions.reshape(x, shape)
+        self.assertEqual(y.data.dtype, numpy.float32)
         self.assertTrue((self.x.reshape(shape) == cuda.to_cpu(y.data)).all())
 
     def test_forward_cpu(self):
diff --git a/tests/functions_tests/test_sigmoid.py b/tests/functions_tests/test_sigmoid.py
--- a/tests/functions_tests/test_sigmoid.py
+++ b/tests/functions_tests/test_sigmoid.py
@@ -23,6 +23,7 @@ def setUp(self):
     def test_forward_gpu(self, use_cudnn=True):
         x = chainer.Variable(cuda.to_gpu(self.x))
         y = functions.sigmoid(x, use_cudnn=use_cudnn)
+        self.assertEqual(y.data.dtype, numpy.float32)
         y_expect = functions.sigmoid(chainer.Variable(self.x))
 
         gradient_check.assert_allclose(y_expect.data, y.data)
diff --git a/tests/functions_tests/test_sigmoid_cross_entropy.py b/tests/functions_tests/test_sigmoid_cross_entropy.py
--- a/tests/functions_tests/test_sigmoid_cross_entropy.py
+++ b/tests/functions_tests/test_sigmoid_cross_entropy.py
@@ -25,6 +25,8 @@ def check_forward(self, x_data, t_data, use_cudnn=True):
         x_val = chainer.Variable(x_data)
         t_val = chainer.Variable(t_data)
         loss = functions.sigmoid_cross_entropy(x_val, t_val, use_cudnn)
+        self.assertEqual(loss.data.shape, ())
+        self.assertEqual(loss.data.dtype, numpy.float32)
         loss_value = float(cuda.to_cpu(loss.data))
 
         # Compute expected value
diff --git a/tests/functions_tests/test_softmax.py b/tests/functions_tests/test_softmax.py
--- a/tests/functions_tests/test_softmax.py
+++ b/tests/functions_tests/test_softmax.py
@@ -23,6 +23,7 @@ def setUp(self):
     def check_forward(self, x_data, use_cudnn=True):
         x = chainer.Variable(x_data)
         y = functions.softmax(x, use_cudnn)
+        self.assertEqual(y.data.dtype, numpy.float32)
 
         y_expect = numpy.exp(self.x)
         for i in six.moves.range(y_expect.shape[0]):
diff --git a/tests/functions_tests/test_softmax_cross_entropy.py b/tests/functions_tests/test_softmax_cross_entropy.py
--- a/tests/functions_tests/test_softmax_cross_entropy.py
+++ b/tests/functions_tests/test_softmax_cross_entropy.py
@@ -25,6 +25,8 @@ def check_forward(self, x_data, t_data, use_cudnn=True):
         x = chainer.Variable(x_data)
         t = chainer.Variable(t_data)
         loss = functions.softmax_cross_entropy(x, t, use_cudnn)
+        self.assertEqual(loss.data.shape, ())
+        self.assertEqual(loss.data.dtype, numpy.float32)
         loss_value = float(cuda.to_cpu(loss.data))
 
         # Compute expected value
diff --git a/tests/functions_tests/test_sum.py b/tests/functions_tests/test_sum.py
--- a/tests/functions_tests/test_sum.py
+++ b/tests/functions_tests/test_sum.py
@@ -22,6 +22,7 @@ def setUp(self):
     def check_forward(self, x_data):
         x = chainer.Variable(x_data)
         y = functions.sum(x)
+        self.assertEqual(y.data.dtype, numpy.float32)
         y_expect = self.x.sum()
         gradient_check.assert_allclose(y_expect, y.data)
 
diff --git a/tests/functions_tests/test_tanh.py b/tests/functions_tests/test_tanh.py
--- a/tests/functions_tests/test_tanh.py
+++ b/tests/functions_tests/test_tanh.py
@@ -23,6 +23,7 @@ def setUp(self):
     def test_forward_gpu(self, use_cudnn=True):
         x = chainer.Variable(cuda.to_gpu(self.x))
         y = functions.tanh(x, use_cudnn=use_cudnn)
+        self.assertEqual(y.data.dtype, numpy.float32)
         y_expect = functions.tanh(chainer.Variable(self.x))
         gradient_check.assert_allclose(y_expect.data, y.data)