diff --git a/mindspore/ops/composite/multitype_ops/_constexpr_utils.py b/mindspore/ops/composite/multitype_ops/_constexpr_utils.py index 8bc337010a..dac8949fdc 100644 --- a/mindspore/ops/composite/multitype_ops/_constexpr_utils.py +++ b/mindspore/ops/composite/multitype_ops/_constexpr_utils.py @@ -57,6 +57,26 @@ def check_equal(param1, param2, msg="{},{}"): return param1 +@constexpr +def check_int_positive(arg_name, arg_value, op_name): + """Int type judgment.""" + if isinstance(arg_value, int): + if arg_value > 0: + return arg_value + raise ValueError("For \'{}\' the `{}` must be positive, but got {}".format(op_name, arg_name, arg_value)) + raise TypeError("For \'{}\' the `{}` must be int, cannot be {}".format(op_name, arg_name, type(arg_value))) + + +@constexpr +def check_non_negative(arg_name, arg_value, op_name): + """Int type judgment.""" + if isinstance(arg_value, int): + if arg_value >= 0: + return arg_value + raise ValueError("For \'{}\' the `{}` must be non_negative, but got {}".format(op_name, arg_name, arg_value)) + raise TypeError("For \'{}\' the `{}` must be int, cannot be {}".format(op_name, arg_name, type(arg_value))) + + @constexpr def check_ellipsis_shape_size(data_shape, value_shape, data_size, value_size): """Checks the shape and size of the sensor and value.""" diff --git a/mindspore/ops/composite/random_ops.py b/mindspore/ops/composite/random_ops.py index d682f15031..00da9303bb 100644 --- a/mindspore/ops/composite/random_ops.py +++ b/mindspore/ops/composite/random_ops.py @@ -21,7 +21,6 @@ from ..primitive import constexpr from .multitype_ops import _constexpr_utils as const_utils from ...common import dtype as mstype from ..._checkparam import Validator as validator -from ..._checkparam import check_int_positive from ..._checkparam import Rel # set graph-level RNG seed @@ -41,7 +40,7 @@ def set_seed(seed): Examples: >>> C.set_seed(10) """ - check_int_positive(seed) + const_utils.check_int_positive("seed", seed, "set_seed") global _GRAPH_SEED _GRAPH_SEED = seed @@ -61,7 +60,6 @@ def get_seed(): """ return _GRAPH_SEED - def normal(shape, mean, stddev, seed=0): """ Generates random numbers according to the Normal (or Gaussian) random number distribution. @@ -88,59 +86,14 @@ def normal(shape, mean, stddev, seed=0): stddev_dtype = F.dtype(stddev) const_utils.check_tensors_dtype_same(mean_dtype, mstype.float32, "normal") const_utils.check_tensors_dtype_same(stddev_dtype, mstype.float32, "normal") + const_utils.check_non_negative("seed", seed, "normal") seed1 = get_seed() seed2 = seed stdnormal = P.StandardNormal(seed1, seed2) - rnd = stdnormal(shape) - value = rnd * stddev + mean + random_normal = stdnormal(shape) + value = random_normal * stddev + mean return value - -def multinomial(inputs, num_sample=None, replacement=True, seed=0): - r""" - Returns a tensor sampled from the multinomial probability distribution located in the corresponding - row of tensor input. - - Note: - The rows of input do not need to sum to one (in which case we use the values as weights), - but must be non-negative, finite and have a non-zero sum. - Args: - seed (int): Seed data is used as entropy source for Random number engines generating pseudo-random numbers. - Default: 0. - - Inputs: - - **input** (Tensor) - the input tensor containing probabilities, must be 1 or 2 dims. - - **num_samples** (int) - number of samples to draw, default None. - - **replacement** (bool, optional) - whether to draw with replacement or not, default True. - - Outputs: - Tensor. have the same rows with input, each row has num_samples sampled indices. - - Examples: - >>> input = Tensor([0, 9, 4, 0], mstype.float32) - >>> output = C.multinomial(input, 2, True) - """ - shape = P.Shape() - reshape = P.Reshape() - validator.check_value_type('replacement', replacement, (bool,), None) - validator.check_value_type('num_sample', num_sample, (int,), None) - validator.check_integer("num_sample", num_sample, 0, Rel.GT, None) - if inputs.dim() != 1 and inputs.dim() != 2: - raise ValueError("inputs dim must be 1d or 2d") - if not replacement: - if shape(inputs)[-1] < num_sample: - raise ValueError("num_sample must be less than shape(input)[-1] without replacement") - n_dist = 1 - if len(shape(inputs)) > 1: - n_dist = shape(inputs)[-2] - random_uniform = P.UniformReal(seed=seed)((n_dist * num_sample,)) - if n_dist != 1: - random_uniform = reshape(random_uniform, (n_dist, num_sample)) - vals = P.RealDiv()(P.Log()(random_uniform), inputs + 1e-6) - _, indices = P.TopK()(vals, num_sample) - return indices - return P.Multinomial(seed=seed)(inputs, num_sample) - def uniform(shape, a, b, seed=0, dtype=mstype.float32): """ Generates random numbers according to the Uniform random number distribution. @@ -158,27 +111,35 @@ def uniform(shape, a, b, seed=0, dtype=mstype.float32): Returns: Tensor. The shape should be the broadcasted shape of Input "shape" and shapes of a and b. - The dtype is float32. + The dtype is designated as the input `dtype`. Examples: - >>> shape = (4, 16) - >>> a = Tensor(1.0, mstype.float32) - >>> b = Tensor(1.0, mstype.float32) + >>> For discrete uniform distribution, only one number is allowed for both a and b: + >>> shape = (4, 2) + >>> a = Tensor(1, mstype.int32) + >>> b = Tensor(2, mstype.int32) + >>> output = C.uniform(shape, a, b, seed=5) + >>> + >>> For continuous uniform distribution, a and b can be multi-dimentional: + >>> shape = (4, 2) + >>> a = Tensor([1.0, 2.0], mstype.float32) + >>> b = Tensor([4.0, 5.0], mstype.float32) >>> output = C.uniform(shape, a, b, seed=5) """ a_dtype = F.dtype(a) b_dtype = F.dtype(b) const_utils.check_tensors_dtype_same(a_dtype, dtype, "uniform") const_utils.check_tensors_dtype_same(b_dtype, dtype, "uniform") + const_utils.check_non_negative("seed", seed, "uniform") seed1 = get_seed() seed2 = seed if const_utils.is_same_type(dtype, mstype.int32): - rnd = P.UniformInt(seed1, seed2) - value = rnd(shape, a, b) + random_uniform = P.UniformInt(seed1, seed2) + value = random_uniform(shape, a, b) else: uniform_real = P.UniformReal(seed1, seed2) - rnd = uniform_real(shape) - value = rnd * (b - a) + a + random_uniform = uniform_real(shape) + value = random_uniform * (b - a) + a return value def gamma(shape, alpha, beta, seed=0): @@ -206,6 +167,7 @@ def gamma(shape, alpha, beta, seed=0): beta_dtype = F.dtype(beta) const_utils.check_tensors_dtype_same(alpha_dtype, mstype.float32, "gamma") const_utils.check_tensors_dtype_same(beta_dtype, mstype.float32, "gamma") + const_utils.check_non_negative("seed", seed, "gamma") seed1 = get_seed() seed2 = seed random_gamma = P.Gamma(seed1, seed2) @@ -233,8 +195,56 @@ def poisson(shape, mean, seed=0): """ mean_dtype = F.dtype(mean) const_utils.check_tensors_dtype_same(mean_dtype, mstype.float32, "poisson") + const_utils.check_non_negative("seed", seed, "poisson") seed1 = get_seed() seed2 = seed random_poisson = P.Poisson(seed1, seed2) value = random_poisson(shape, mean) return value + +def multinomial(inputs, num_sample=None, replacement=True, seed=0): + r""" + Returns a tensor sampled from the multinomial probability distribution located in the corresponding + row of tensor input. + + Note: + The rows of input do not need to sum to one (in which case we use the values as weights), + but must be non-negative, finite and have a non-zero sum. + Args: + seed (int): Seed data is used as entropy source for Random number engines generating pseudo-random numbers. + Default: 0. + + Inputs: + - **input** (Tensor) - the input tensor containing probabilities, must be 1 or 2 dims. + - **num_samples** (int) - number of samples to draw, default None. + - **replacement** (bool, optional) - whether to draw with replacement or not, default True. + + Outputs: + Tensor. have the same rows with input, each row has num_samples sampled indices. + + Examples: + >>> input = Tensor([0, 9, 4, 0], mstype.float32) + >>> output = C.multinomial(input, 2, True) + """ + shape = P.Shape() + reshape = P.Reshape() + validator.check_value_type('replacement', replacement, (bool,), None) + validator.check_value_type('num_sample', num_sample, (int,), None) + validator.check_integer("num_sample", num_sample, 0, Rel.GT, None) + if inputs.dim() != 1 and inputs.dim() != 2: + raise ValueError("inputs dim must be 1d or 2d") + if not replacement: + if shape(inputs)[-1] < num_sample: + raise ValueError("num_sample must be less than shape(input)[-1] without replacement") + n_dist = 1 + if len(shape(inputs)) > 1: + n_dist = shape(inputs)[-2] + a = Tensor(0.0, mstype.float32) + b = Tensor(1.0, mstype.float32) + random_uniform = P.UniformReal(seed=seed)((n_dist * num_sample,), a, b) + if n_dist != 1: + random_uniform = reshape(random_uniform, (n_dist, num_sample)) + vals = P.RealDiv()(P.Log()(random_uniform), inputs + 1e-6) + _, indices = P.TopK()(vals, num_sample) + return indices + return P.Multinomial(seed=seed)(inputs, num_sample) diff --git a/mindspore/ops/operations/random_ops.py b/mindspore/ops/operations/random_ops.py index a303f58dc7..61d659f00f 100644 --- a/mindspore/ops/operations/random_ops.py +++ b/mindspore/ops/operations/random_ops.py @@ -46,8 +46,8 @@ class StandardNormal(PrimitiveWithInfer): def __init__(self, seed=0, seed2=0): """Init StandardNormal""" self.init_prim_io_names(inputs=['shape'], outputs=['output']) - validator.check_value_type('seed', seed, [int], self.name) - validator.check_value_type('seed2', seed2, [int], self.name) + validator.check_integer("seed", seed, 0, Rel.GE, self.name) + validator.check_integer("seed2", seed2, 0, Rel.GE, self.name) def __infer__(self, shape): shape_v = shape["value"] @@ -151,8 +151,8 @@ class Gamma(PrimitiveWithInfer): def __init__(self, seed=0, seed2=0): """Init Gamma""" self.init_prim_io_names(inputs=['shape', 'alpha', 'beta'], outputs=['output']) - validator.check_value_type('seed', seed, [int], self.name) - validator.check_value_type('seed2', seed2, [int], self.name) + validator.check_integer("seed", seed, 0, Rel.GE, self.name) + validator.check_integer("seed2", seed2, 0, Rel.GE, self.name) def __infer__(self, shape, alpha, beta): shape_v = shape["value"] @@ -203,8 +203,8 @@ class Poisson(PrimitiveWithInfer): def __init__(self, seed=0, seed2=0): """Init Poisson""" self.init_prim_io_names(inputs=['shape', 'mean'], outputs=['output']) - validator.check_value_type('seed', seed, [int], self.name) - validator.check_value_type('seed2', seed2, [int], self.name) + validator.check_integer("seed", seed, 0, Rel.GE, self.name) + validator.check_integer("seed2", seed2, 0, Rel.GE, self.name) def __infer__(self, shape, mean): shape_v = shape["value"] @@ -259,8 +259,8 @@ class UniformInt(PrimitiveWithInfer): def __init__(self, seed=0, seed2=0): """Init UniformInt""" self.init_prim_io_names(inputs=['shape', 'a', 'b'], outputs=['output']) - validator.check_value_type('seed', seed, [int], self.name) - validator.check_value_type('seed2', seed2, [int], self.name) + validator.check_integer("seed", seed, 0, Rel.GE, self.name) + validator.check_integer("seed2", seed2, 0, Rel.GE, self.name) def __infer__(self, shape, a, b): shape_v = shape["value"] @@ -306,8 +306,8 @@ class UniformReal(PrimitiveWithInfer): def __init__(self, seed=0, seed2=0): """Init UniformReal""" self.init_prim_io_names(inputs=['shape'], outputs=['output']) - validator.check_value_type('seed', seed, [int], self.name) - validator.check_value_type('seed2', seed2, [int], self.name) + validator.check_integer("seed", seed, 0, Rel.GE, self.name) + validator.check_integer("seed2", seed2, 0, Rel.GE, self.name) def __infer__(self, shape): shape_v = shape["value"]