Repository: chainer/chainer

Issue:
Fix the shape of return value of F.det
Currently, return value of `det` is `xp.array` whose shape is `(1, )`, not a scalar.

```
In [16]: a = chainer.Variable(numpy.random.uniform(-1, 1, (3, 3)).astype(numpy.float32))
In [17]: chainer.functions.det(a).data
Out[17]: array([-0.80874199], dtype=float32)
```

But the document says the return value should be `chainer.Variable` whose data have the shape `()`.



Discussion:

Resolving patch:
diff --git a/chainer/functions/math/det.py b/chainer/functions/math/det.py
--- a/chainer/functions/math/det.py
+++ b/chainer/functions/math/det.py
@@ -109,4 +109,4 @@ def det(a):
     shape = (1, len(a.data), a.data.shape[1])
     batched_a = reshape.Reshape(shape)(a)
     batched_det = BatchDet()(batched_a)
-    return reshape.Reshape((1, ))(batched_det)
+    return reshape.Reshape(())(batched_det)


Test patch:
diff --git a/tests/chainer_tests/functions_tests/math_tests/test_det.py b/tests/chainer_tests/functions_tests/math_tests/test_det.py
--- a/tests/chainer_tests/functions_tests/math_tests/test_det.py
+++ b/tests/chainer_tests/functions_tests/math_tests/test_det.py
@@ -14,11 +14,6 @@
 
 class DetFunctionTestBase(object):
 
-    def setUp(self):
-        self.x, self.y, self.gy = self.make_data()
-        self.ct = numpy.array(
-            [ix.T for ix in self.x], dtype=numpy.float32)
-
     def det_transpose(self, gpu=False):
         if gpu:
             cx = cuda.to_gpu(self.x)
@@ -122,18 +117,20 @@ def test_batch_backward_cpu(self):
         x_data, y_grad = self.x, self.gy
         gradient_check.check_backward(self.det, x_data, y_grad)
 
-    def test_expect_scalar_cpu(self):
-        x = numpy.random.uniform(.5, 1, (2, 2)).astype(numpy.float32)
+    def check_single_matrix(self, x):
         x = chainer.Variable(x)
-        y = F.det(x)
-        self.assertEqual(y.data.ndim, 1)
+        y = self.det(x)
+        if self.batched:
+            self.assertEqual(y.data.ndim, 1)
+        else:
+            self.assertEqual(y.data.ndim, 0)
+
+    def test_single_matrix_cpu(self):
+        self.check_single_matrix(self.x)
 
     @attr.gpu
     def test_expect_scalar_gpu(self):
-        x = cuda.cupy.random.uniform(.5, 1, (2, 2)).astype(numpy.float32)
-        x = chainer.Variable(x)
-        y = F.det(x)
-        self.assertEqual(y.data.ndim, 1)
+        self.check_single_matrix(cuda.to_gpu(self.x))
 
     def test_zero_det_cpu(self):
         x_data, y_grad = self.x, self.gy
@@ -198,11 +195,11 @@ def det(self, x):
     def matmul(self, x, y):
         return F.batch_matmul(x, y)
 
-    def make_data(self):
-        x = numpy.random.uniform(.5, 1, (6, 3, 3)).astype(numpy.float32)
-        y = numpy.random.uniform(.5, 1, (6, 3, 3)).astype(numpy.float32)
-        gy = numpy.random.uniform(-1, 1, (6,)).astype(numpy.float32)
-        return x, y, gy
+    def setUp(self):
+        self.x = numpy.random.uniform(.5, 1, (6, 3, 3)).astype(numpy.float32)
+        self.y = numpy.random.uniform(.5, 1, (6, 3, 3)).astype(numpy.float32)
+        self.gy = numpy.random.uniform(-1, 1, (6,)).astype(numpy.float32)
+        self.ct = self.x.transpose(0, 2, 1)
 
 
 class TestSquareDet(DetFunctionTestBase, unittest.TestCase):
@@ -214,11 +211,11 @@ def det(self, x):
     def matmul(self, x, y):
         return F.matmul(x, y)
 
-    def make_data(self):
-        x = numpy.random.uniform(.5, 1, (5, 5)).astype(numpy.float32)
-        y = numpy.random.uniform(.5, 1, (5, 5)).astype(numpy.float32)
-        gy = numpy.random.uniform(-1, 1, (1,)).astype(numpy.float32)
-        return x, y, gy
+    def setUp(self):
+        self.x = numpy.random.uniform(.5, 1, (5, 5)).astype(numpy.float32)
+        self.y = numpy.random.uniform(.5, 1, (5, 5)).astype(numpy.float32)
+        self.gy = numpy.random.uniform(-1, 1, ()).astype(numpy.float32)
+        self.ct = self.x.transpose()
 
 
 class DetFunctionRaiseTest(unittest.TestCase):