Browse Source

!31960 fix sparse arg check 1.7

Merge pull request !31960 from 杨林枫/sparse_fix_1.7
r1.7
i-robot Gitee 4 years ago
parent
commit
84f922dc44
No known key found for this signature in database GPG Key ID: 173E9B9CA92EEF8F
5 changed files with 75 additions and 51 deletions
  1. +2
    -2
      docs/api/api_python/mindspore/mindspore.CSRTensor.rst
  2. +57
    -39
      mindspore/core/abstract/prim_others.cc
  3. +9
    -5
      mindspore/python/mindspore/_checkparam.py
  4. +1
    -0
      mindspore/python/mindspore/_extends/parse/standard_method.py
  5. +6
    -5
      mindspore/python/mindspore/common/tensor.py

+ 2
- 2
docs/api/api_python/mindspore/mindspore.CSRTensor.rst View File

@@ -15,7 +15,7 @@ mindspore.CSRTensor
- **indptr** (Tensor) - 形状为 `[M]` 的一维整数张量,其中M等于 `shape[0] + 1` , 表示每行非零元素的在 `values` 中存储的起止位置。默认值:None。支持的数据类型为 `int16` , `int32` 和 `int64` 。
- **indices** (Tensor) - 形状为 `[N]` 的一维整数张量,其中N等于非零元素数量,表示每个元素的列索引值。默认值:None。支持的数据类型为 `int16` , `int32` 和 `int64` 。
- **values** (Tensor) - 形状为 `[N]` 的一维张量,用来表示索引对应的数值。默认值:None。
- **shape** (tuple(int)) - 形状为ndims的整数元组,用来指定稀疏矩阵的稠密形状。目前只支持2维CSRTensor,所以 `shape` 长度只能为2。`shape[0]` 表示行数,因此必须和 `indptr[0] - 1` 值相等。默认值:None。
- **shape** (tuple(int)) - 形状为ndims的整数元组,用来指定稀疏矩阵的稠密形状。目前只支持2维CSRTensor,所以 `shape` 长度只能为2。`shape[0]` 表示行数,因此必须和 `M - 1` 值相等。默认值:None。
- **csr_tensor** (CSRTensor) - CSRTensor对象,用来初始化新的CSRTensor。默认值:None。

**输出:**
@@ -69,7 +69,7 @@ mindspore.CSRTensor

**参数:**

- **dense_vector** (Tensor) - 形状为 `[N,1]` 的维张量,其中N等于CSRTensor的列数。
- **dense_vector** (Tensor) - 形状为 `[N,1]` 的维张量,其中N等于CSRTensor的列数。

**返回:**



+ 57
- 39
mindspore/core/abstract/prim_others.cc View File

@@ -60,6 +60,19 @@ inline void CheckSparseShape(ShapeVector sparse_shp, ShapeVector dense_shp) {
}
}
}
inline void CheckSparseShape(const size_t shape_size, const size_t expected_dim, const std::string &arg_name) {
if (shape_size != expected_dim) {
MS_EXCEPTION(mindspore::ValueError) << arg_name << " must be a " << expected_dim
<< "-dimensional tensor, but got a " << shape_size << "-dimensional tensor.";
}
}
inline void CheckSparseIndicesDtype(const mindspore::TypePtr data_type, const std::string &arg_name) {
if (!(data_type->equal(mindspore::kInt16) || data_type->equal(mindspore::kInt32) ||
data_type->equal(mindspore::kInt64))) {
MS_EXCEPTION(mindspore::TypeError) << "The dtype of " << arg_name << " must be Int16 or Int32 or Int64, but got "
<< data_type->ToString() << ".";
}
}
} // namespace

namespace mindspore {
@@ -370,19 +383,14 @@ AbstractBasePtr InferImplMakeCOOTensor(const AnalysisEnginePtr &, const Primitiv
auto dense_shape = CheckArg<AbstractTuple>(op_name, args_spec_list, kIndexTwo);

auto indices_dtype = indices->element()->BuildType();
if (!indices_dtype->isa<Int>()) {
MS_EXCEPTION(TypeError) << "The dtype of indices must be a Int, but got " << indices_dtype->ToString();
}
CheckSparseIndicesDtype(indices_dtype, "indices");

auto indices_shp = indices->shape()->shape();
if (indices_shp.size() != kSizeTwo) {
MS_EXCEPTION(TypeError) << "Indices must be a 2 dimensional tensor, but got a " << indices_shp.size()
<< " dimension tensor";
}
CheckSparseShape(indices_shp.size(), kSizeTwo, "Indices");

auto values_shp = values->shape()->shape();
if (values_shp.size() != kSizeOne) {
MS_EXCEPTION(TypeError) << "Values must be a 1 dimensional tensor, but got a " << values_shp.size()
<< " dimension tensor";
}
CheckSparseShape(values_shp.size(), kSizeOne, "Values");

if (indices_shp[kIndexZero] != values_shp[kIndexZero]) {
MS_EXCEPTION(TypeError) << "Indices and values must equal in their shape, but got indices shape: " << indices_shp[0]
<< ", values shape: " << values_shp[kIndexZero];
@@ -506,14 +514,19 @@ AbstractBasePtr InferImplCSRMV(const AnalysisEnginePtr &, const PrimitivePtr &pr
<< "but sparse tensor has " << sparse_shape.size() << " dimensions, "
<< "and dense tensor has " << dense_shape.size() << " dimensions, ";
}
if (dense_shape[kIndexZero] != sparse_shape[kIndexOne] || dense_shape[kIndexOne] != 1) {
MS_EXCEPTION(ValueError) << "The dense_vector's shape should be (" << sparse_shape[kIndexOne] << ", 1)"
<< ", but its current shape is: "
<< "(" << dense_shape[kIndexZero] << ", " << dense_shape[kIndexOne] << ").";
}

MS_EXCEPTION_IF_NULL(sparse->values()->element());
ShapeVector out_shape = {sparse_shape[0], dense_shape[1]};
ShapeVector out_shape = {sparse_shape[kIndexZero], dense_shape[kIndexOne]};
auto ret = std::make_shared<AbstractTensor>(sparse->values()->element()->BuildType(), out_shape);

MS_EXCEPTION_IF_NULL(sparse->indices()->shape());
auto nnz_vec = sparse->indices()->shape()->shape();
auto csr_avg_rows = nnz_vec[0] / dense_shape[0];
auto csr_avg_rows = nnz_vec[kIndexZero] / dense_shape[kIndexZero];
primitive->set_attr(kCSRAvgRows, MakeValue(csr_avg_rows));
primitive->set_attr(kCSRDenseShape, MakeValue(sparse_shape));
primitive->set_attr(kIsCSR, MakeValue(true));
@@ -672,34 +685,25 @@ AbstractBasePtr InferImplMakeCSRTensor(const AnalysisEnginePtr &, const Primitiv
auto values = CheckArg<AbstractTensor>(op_name, args_spec_list, kIndexTwo);
auto shape = CheckArg<AbstractTuple>(op_name, args_spec_list, kIndexThree);

auto indptr_dtype = indptr->element()->BuildType();
auto indices_dtype = indices->element()->BuildType();
if (!indices_dtype->isa<Int>()) {
MS_EXCEPTION(TypeError) << "The dtype of indices must be a Int, but got " << indices_dtype->ToString();
}
CheckSparseIndicesDtype(indptr_dtype, "indptr");
CheckSparseIndicesDtype(indices_dtype, "indices");
auto indptr_shp = indptr->shape()->shape();
if (indptr_shp.size() != 1) {
MS_EXCEPTION(ValueError) << "Indptr must be a 1-dimensional tensor, but got a " << indptr_shp.size()
<< "-dimensional tensor";
}
CheckSparseShape(indptr_shp.size(), kSizeOne, "Indptr");

auto indices_shp = indices->shape()->shape();
if (indices_shp.size() != 1) {
MS_EXCEPTION(ValueError) << "Indices must be a 1-dimensional tensor, but got a " << indices_shp.size()
<< "-dimensional tensor";
}
CheckSparseShape(indices_shp.size(), kSizeOne, "Indices");

auto values_shp = values->shape()->shape();
if (values_shp.size() != 1) {
MS_EXCEPTION(ValueError) << "Values must be a 1-dimensional tensor, but got a " << values_shp.size()
<< "-dimensional tensor";
}
if (indices_shp[0] != values_shp[0]) {
MS_EXCEPTION(ValueError) << "Indices and values must have same size, but got: values length: " << values_shp[0]
<< ", indices length " << indices_shp[0];
}
for (const auto &elem_type : shape->ElementsType()) {
if (!elem_type->isa<Int>()) {
MS_EXCEPTION(TypeError) << "The element type of shape must be Int, but got " << elem_type->ToString();
}
CheckSparseShape(values_shp.size(), kSizeOne, "Values");

if (indices_shp[kIndexZero] != values_shp[kIndexZero]) {
MS_EXCEPTION(ValueError) << "Indices and values must have same size, but got: values length: "
<< values_shp[kIndexZero] << ", indices length " << indices_shp[kIndexZero];
}

auto shape_value = shape->BuildValue()->cast<ValueTuplePtr>();
MS_EXCEPTION_IF_NULL(shape_value);
auto shp = shape_value->value();
@@ -708,19 +712,33 @@ AbstractBasePtr InferImplMakeCSRTensor(const AnalysisEnginePtr &, const Primitiv
auto elem = GetValue<int64_t>(e);
return elem;
});
if (shape_vec.size() != kSizeTwo) {
MS_EXCEPTION(ValueError) << "Currently only supports 2-dimensional csr tensor, got shape length = "
<< shape_vec.size() << ".";
}
if (values_shp.size() + 1 != shape_vec.size()) {
MS_EXCEPTION(ValueError) << "Values' dimension should equal to csr_tensor's dimension - 1.";
}
if (shape_vec[0] + 1 != indptr_shp[0]) {
MS_EXCEPTION(ValueError) << "Indptr must have length (1 + shape[0]), but got: " << indptr_shp[0];
if (shape_vec[kIndexZero] + 1 != indptr_shp[kIndexZero]) {
MS_EXCEPTION(ValueError) << "Indptr must have length (1 + shape[0]), but got: " << indptr_shp[kIndexZero];
}
size_t shape_size = 1;
auto shape_types = shape->ElementsType();
for (size_t i = 0; i < shape_vec.size(); ++i) {
if (shape_vec[i] <= 0) {
MS_EXCEPTION(TypeError) << "The element of shape must be positive, but got " << shape_value->ToString();
MS_EXCEPTION(ValueError) << "The element of shape must be positive, but got " << shape_value->ToString();
}
if ((i > 1) && (shape_vec[i] != values_shp[i - 1])) {
MS_EXCEPTION(ValueError) << "csr_tensor's shape should match with values' shape.";
}
if (!shape_types[i]->isa<Int>()) {
MS_EXCEPTION(TypeError) << "The element type of shape must be Int, but got " << shape_types[i]->ToString();
}
shape_size *= shape_vec[i];
}
if (static_cast<int64_t>(shape_size) < values_shp[kIndexZero]) {
MS_EXCEPTION(ValueError) << "Shape total size: " << shape_size << " is too small to hold " << values_shp[kIndexZero]
<< " non-zero values.";
}
auto ret = std::make_shared<AbstractCSRTensor>(values->element()->BuildType(), shape_vec);
ret->set_indptr(indptr);


+ 9
- 5
mindspore/python/mindspore/_checkparam.py View File

@@ -874,19 +874,23 @@ class Validator:
def check_csr_tensor_input(indptr, indices, values, shape):
"""Checks inputs type for CSRTensor."""
if not isinstance(indptr, Tensor_):
raise TypeError(f"indptr should be Tensor, but got {type(indices)}.")
raise TypeError(f"indptr should be Tensor, but got {type(indptr)}.")
Validator.check_sparse_tensor_input(indices, values, shape)

@staticmethod
def check_csr_tensor_shape(indptr_shp, indices_shp, values_shp, csr_shp):
"""Checks input tensors' shapes for CSRTensor."""
if len(csr_shp) != 2:
raise ValueError("Currently only supports 2-dimensional csr tensor.")
raise ValueError(f"Currently only supports 2-dimensional csr tensor, got `shape length`={len(csr_shp)}.")
shape_size = 1
for item in csr_shp:
if item <= 0:
raise ValueError(f"The element of shape must be positive, but got {item}")
if not isinstance(item, int):
raise TypeError(f"The element type of shape must be int, but got {type(item)}")
shape_size *= item
if shape_size < values_shp[0]:
raise ValueError(f"Shape total size: {shape_size} is too small to hold {values_shp[0]} non-zero values.")
if len(values_shp) != 1:
raise ValueError(f"Values must be a 1-dimensional tensor, but got a {len(values_shp)} dimension tensor.")
if len(indices_shp) != 1:
@@ -904,9 +908,9 @@ class Validator:
def check_csr_tensor_dtype(indptr_dtype, indices_dtype):
"""Checks input tensors' data types for CSRTensor."""
if indptr_dtype not in (mstype.int16, mstype.int32, mstype.int64):
raise TypeError("Indptr must have integer data type.")
raise TypeError(f"Indptr must have int16 or int32 or int64 data type, but got {indptr_dtype}.")
if indices_dtype not in (mstype.int16, mstype.int32, mstype.int64):
raise TypeError("Indices must have integer data type.")
raise TypeError(f"Indices must have int16 or int32 or int64 data type, but got {indices_dtype}.")

@staticmethod
def check_coo_tensor_input(indices, values, shape):
@@ -938,7 +942,7 @@ class Validator:
def check_coo_tensor_dtype(indices_dtype):
"""Checks input tensors' data types for COOTensor."""
if indices_dtype not in (mstype.int16, mstype.int32, mstype.int64):
raise TypeError("Indices must have integer data type.")
raise TypeError(f"Indices must have int16 or int32 or int64 data type, but got {indices_dtype}.")


def check_input_format(input_param):


+ 1
- 0
mindspore/python/mindspore/_extends/parse/standard_method.py View File

@@ -1929,6 +1929,7 @@ def csr_abs(x):

def csr_mv(x, dense_vector):
"""Implementation of `abs` for CSRTensor."""
check_value_type('dense_vector', dense_vector, (Tensor_,), 'Tensor')
return F.csr_mv(x, dense_vector)




+ 6
- 5
mindspore/python/mindspore/common/tensor.py View File

@@ -2637,17 +2637,17 @@ class CSRTensor(CSRTensor_):
If the length of values or indices exceeds the range indicated by indptr, its behavior will be undefined.

Args:
indptr (Tensor): 1-D Tensor of size `shape[0] + 1`, which indicates the
indptr (Tensor): 1-D Tensor of shape `[M]`, which equals to `shape[0] + 1`, which indicates the
start and end point for `values` in each row. Default: None. If provided,
must be :class:`mindspore.int16`, :class:`mindspore.int32` or :class:`mindspore.int64`.
indices (Tensor): 1-D Tensor, which has the same length as `values`. `indices`
indices (Tensor): 1-D Tensor of shape `[N]`, which has the same length as `values`. `indices`
indicates the which column `values` should be placed. Default: None. If provided,
must be :class:`mindspore.int16`, :class:`mindspore.int32` or :class:`mindspore.int64`.
values (Tensor): 1-D Tensor, which has the same length as `indices`. `values`
values (Tensor): 1-D Tensor of shape `[N]`, which has the same length as `indices`. `values`
stores the data for CSRTensor. Default: None.
shape (Tuple): A tuple indicates the shape of the CSRTensor, its length must
be `2`, as only 2-D CSRTensor is currently supported, and `shape[0]` must
equal to `indptr[0] - 1`, which all equal to number of rows of the CSRTensor. Default: None.
equal to `M - 1`, which all equal to number of rows of the CSRTensor. Default: None.
csr_tensor (CSRTensor): A CSRTensor object. Default: None.

Outputs:
@@ -2814,7 +2814,7 @@ class CSRTensor(CSRTensor_):
Sparse matrix-vector multiplication.

Args:
dense_vector (Tensor) - A dense Tensor.
dense_vector (Tensor) - A dense Tensor, its shape must be (csr_tensor.shape[1], 1)

Returns:
Tensor.
@@ -2835,6 +2835,7 @@ class CSRTensor(CSRTensor_):
[[2.]
[1.]]
"""
validator.check_value_type('dense_vector', dense_vector, (Tensor_,), 'Tensor')
return tensor_operator_registry.get("csr_mv")(self, dense_vector)

def sum(self, axis):


Loading…
Cancel
Save