You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

random_ops.py 17 kB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. # Copyright 2020 Huawei Technologies Co., Ltd
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. # ============================================================================
  15. """Operations for random number generators."""
  16. from mindspore.ops.primitive import constexpr
  17. from .. import operations as P
  18. from .. import functional as F
  19. from .multitype_ops import _constexpr_utils as const_utils
  20. from ...common import dtype as mstype
  21. from ...common.seed import _get_graph_seed
  22. @constexpr
  23. def _get_seed(op_seed, kernel_name):
  24. "Get the graph-level seed."
  25. return _get_graph_seed(op_seed, kernel_name)
  26. def normal(shape, mean, stddev, seed=None):
  27. """
  28. Generates random numbers according to the Normal (or Gaussian) random number distribution.
  29. Args:
  30. shape (tuple): The shape of random tensor to be generated.
  31. The format is :math:`(N,*)` where :math:`*` means, any number of additional dimensions.
  32. mean (Tensor): The mean μ distribution parameter, which specifies the location of the peak,
  33. with data type in [int8, int16, int32, int64, float16, float32].
  34. stddev (Tensor): The deviation σ distribution parameter. It should be greater than 0,
  35. with data type in [int8, int16, int32, int64, float16, float32].
  36. seed (int): Seed is used as entropy source for the Random number engines to generate pseudo-random numbers.
  37. must be non-negative. Default: None, which will be treated as 0.
  38. Returns:
  39. Tensor. The shape should be equal to the broadcasted shape between the input `shape` and shapes
  40. of `mean` and `stddev`.
  41. The dtype is float32.
  42. Supported Platforms:
  43. ``Ascend`` ``GPU`` ``CPU``
  44. Examples:
  45. >>> shape = (3, 1, 2)
  46. >>> mean = Tensor(np.array([[3, 4], [5, 6]]), mindspore.float32)
  47. >>> stddev = Tensor(1.0, mindspore.float32)
  48. >>> output = ops.normal(shape, mean, stddev, seed=5)
  49. >>> result = output.shape
  50. >>> print(result)
  51. (3, 2, 2)
  52. >>> shape = (3, 1, 3)
  53. >>> mean = Tensor(np.array([[3, 4, 3], [3, 5, 6]]), mindspore.float32)
  54. >>> stddev = Tensor(1.0, mindspore.float32)
  55. >>> output = ops.normal(shape, mean, stddev, seed=5)
  56. >>> result = output.shape
  57. >>> print(result)
  58. (3, 2, 3)
  59. >>> shape = (3, 1, 3)
  60. >>> mean = Tensor(np.array([[1, 2, 3], [3, 4, 3], [3, 5, 6]]), mindspore.float32)
  61. >>> stddev = Tensor(1.0, mindspore.float32)
  62. >>> output = ops.normal(shape, mean, stddev, seed=5)
  63. >>> result = output.shape
  64. >>> print(result)
  65. (3, 3, 3)
  66. """
  67. mean_dtype = F.dtype(mean)
  68. stddev_dtype = F.dtype(stddev)
  69. const_utils.check_type_valid(mean_dtype, mstype.int_type + (mstype.float16, mstype.float32), 'normal')
  70. const_utils.check_type_valid(stddev_dtype, mstype.int_type + (mstype.float16, mstype.float32), 'normal')
  71. seed1, seed2 = _get_seed(seed, "normal")
  72. stdnormal = P.StandardNormal(seed1, seed2)
  73. random_normal = stdnormal(shape)
  74. value = random_normal * stddev + mean
  75. return value
  76. def laplace(shape, mean, lambda_param, seed=None):
  77. r"""
  78. Generates random numbers according to the Laplace random number distribution.
  79. It is defined as:
  80. .. math::
  81. \text{f}(x;μ,λ) = \frac{1}{2λ}\exp(-\frac{|x-μ|}{λ}),
  82. Args:
  83. shape (tuple): The shape of random tensor to be generated.
  84. The format is :math:`(N,*)` where :math:`*` means, any number of additional dimensions.
  85. mean (Tensor): The mean μ distribution parameter, which specifies the location of the peak.
  86. With float32 data type.
  87. lambda_param (Tensor): The parameter used for controlling the variance of this random distribution. The
  88. variance of Laplace distribution is equal to twice the square of lambda_param. With float32 data type.
  89. seed (int): Seed is used as entropy source for Random number engines generating pseudo-random numbers.
  90. Default: None, which will be treated as 0.
  91. Returns:
  92. Tensor. The shape should be the broadcasted shape of input `shape` and shapes of `mean` and `lambda_param`.
  93. The dtype is float32.
  94. Supported Platforms:
  95. ``Ascend``
  96. Examples:
  97. >>> import mindspore
  98. >>> from mindspore import Tensor
  99. >>> from mindspore import ops as ops
  100. >>> shape = (2, 3)
  101. >>> mean = Tensor(1.0, mindspore.float32)
  102. >>> lambda_param = Tensor(1.0, mindspore.float32)
  103. >>> output = ops.laplace(shape, mean, lambda_param, seed=5)
  104. >>> print(output.shape)
  105. (2, 3)
  106. """
  107. mean_dtype = F.dtype(mean)
  108. lambda_param_dtype = F.dtype(lambda_param)
  109. const_utils.check_tensors_dtype_same(mean_dtype, mstype.float32, "laplace")
  110. const_utils.check_tensors_dtype_same(lambda_param_dtype, mstype.float32, "laplace")
  111. seed1, seed2 = _get_seed(seed, "laplace")
  112. stdlaplace = P.StandardLaplace(seed1, seed2)
  113. rnd = stdlaplace(shape)
  114. value = rnd * lambda_param + mean
  115. return value
  116. def uniform(shape, minval, maxval, seed=None, dtype=mstype.float32):
  117. """
  118. Generates random numbers according to the Uniform random number distribution.
  119. Note:
  120. The number in tensor minval should be strictly less than maxval at any position after broadcasting.
  121. Args:
  122. shape (tuple): The shape of random tensor to be generated.
  123. The format is :math:`(N,*)` where :math:`*` means, any number of additional dimensions
  124. and the length of :math:`(N,*)` should be less than 8 in broadcast operation.
  125. minval (Tensor): The distribution parameter `a`.
  126. It defines the minimum possible generated value, with int32 or float32 data type.
  127. If dtype is int32, only one number is allowed.
  128. maxval (Tensor): The distribution parameter `b`.
  129. It defines the maximum possible generated value, with int32 or float32 data type.
  130. If dtype is int32, only one number is allowed.
  131. seed (int): Seed is used as entropy source for the random number engines to generate pseudo-random numbers,
  132. must be non-negative. Default: None, which will be treated as 0.
  133. dtype (mindspore.dtype): Type of the Uniform distribution. If it is int32, it generates numbers from discrete
  134. uniform distribution; if it is float32, it generates numbers from continuous uniform distribution. It only
  135. supports these two data types. Default: mindspore.float32.
  136. Returns:
  137. Tensor. The shape should be equal to the broadcasted shape between the input `shape` and shapes
  138. of `minval` and `maxval`.
  139. The dtype is designated as the input `dtype`.
  140. Raises:
  141. TypeError: If `shape` is not tuple.
  142. TypeError: If 'minval' or 'maxval' is neither int32 nor float32
  143. and dtype of 'minval' is not the same as 'maxval'.
  144. TypeError: If `seed` is not an int.
  145. TypeError: If 'dtype' is neither int32 nor float32.
  146. Supported Platforms:
  147. ``Ascend`` ``GPU``
  148. Examples:
  149. >>> # For discrete uniform distribution, only one number is allowed for both minval and maxval:
  150. >>> shape = (4, 2)
  151. >>> minval = Tensor(1, mindspore.int32)
  152. >>> maxval = Tensor(2, mindspore.int32)
  153. >>> output = ops.uniform(shape, minval, maxval, seed=5, dtype=mindspore.int32)
  154. >>>
  155. >>> # For continuous uniform distribution, minval and maxval can be multi-dimentional:
  156. >>> shape = (3, 1, 2)
  157. >>> minval = Tensor(np.array([[3, 4], [5, 6]]), mindspore.float32)
  158. >>> maxval = Tensor([8.0, 10.0], mindspore.float32)
  159. >>> output = ops.uniform(shape, minval, maxval, seed=5)
  160. >>> result = output.shape
  161. >>> print(result)
  162. (3, 2, 2)
  163. """
  164. minval_dtype = F.dtype(minval)
  165. maxval_dtype = F.dtype(maxval)
  166. const_utils.check_type_valid(dtype, [mstype.int32, mstype.float32], 'uniform')
  167. const_utils.check_tensors_dtype_same(minval_dtype, dtype, "uniform")
  168. const_utils.check_tensors_dtype_same(maxval_dtype, dtype, "uniform")
  169. seed1, seed2 = _get_seed(seed, "uniform")
  170. if const_utils.is_same_type(dtype, mstype.int32):
  171. random_uniform = P.UniformInt(seed1, seed2)
  172. value = random_uniform(shape, minval, maxval)
  173. else:
  174. uniform_real = P.UniformReal(seed1, seed2)
  175. random_uniform = uniform_real(shape)
  176. value = random_uniform * (maxval - minval) + minval
  177. return value
  178. def gamma(shape, alpha, beta, seed=None):
  179. """
  180. Generates random numbers according to the Gamma random number distribution.
  181. Args:
  182. shape (tuple): The shape of random tensor to be generated.
  183. The format is :math:`(N,*)` where :math:`*` means, any number of additional dimensions.
  184. alpha (Tensor): The alpha α distribution parameter. It should be greater than 0 with float32 data type.
  185. beta (Tensor): The beta β distribution parameter. It should be greater than 0 with float32 data type.
  186. seed (int): Seed is used as entropy source for the random number engines to generate
  187. pseudo-random numbers, must be non-negative. Default: None, which will be treated as 0.
  188. Returns:
  189. Tensor. The shape should be equal to the broadcasted shape between the input `shape` and shapes
  190. of `alpha` and `beta`.
  191. The dtype is float32.
  192. Raises:
  193. TypeError: If `shape` is not a tuple.
  194. TypeError: If neither `alpha` nor `beta` is a Tensor.
  195. TypeError: If `seed` is not an int.
  196. TypeError: If dtype of `alpha` and `beta` is not float32.
  197. Supported Platforms:
  198. ``Ascend``
  199. Examples:
  200. >>> # case 1: alpha_shape is (2, 2)
  201. >>> shape = (3, 1, 2)
  202. >>> alpha = Tensor(np.array([[3, 4], [5, 6]]), mindspore.float32)
  203. >>> beta = Tensor(np.array([1.0]), mindspore.float32)
  204. >>> output = ops.gamma(shape, alpha, beta, seed=5)
  205. >>> result = output.shape
  206. >>> print(result)
  207. (3, 2, 2)
  208. >>> # case 2: alpha_shape is (2, 3), so shape is (3, 1, 3)
  209. >>> shape = (3, 1, 3)
  210. >>> alpha = Tensor(np.array([[1, 3, 4], [2, 5, 6]]), mindspore.float32)
  211. >>> beta = Tensor(np.array([1.0]), mindspore.float32)
  212. >>> output = ops.gamma(shape, alpha, beta, seed=5)
  213. >>> result = output.shape
  214. >>> print(result)
  215. (3, 2, 3)
  216. >>> # case 3: beta_shape is (1, 2), the output is different.
  217. >>> shape = (3, 1, 2)
  218. >>> alpha = Tensor(np.array([[3, 4], [5, 6]]), mindspore.float32)
  219. >>> beta = Tensor(np.array([1.0, 2]), mindspore.float32)
  220. >>> output = ops.gamma(shape, alpha, beta, seed=5)
  221. >>> result = output.shape
  222. >>> print(output)
  223. [[[ 2.2132034 5.8855834]]
  224. [ 3.3981476 7.5805717]
  225. [[ 3.3981476 7.5805717]]
  226. [ 3.7190282 19.941492]
  227. [[ 2.9512358 2.5969937]]
  228. [ 3.786061 5.160872 ]]]
  229. >>> # case 4: beta_shape is (2, 1), the output is different.
  230. >>> shape = (3, 1, 2)
  231. >>> alpha = Tensor(np.array([[3, 4], [5, 6]]), mindspore.float32)
  232. >>> beta = Tensor(np.array([[1.0], [2.0]]), mindspore.float32)
  233. >>> output = ops.gamma(shape, alpha, beta, seed=5)
  234. >>> result = output.shape
  235. >>> print(output)
  236. [[[ 5.6085486 7.8280783]]
  237. [ 15.97684 16.116285]
  238. [[ 1.8347423 1.713663]]
  239. [ 3.2434065 15.667398]
  240. [[ 4.2922077 7.3365674]]
  241. [ 5.3876944 13.159832 ]]]
  242. """
  243. seed1, seed2 = _get_seed(seed, "gamma")
  244. random_gamma = P.Gamma(seed1, seed2)
  245. value = random_gamma(shape, alpha, beta)
  246. return value
  247. def poisson(shape, mean, seed=None):
  248. r"""
  249. Generates random numbers according to the Poisson random number distribution.
  250. .. math::
  251. \text{P}(i|μ) = \frac{\exp(-μ)μ^{i}}{i!}
  252. Args:
  253. shape (tuple): The shape of random tensor to be generated.
  254. The format is :math:`(N,*)` where :math:`*` means, any number of additional dimensions.
  255. mean (Tensor): The mean μ distribution parameter. It should be greater than 0 with float32 data type.
  256. seed (int): Seed is used as entropy source for the random number engines to generate pseudo-random numbers
  257. and must be non-negative. Default: None, which will be treated as 0.
  258. Returns:
  259. Tensor. The shape should be equal to the broadcasted shape between the input "shape" and shapes of `mean`.
  260. The dtype is float32.
  261. Raises:
  262. TypeError: If `shape` is not a tuple.
  263. TypeError: If `mean` is not a Tensor whose dtype is not float32.
  264. TypeError: If `seed` is not an int.
  265. Supported Platforms:
  266. ``Ascend``
  267. Examples:
  268. >>> # case 1: It can be broadcast.
  269. >>> shape = (4, 1)
  270. >>> mean = Tensor(np.array([5.0, 10.0]), mindspore.float32)
  271. >>> output = ops.poisson(shape, mean, seed=5)
  272. >>> result = output.shape
  273. >>> print(result)
  274. (4, 2)
  275. >>> # case 2: It can not be broadcast. It is recommended to use the same shape.
  276. >>> shape = (2, 2)
  277. >>> mean = Tensor(np.array([[5.0, 10.0], [5.0, 1.0]]), mindspore.float32)
  278. >>> output = ops.poisson(shape, mean, seed=5)
  279. >>> result = output.shape
  280. >>> print(result)
  281. (2, 2)
  282. """
  283. seed1, seed2 = _get_seed(seed, "poisson")
  284. random_poisson = P.Poisson(seed1, seed2)
  285. value = random_poisson(shape, mean)
  286. return value
  287. def multinomial(inputs, num_sample, replacement=True, seed=None):
  288. r"""
  289. Returns a tensor sampled from the multinomial probability distribution located in the corresponding
  290. row of the input tensor.
  291. Note:
  292. The rows of input do not need to sum to one (in which case we use the values as weights),
  293. but must be non-negative, finite and have a non-zero sum.
  294. Args:
  295. x (Tensor): The input tensor containing probabilities, must be 1 or 2 dimensions, with
  296. float32 data type.
  297. num_sample (int): Number of samples to draw.
  298. replacement (bool, optional): Whether to draw with replacement or not, default True.
  299. seed (int, optional): Seed is used as entropy source for the random number engines to generate
  300. pseudo-random numbers, must be non-negative. Default: 0.
  301. Outputs:
  302. Tensor, has the same rows with input. The number of sampled indices of each row is `num_samples`.
  303. The dtype is float32.
  304. Raises:
  305. TypeError: If `x` is not a Tensor whose dtype is not float32.
  306. TypeError: If `num_sample` is not an int.
  307. TypeError: If `seed` is neither an int nor a optional.
  308. Supported Platforms:
  309. ``GPU``
  310. Examples:
  311. >>> # case 1: The output is random, and the length of the output is the same as num_sample.
  312. >>> x = Tensor([0, 9, 4, 0], mindspore.float32)
  313. >>> output = ops.multinomial(x, 2)
  314. >>> # print(output)
  315. >>> # [1 2] or [2 1]
  316. >>> # the case where the result is [2 1] in multiple times.
  317. >>> # This is because the value corresponding to the index 1 is larger than the value of the index 2.
  318. >>> print(len(output))
  319. 2
  320. >>> # case 2: The output is random, and the length of the output is the same as num_sample.
  321. >>> # replacement is False(Default).
  322. >>> # If the extracted value is 0, the index value of 1 will be returned.
  323. >>> x = Tensor([0, 9, 4, 0], mstype.float32)
  324. >>> output = ops.multinomial(x, 4)
  325. >>> print(output)
  326. [1 1 2 1]
  327. >>> # case 3: num_sample == x_length = 4, and replacement is True, Can extract the same elements。
  328. >>> x = Tensor([0, 9, 4, 0], mstype.float32)
  329. >>> output = ops.multinomial(x, 4, True)
  330. >>> print(output)
  331. [1 1 2 2]
  332. """
  333. shape = P.Shape()
  334. reshape = P.Reshape()
  335. const_utils.check_valid_dim(len(shape(inputs)), "multinomial")
  336. seed1, seed2 = _get_seed(seed, "multinomial")
  337. if not replacement:
  338. if shape(inputs)[-1] < num_sample:
  339. const_utils.raise_value_error("For 'multinomial', the 'num_sample' must be less than "
  340. "the last dimension of input without 'replacement', "
  341. "but got 'num_sample': {} and "
  342. "'replacement': {}".format(num_sample, replacement))
  343. n_dist = 1
  344. if len(shape(inputs)) > 1:
  345. n_dist = shape(inputs)[-2]
  346. random_uniform = P.UniformReal(seed1, seed2)((n_dist * shape(inputs)[-1],))
  347. if n_dist != 1:
  348. random_uniform = reshape(random_uniform, (n_dist, shape(inputs)[-1]))
  349. vals = P.RealDiv()(P.Log()(random_uniform), inputs + 1e-6)
  350. _, indices = P.TopK()(vals, num_sample)
  351. return indices
  352. return P.Multinomial(seed1, seed2)(inputs, num_sample)