Skip to content

Commit

Permalink
Merge pull request #3770 from kmaehashi/fix-inv-error-check
Browse files Browse the repository at this point in the history
fix F.inv to raise exception when input has singular matrices
  • Loading branch information
okuta committed Nov 4, 2017
2 parents 2877091 + 42c1d2d commit a9d8aaf
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 2 deletions.
12 changes: 10 additions & 2 deletions chainer/functions/math/inv.py
@@ -1,5 +1,6 @@
import numpy.linalg

import chainer
from chainer import cuda
from chainer import function_node
import chainer.functions
Expand Down Expand Up @@ -54,7 +55,11 @@ def forward_cpu(self, x):
def forward_gpu(self, x):
self.retain_outputs((0,))
shape = x[0].shape
invx = _inv_gpu(x[0].reshape(1, *shape))[0].reshape(shape)
invx, info = _inv_gpu(x[0].reshape(1, *shape))
if chainer.is_debug():
if cuda.cupy.any(info != 0):
raise ValueError('Input has singular matrices.')
invx = invx.reshape(shape)
return invx,

def backward(self, x, gy):
Expand Down Expand Up @@ -85,7 +90,10 @@ def forward_cpu(self, x):

def forward_gpu(self, x):
self.retain_outputs((0,))
invx, _ = _inv_gpu(x[0])
invx, info = _inv_gpu(x[0])
if chainer.is_debug():
if cuda.cupy.any(info != 0):
raise ValueError('Input has singular matrices.')
return invx,

def backward(self, x, gy):
Expand Down
36 changes: 36 additions & 0 deletions tests/chainer_tests/functions_tests/math_tests/test_inv.py
Expand Up @@ -158,6 +158,24 @@ def test_invalid_shape(self):
with self.assertRaises(type_check.InvalidType):
functions.inv(x)

def test_singular_cpu(self):
x = chainer.Variable(numpy.zeros((2, 2), dtype=numpy.float32))
with self.assertRaises(numpy.linalg.LinAlgError):
functions.inv(x)

@attr.gpu
def test_singular_gpu(self):
x = chainer.Variable(
cuda.to_gpu(numpy.zeros((2, 2), dtype=numpy.float32)))

# Should raise exception only when debug mode.
with chainer.using_config('debug', False):
functions.inv(x)

with chainer.using_config('debug', True):
with self.assertRaises(ValueError):
functions.inv(x)


class BatchInvFunctionRaiseTest(unittest.TestCase):

Expand All @@ -171,5 +189,23 @@ def test_invalid_shape(self):
with self.assertRaises(type_check.InvalidType):
functions.batch_inv(x)

def test_singular_cpu(self):
x = chainer.Variable(numpy.zeros((1, 2, 2), dtype=numpy.float32))
with self.assertRaises(numpy.linalg.LinAlgError):
functions.batch_inv(x)

@attr.gpu
def test_singular_gpu(self):
x = chainer.Variable(
cuda.to_gpu(numpy.zeros((1, 2, 2), dtype=numpy.float32)))

# Should raise exception only when debug mode.
with chainer.using_config('debug', False):
functions.batch_inv(x)

with chainer.using_config('debug', True):
with self.assertRaises(ValueError):
functions.batch_inv(x)


testing.run_module(__name__, __file__)

0 comments on commit a9d8aaf

Please sign in to comment.