!31091 Fix sparse check and refactor the test cases of cg method.

Merge pull request !31091 from hezhenhao1/fix_cg
This commit is contained in:
i-robot 2022-03-10 09:14:21 +00:00 committed by Gitee
commit 4623b599b9
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
3 changed files with 48 additions and 83 deletions

View File

@ -164,30 +164,36 @@ def _sparse_check(func_name, a, m, b, x0):
_mstype_check(func_name, x0, mstype.tensor_type, 'x0')
# Checking shape and dtype
if b.ndim != 1 or (b.ndim == 2 and b.shape[1] != 1):
if (b.ndim != 1 and b.ndim != 2) or (b.ndim == 2 and b.shape[1] != 1):
_raise_value_error(
"For: '", func_name, "', the shape of b should be like (N,) or (N, 1), bug got ", b.shape, ".")
"For: '", func_name, "', the shape of 'b' should be like (N,) or (N, 1), bug got ", b.shape, ".")
if (x0.ndim != 1 and x0.ndim != 2) or (x0.ndim == 2 and x0.shape[1] != 1):
_raise_value_error(
"For: '", func_name, "', the shape of 'x0' should be like (N,) or (N, 1), bug got ", x0.shape, ".")
_dtype_check(func_name, b, [mstype.int32, mstype.int64, mstype.float32, mstype.float64], 'b')
_super_check((b.dtype, x0.dtype), (func_name, 'b', 'x0', 'data type'), '==', 'match', None, True)
_super_check((b.shape, x0.shape), (func_name, 'b', 'x0', 'shape'), '==', 'match', None, True)
_dtype_check(func_name, x0, [mstype.int32, mstype.int64, mstype.float32, mstype.float64], 'x0')
def _check(arg, arg_name):
if _callable_const(F.typeof(arg)):
return arg
_solve_check(func_name, arg, b, arg_name, 'b', True)
if isinstance(arg, CSRTensor):
_dtype_check(func_name, arg.indptr, [mstype.int32], arg_name)
_dtype_check(func_name, arg.indices, [mstype.int32], arg_name)
_dtype_check(func_name, arg.values, [mstype.float32], arg_name)
else:
_dtype_check(func_name, arg, [mstype.int32, mstype.int64, mstype.float32, mstype.float64], arg_name)
if F.dtype(arg) in (mstype.int32, mstype.int64):
arg = F.cast(arg, mstype.float64)
_solve_check(func_name, arg, b, arg_name, 'b', True)
_solve_check(func_name, arg, x0, arg_name, 'x0', True)
if isinstance(arg, Tensor) and F.dtype(arg) in (mstype.int32, mstype.int64):
arg = F.cast(arg, mstype.float64)
return arg
a = _check(a, 'A')
m = _check(m, 'M')
b = b.ravel()
x0 = x0.ravel()
if F.dtype(b) in (mstype.int32, mstype.int64):
b = F.cast(b, mstype.float64)
x0 = F.cast(x0, mstype.float64)

View File

@ -21,9 +21,8 @@ import mindspore.ops as ops
import mindspore.nn as nn
import mindspore.scipy as msp
from mindspore import context
from mindspore.common import Tensor, CSRTensor
from tests.st.scipy_st.utils import create_sym_pos_matrix, create_full_rank_matrix, create_sym_pos_sparse_matrix, \
to_tensor
from mindspore.common import Tensor
from tests.st.scipy_st.utils import create_sym_pos_matrix, create_full_rank_matrix, to_tensor
def _fetch_preconditioner(preconditioner, A):
@ -48,14 +47,15 @@ def _fetch_preconditioner(preconditioner, A):
@pytest.mark.platform_x86_gpu_training
@pytest.mark.platform_x86_cpu
@pytest.mark.env_onecard
@pytest.mark.parametrize('dtype, tol', [(onp.float32, 1e-5), (onp.float64, 1e-12)])
@pytest.mark.parametrize('shape', [(4, 4), (7, 7)])
@pytest.mark.parametrize('tensor_type, dtype, tol', [('Tensor', onp.float32, 1e-5), ('Tensor', onp.float64, 1e-12),
('CSRTensor', onp.float32, 1e-5)])
@pytest.mark.parametrize('shape', [(7, 7)])
@pytest.mark.parametrize('preconditioner', [None, 'identity', 'exact', 'random'])
@pytest.mark.parametrize('maxiter', [1, 3])
def test_cg_against_scipy(dtype, tol, shape, preconditioner, maxiter):
@pytest.mark.parametrize('maxiter', [3, None])
def test_cg_against_scipy(tensor_type, dtype, tol, shape, preconditioner, maxiter):
"""
Feature: ALL TO ALL
Description: test cases for cg
Description: test cases for cg using function way in pynative/graph mode
Expectation: the result match scipy
"""
onp.random.seed(0)
@ -64,9 +64,9 @@ def test_cg_against_scipy(dtype, tol, shape, preconditioner, maxiter):
m = _fetch_preconditioner(preconditioner, a)
osp_res = scipy.sparse.linalg.cg(a, b, M=m, maxiter=maxiter, atol=tol, tol=tol)
a = Tensor(a)
a = to_tensor((a, tensor_type))
b = Tensor(b)
m = Tensor(m) if m is not None else m
m = to_tensor((m, tensor_type)) if m is not None else m
# using PYNATIVE MODE
context.set_context(mode=context.PYNATIVE_MODE)
@ -117,17 +117,17 @@ def test_cg_against_numpy(dtype, shape):
@pytest.mark.platform_x86_gpu_training
@pytest.mark.platform_x86_cpu
@pytest.mark.env_onecard
@pytest.mark.parametrize('dtype, tol', [(onp.float32, 1e-5), (onp.float64, 1e-12)])
@pytest.mark.parametrize('tensor_type, dtype, tol', [('Tensor', onp.float32, 1e-5), ('Tensor', onp.float64, 1e-12),
('CSRTensor', onp.float32, 1e-5)])
@pytest.mark.parametrize('shape', [(7, 7)])
@pytest.mark.parametrize('preconditioner', [None, 'identity', 'exact', 'random'])
@pytest.mark.parametrize('maxiter', [3])
def test_cg_against_scipy_graph(dtype, tol, shape, preconditioner, maxiter):
@pytest.mark.parametrize('maxiter', [3, None])
def test_cg_against_scipy_graph(tensor_type, dtype, tol, shape, preconditioner, maxiter):
"""
Feature: ALL TO ALL
Description: test cases for cg within Cell object
Description: test cases for cg within Cell object in pynative/graph mode
Expectation: the result match scipy
"""
context.set_context(mode=context.GRAPH_MODE)
class Net(nn.Cell):
def construct(self, a, b, m, maxiter, tol):
@ -139,52 +139,23 @@ def test_cg_against_scipy_graph(dtype, tol, shape, preconditioner, maxiter):
m = _fetch_preconditioner(preconditioner, a)
osp_res = scipy.sparse.linalg.cg(a, b, M=m, maxiter=maxiter, atol=tol, tol=tol)
a = Tensor(a)
a = to_tensor((a, tensor_type))
b = Tensor(b)
m = Tensor(m) if m is not None else m
msp_res = Net()(a, b, m, maxiter, tol)
m = to_tensor((m, tensor_type)) if m is not None else m
kw = {"atol": tol, "rtol": tol}
onp.testing.assert_allclose(osp_res[0], msp_res[0].asnumpy(), **kw)
assert osp_res[1] == msp_res[1].asnumpy().item()
# using PYNATIVE MODE
context.set_context(mode=context.PYNATIVE_MODE)
msp_res_dyn = Net()(a, b, m, maxiter, tol)
@pytest.mark.level0
@pytest.mark.platform_x86_gpu_training
@pytest.mark.env_onecard
@pytest.mark.parametrize('dtype, tol', [(onp.float32, 1e-5)])
@pytest.mark.parametrize('shape', [(7, 7)])
@pytest.mark.parametrize('preconditioner', [None, 'identity', 'random'])
@pytest.mark.parametrize('maxiter', [3])
def test_cg_against_scipy_sparse(dtype, tol, shape, preconditioner, maxiter):
"""
Feature: ALL TO ALL
Description: test cases of CSRTensor for cg
Expectation: the result match scipy.
"""
# using GRAPH MODE
context.set_context(mode=context.GRAPH_MODE)
class Net(nn.Cell):
def construct(self, a, b, m, maxiter, tol):
return msp.sparse.linalg.cg(a, b, M=m, maxiter=maxiter, atol=tol, tol=tol)
onp.random.seed(0)
# scipy
a = create_sym_pos_sparse_matrix(shape, dtype)
b = onp.random.random(shape[:1]).astype(dtype)
m = _fetch_preconditioner(preconditioner, a)
osp_res = scipy.sparse.linalg.cg(a, b, M=m, maxiter=maxiter, atol=tol, tol=tol)
# mindspore
a = CSRTensor(Tensor(a.indptr), Tensor(a.indices), Tensor(a.data), shape)
b = Tensor(b)
m = Tensor(m) if m is not None else m
msp_res = Net()(a, b, m, maxiter, tol)
msp_res_sta = Net()(a, b, m, maxiter, tol)
kw = {"atol": tol, "rtol": tol}
onp.testing.assert_allclose(osp_res[0], msp_res[0].asnumpy(), **kw)
assert osp_res[1] == msp_res[1].asnumpy().item()
onp.testing.assert_allclose(osp_res[0], msp_res_dyn[0].asnumpy(), **kw)
onp.testing.assert_allclose(osp_res[0], msp_res_sta[0].asnumpy(), **kw)
assert osp_res[1] == msp_res_dyn[1].asnumpy().item()
assert osp_res[1] == msp_res_sta[1].asnumpy().item()
@pytest.mark.level0

View File

@ -14,18 +14,17 @@
# ============================================================================
"""utility functions for mindspore.scipy st tests"""
from typing import List
from functools import cmp_to_key, partial
from functools import cmp_to_key
import numpy as onp
import scipy as osp
import scipy.sparse.linalg
from mindspore import Tensor, CSRTensor
import mindspore.ops as ops
import mindspore.numpy as mnp
from mindspore.common import dtype as mstype
def to_tensor(obj, dtype=None):
def to_tensor(obj, dtype=None, indice_dtype=onp.int32):
"""
This function is used to initialize Tensor or CSRTensor.
'obj' can be three type:
@ -45,13 +44,14 @@ def to_tensor(obj, dtype=None):
dtype = obj.dtype
if isinstance(obj, onp.ndarray):
tensor_fn = partial(Tensor, input_data=obj.astype(dtype))
else:
tensor_fn = partial(CSRTensor, indptr=Tensor(obj.indptr), indices=Tensor(obj.indices),
values=Tensor(obj.data.astype(dtype)), shape=obj.shape)
obj = Tensor(obj.astype(dtype))
elif isinstance(obj, osp.sparse.csr_matrix):
obj = CSRTensor(indptr=Tensor(obj.indptr.astype(indice_dtype)),
indices=Tensor(obj.indices.astype(indice_dtype)),
values=Tensor(obj.data.astype(dtype)),
shape=obj.shape)
res = tensor_fn()
return res
return obj
def match_array(actual, expected, error=0, err_msg=''):
@ -117,18 +117,6 @@ def create_sym_pos_matrix(shape, dtype):
return (onp.matmul(x, x.T) + onp.eye(n)).astype(dtype)
def create_sym_pos_sparse_matrix(shape, dtype, indice_dtype=onp.int32):
if len(shape) != 2 or shape[0] != shape[1]:
raise ValueError(
'Symmetric positive definite matrix must be a square matrix, but has shape: ', shape)
n = shape[-1]
indptr = onp.arange(n + 1).astype(indice_dtype)
indices = onp.arange(n).astype(indice_dtype)
values = onp.random.random(n).astype(dtype)
return scipy.sparse.csr_matrix((values, indices, indptr), shape=shape)
def gradient_check(x, net, epsilon=1e-3, symmetric=False, enumerate_fn=onp.ndenumerate):
# Some utils
def _tensor_to_numpy(arg: List[Tensor]) -> List[onp.ndarray]: