From: @shallydeng Reviewed-by: @sunnybeike Signed-off-by: @sunnybeiketags/v1.1.0
| @@ -168,9 +168,12 @@ def check_sum_equal_one(probs): | |||||
| if not isinstance(probs.data, Tensor): | if not isinstance(probs.data, Tensor): | ||||
| return | return | ||||
| probs = probs.data | probs = probs.data | ||||
| prob_sum = np.sum(probs.asnumpy(), axis=-1) | |||||
| comp = np.equal(np.ones(prob_sum.shape), prob_sum) | |||||
| if not comp.all(): | |||||
| if isinstance(probs, Tensor): | |||||
| probs = probs.asnumpy() | |||||
| prob_sum = np.sum(probs, axis=-1) | |||||
| # add a small tolerance here to increase numerical stability | |||||
| comp = np.allclose(prob_sum, np.ones(prob_sum.shape), rtol=1e-14, atol=1e-14) | |||||
| if not comp: | |||||
| raise ValueError('Probabilities for each category should sum to one for Categorical distribution.') | raise ValueError('Probabilities for each category should sum to one for Categorical distribution.') | ||||
| def check_rank(probs): | def check_rank(probs): | ||||
| @@ -40,65 +40,84 @@ class Categorical(Distribution): | |||||
| `probs` must have rank at least 1, values are proper probabilities and sum to 1. | `probs` must have rank at least 1, values are proper probabilities and sum to 1. | ||||
| Examples: | Examples: | ||||
| >>> # To initialize a Categorical distribution of probs [0.5, 0.5] | |||||
| >>> import mindspore | |||||
| >>> import mindspore.nn as nn | |||||
| >>> import mindspore.nn.probability.distribution as msd | >>> import mindspore.nn.probability.distribution as msd | ||||
| >>> b = msd.Categorical(probs = [0.5, 0.5], dtype=mstype.int32) | |||||
| >>> | |||||
| >>> # To use a Categorical distribution in a network | |||||
| >>> class net(Cell): | |||||
| ... def __init__(self, probs): | |||||
| ... super(net, self).__init__(): | |||||
| ... self.ca = msd.Categorical(probs=[0.2, 0.8], dtype=mstype.int32) | |||||
| ... self.ca1 = msd.Categorical(dtype=mstype.int32) | |||||
| ... | |||||
| ... # All the following calls in construct are valid | |||||
| ... def construct(self, value): | |||||
| ... | |||||
| ... # Private interfaces of probability functions corresponding to public interfaces, including | |||||
| ... # `prob`, `log_prob`, `cdf`, `log_cdf`, `survival_function`, and `log_survival`, are the same as follows. | |||||
| ... # Args: | |||||
| ... # value (Tensor): the value to be evaluated. | |||||
| ... # probs (Tensor): event probabilities. Default: self.probs. | |||||
| ... | |||||
| ... # Examples of `prob`. | |||||
| ... # Similar calls can be made to other probability functions | |||||
| ... # by replacing `prob` by the name of the function. | |||||
| ... ans = self.ca.prob(value) | |||||
| ... # Evaluate `prob` with respect to distribution b. | |||||
| ... ans = self.ca.prob(value, probs_b) | |||||
| ... # `probs` must be passed in during function calls. | |||||
| ... ans = self.ca1.prob(value, probs_a) | |||||
| ... | |||||
| ... # Functions `mean`, `sd`, `var`, and `entropy` have the same arguments. | |||||
| ... # Args: | |||||
| ... # probs (Tensor): event probabilities. Default: self.probs. | |||||
| ... | |||||
| ... # Examples of `mean`. `sd`, `var`, and `entropy` are similar. | |||||
| ... ans = self.ca.mean() # return 0.8 | |||||
| ... ans = self.ca.mean(probs_b) | |||||
| ... # `probs` must be passed in during function calls. | |||||
| ... ans = self.ca1.mean(probs_a) | |||||
| ... | |||||
| ... # Interfaces of `kl_loss` and `cross_entropy` are the same as follows: | |||||
| ... # Args: | |||||
| ... # dist (str): the name of the distribution. Only 'Categorical' is supported. | |||||
| ... # probs_b (Tensor): event probabilities of distribution b. | |||||
| ... # probs (Tensor): event probabilities of distribution a. Default: self.probs. | |||||
| ... | |||||
| ... # Examples of kl_loss. `cross_entropy` is similar. | |||||
| ... ans = self.ca.kl_loss('Categorical', probs_b) | |||||
| ... ans = self.ca.kl_loss('Categorical', probs_b, probs_a) | |||||
| ... # An additional `probs` must be passed in. | |||||
| ... ans = self.ca1.kl_loss('Categorical', probs_b, probs_a) | |||||
| ... | |||||
| ... # Examples of `sample`. | |||||
| ... # Args: | |||||
| ... # shape (tuple): the shape of the sample. Default: (). | |||||
| ... # probs (Tensor): event probabilities. Default: self.probs. | |||||
| ... ans = self.ca.sample() | |||||
| ... ans = self.ca.sample((2,3)) | |||||
| ... ans = self.ca.sample((2,3), probs_b) | |||||
| ... ans = self.ca1.sample((2,3), probs_a) | |||||
| >>> from mindspore import Tensor | |||||
| >>> # To initialize a Categorical distribution of probs [0.5, 0.5] | |||||
| >>> ca1 = msd.Categorical(probs=[0.2, 0.8], dtype=mindspore.int32) | |||||
| >>> # A Categorical distribution can be initialized without arguments. | |||||
| >>> # In this case, `probs` must be passed in through arguments during function calls. | |||||
| >>> ca2 = msd.Categorical(dtype=mindspore.int32) | |||||
| >>> # Here are some tensors used below for testing | |||||
| >>> value = Tensor([1, 0], dtype=mindspore.int32) | |||||
| >>> probs_a = Tensor([0.5, 0.5], dtype=mindspore.float32) | |||||
| >>> probs_b = Tensor([0.35, 0.65], dtype=mindspore.float32) | |||||
| >>> # Private interfaces of probability functions corresponding to public interfaces, including | |||||
| >>> # `prob`, `log_prob`, `cdf`, `log_cdf`, `survival_function`, and `log_survival`, are the same as follows. | |||||
| >>> # Args: | |||||
| >>> # value (Tensor): the value to be evaluated. | |||||
| >>> # probs (Tensor): event probabilities. Default: self.probs. | |||||
| >>> # Examples of `prob`. | |||||
| >>> # Similar calls can be made to other probability functions | |||||
| >>> # by replacing `prob` by the name of the function. | |||||
| >>> ans = ca1.prob(value) | |||||
| >>> print(ans) | |||||
| [0.8 0.2] | |||||
| >>> # Evaluate `prob` with respect to distribution b. | |||||
| >>> ans = ca1.prob(value, probs_b) | |||||
| >>> print(ans) | |||||
| [0.65 0.35] | |||||
| >>> # `probs` must be passed in during function calls. | |||||
| >>> ans = ca2.prob(value, probs_a) | |||||
| >>> print(ans) | |||||
| [0.5 0.5] | |||||
| >>> # Functions `mean`, `sd`, `var`, and `entropy` have the same arguments. | |||||
| >>> # Args: | |||||
| >>> # probs (Tensor): event probabilities. Default: self.probs. | |||||
| >>> # Examples of `mean`. `sd`, `var`, and `entropy` are similar. | |||||
| >>> ans = ca1.mean() # return 0.8 | |||||
| >>> print(ans) | |||||
| [0.8] | |||||
| >>> ans = ca1.mean(probs_b) | |||||
| >>> print(ans) | |||||
| [0.65] | |||||
| >>> # `probs` must be passed in during function calls. | |||||
| >>> ans = ca2.mean(probs_a) | |||||
| >>> print(ans) | |||||
| [0.5] | |||||
| >>> # Interfaces of `kl_loss` and `cross_entropy` are the same as follows: | |||||
| >>> # Args: | |||||
| >>> # dist (str): the name of the distribution. Only 'Categorical' is supported. | |||||
| >>> # probs_b (Tensor): event probabilities of distribution b. | |||||
| >>> # probs (Tensor): event probabilities of distribution a. Default: self.probs. | |||||
| >>> # Examples of kl_loss. `cross_entropy` is similar. | |||||
| >>> ans = ca1.kl_loss('Categorical', probs_b) | |||||
| >>> print(ans) | |||||
| 0.05418826 | |||||
| >>> ans = ca1.kl_loss('Categorical', probs_b, probs_a) | |||||
| >>> print(ans) | |||||
| 0.04715523 | |||||
| >>> # An additional `probs` must be passed in. | |||||
| >>> ans = ca2.kl_loss('Categorical', probs_b, probs_a) | |||||
| >>> print(ans) | |||||
| 0.04715523 | |||||
| >>> # Examples of `sample`. | |||||
| >>> # Args: | |||||
| >>> # shape (tuple): the shape of the sample. Default: (). | |||||
| >>> # probs (Tensor): event probabilities. Default: self.probs. | |||||
| >>> ans = ca1.sample() | |||||
| >>> print(ans.shape) | |||||
| () | |||||
| >>> ans = ca1.sample((2,3)) | |||||
| >>> print(ans.shape) | |||||
| (2, 3) | |||||
| >>> ans = ca1.sample((2,3), probs_b) | |||||
| >>> print(ans.shape) | |||||
| (2, 3) | |||||
| >>> ans = ca2.sample((2,3), probs_a) | |||||
| >>> print(ans.shape) | |||||
| (2, 3) | |||||
| """ | """ | ||||
| def __init__(self, | def __init__(self, | ||||
| @@ -108,7 +127,7 @@ class Categorical(Distribution): | |||||
| name="Categorical"): | name="Categorical"): | ||||
| param = dict(locals()) | param = dict(locals()) | ||||
| param['param_dict'] = {'probs': probs} | param['param_dict'] = {'probs': probs} | ||||
| valid_dtype = mstype.int_type + mstype.float_type | |||||
| valid_dtype = mstype.uint_type + mstype.int_type + mstype.float_type | |||||
| Validator.check_type_name("dtype", dtype, valid_dtype, type(self).__name__) | Validator.check_type_name("dtype", dtype, valid_dtype, type(self).__name__) | ||||
| super(Categorical, self).__init__(seed, dtype, name, param) | super(Categorical, self).__init__(seed, dtype, name, param) | ||||
| @@ -116,7 +135,7 @@ class Categorical(Distribution): | |||||
| if self.probs is not None: | if self.probs is not None: | ||||
| check_rank(self.probs) | check_rank(self.probs) | ||||
| check_prob(self.probs) | check_prob(self.probs) | ||||
| check_sum_equal_one(self.probs) | |||||
| check_sum_equal_one(probs) | |||||
| # update is_scalar_batch and broadcast_shape | # update is_scalar_batch and broadcast_shape | ||||
| # drop one dimension | # drop one dimension | ||||
| @@ -124,7 +143,7 @@ class Categorical(Distribution): | |||||
| self._is_scalar_batch = True | self._is_scalar_batch = True | ||||
| self._broadcast_shape = self._broadcast_shape[:-1] | self._broadcast_shape = self._broadcast_shape[:-1] | ||||
| self.argmax = P.Argmax() | |||||
| self.argmax = P.ArgMaxWithValue(axis=-1) | |||||
| self.broadcast = broadcast_to | self.broadcast = broadcast_to | ||||
| self.cast = P.Cast() | self.cast = P.Cast() | ||||
| self.clip_by_value = C.clip_by_value | self.clip_by_value = C.clip_by_value | ||||
| @@ -140,6 +159,7 @@ class Categorical(Distribution): | |||||
| self.log = log_generic | self.log = log_generic | ||||
| self.log_softmax = P.LogSoftmax() | self.log_softmax = P.LogSoftmax() | ||||
| self.logicor = P.LogicalOr() | self.logicor = P.LogicalOr() | ||||
| self.logicand = P.LogicalAnd() | |||||
| self.multinomial = P.Multinomial(seed=self.seed) | self.multinomial = P.Multinomial(seed=self.seed) | ||||
| self.reshape = P.Reshape() | self.reshape = P.Reshape() | ||||
| self.reduce_sum = P.ReduceSum(keep_dims=True) | self.reduce_sum = P.ReduceSum(keep_dims=True) | ||||
| @@ -192,8 +212,9 @@ class Categorical(Distribution): | |||||
| def _mode(self, probs=None): | def _mode(self, probs=None): | ||||
| probs = self._check_param_type(probs) | probs = self._check_param_type(probs) | ||||
| mode = self.cast(self.argmax(probs), self.dtype) | |||||
| return self.squeeze(mode) | |||||
| index, _ = self.argmax(probs) | |||||
| mode = self.cast(index, self.dtype) | |||||
| return mode | |||||
| def _var(self, probs=None): | def _var(self, probs=None): | ||||
| r""" | r""" | ||||
| @@ -232,7 +253,7 @@ class Categorical(Distribution): | |||||
| probs_a = self._check_param_type(probs) | probs_a = self._check_param_type(probs) | ||||
| logits_a = self.log(probs_a) | logits_a = self.log(probs_a) | ||||
| logits_b = self.log(probs_b) | logits_b = self.log(probs_b) | ||||
| return self.squeeze(-self.reduce_sum( | |||||
| return self.squeeze(self.reduce_sum( | |||||
| self.softmax(logits_a) * (self.log_softmax(logits_a) - (self.log_softmax(logits_b))), -1)) | self.softmax(logits_a) * (self.log_softmax(logits_a) - (self.log_softmax(logits_b))), -1)) | ||||
| def _cross_entropy(self, dist, probs_b, probs=None): | def _cross_entropy(self, dist, probs_b, probs=None): | ||||
| @@ -256,10 +277,13 @@ class Categorical(Distribution): | |||||
| probs (Tensor): Event probabilities. Default: self.probs. | probs (Tensor): Event probabilities. Default: self.probs. | ||||
| """ | """ | ||||
| value = self._check_value(value, 'value') | value = self._check_value(value, 'value') | ||||
| # cast value to int to find the right integer to compute index | |||||
| if self.issubclass(self.dtype, mstype.float_): | if self.issubclass(self.dtype, mstype.float_): | ||||
| value = self.cast(value, self.index_type) | value = self.cast(value, self.index_type) | ||||
| else: | else: | ||||
| value = self.cast(value, self.dtype) | value = self.cast(value, self.dtype) | ||||
| # cast int to float for the broadcasting below | |||||
| value = self.cast(value, mstype.float32) | |||||
| probs = self._check_param_type(probs) | probs = self._check_param_type(probs) | ||||
| logits = self.log(probs) | logits = self.log(probs) | ||||
| @@ -289,6 +313,9 @@ class Categorical(Distribution): | |||||
| value = self.reshape(value, (-1, 1)) | value = self.reshape(value, (-1, 1)) | ||||
| out_of_bound = self.squeeze_last_axis(self.logicor(\ | out_of_bound = self.squeeze_last_axis(self.logicor(\ | ||||
| self.less(value, 0.0), self.less(num_classes-1, value))) | self.less(value, 0.0), self.less(num_classes-1, value))) | ||||
| # deal with the case the there is only one class. | |||||
| zeros = self.fill(mstype.float32, self.shape(out_of_bound), 0.0) | |||||
| out_of_bound = self.logicand(out_of_bound, self.less(zeros, num_classes-1)) | |||||
| value_clipped = self.clip_by_value(value, 0.0, num_classes - 1) | value_clipped = self.clip_by_value(value, 0.0, num_classes - 1) | ||||
| value_clipped = self.cast(value_clipped, self.index_type) | value_clipped = self.cast(value_clipped, self.index_type) | ||||
| # create index from 0 ... NumOfLabels | # create index from 0 ... NumOfLabels | ||||
| @@ -41,77 +41,91 @@ class Cauchy(Distribution): | |||||
| Cauchy distribution is not supported on GPU backend. | Cauchy distribution is not supported on GPU backend. | ||||
| Examples: | Examples: | ||||
| >>> # To initialize a Cauchy distribution of loc 3.0 and scale 4.0. | |||||
| >>> import mindspore | |||||
| >>> import mindspore.nn as nn | |||||
| >>> import mindspore.nn.probability.distribution as msd | >>> import mindspore.nn.probability.distribution as msd | ||||
| >>> cauchy = msd.Cauchy(3.0, 4.0, dtype=mstype.float32) | |||||
| >>> | |||||
| >>> # The following creates two independent Cauchy distributions. | |||||
| >>> cauchy = msd.Cauchy([3.0, 3.0], [4.0, 4.0], dtype=mstype.float32) | |||||
| >>> | |||||
| >>> from mindspore import Tensor | |||||
| >>> # To initialize a Cauchy distribution of loc 3.0 and scale 4.0. | |||||
| >>> cauchy1 = msd.Cauchy(3.0, 4.0, dtype=mindspore.float32) | |||||
| >>> # A Cauchy distribution can be initialized without arguments. | >>> # A Cauchy distribution can be initialized without arguments. | ||||
| >>> # In this case, 'loc' and `scale` must be passed in through arguments. | >>> # In this case, 'loc' and `scale` must be passed in through arguments. | ||||
| >>> cauchy = msd.Cauchy(dtype=mstype.float32) | |||||
| >>> | |||||
| >>> # To use a Cauchy distribution in a network. | |||||
| >>> class net(Cell): | |||||
| ... def __init__(self): | |||||
| ... super(net, self).__init__(): | |||||
| ... self.cau1 = msd.Cauchy(0.0, 1.0, dtype=mstype.float32) | |||||
| ... self.cau2 = msd.Cauchy(dtype=mstype.float32) | |||||
| ... | |||||
| ... # The following calls are valid in construct. | |||||
| ... def construct(self, value, loc_b, scale_b, loc_a, scale_a): | |||||
| ... | |||||
| ... # Private interfaces of probability functions corresponding to public interfaces, including | |||||
| ... # `prob`, `log_prob`, `cdf`, `log_cdf`, `survival_function`, and `log_survival`, have the same arguments as follows. | |||||
| ... # Args: | |||||
| ... # value (Tensor): the value to be evaluated. | |||||
| ... # loc (Tensor): the location of the distribution. Default: self.loc. | |||||
| ... # scale (Tensor): the scale of the distribution. Default: self.scale. | |||||
| ... | |||||
| ... # Examples of `prob`. | |||||
| ... # Similar calls can be made to other probability functions | |||||
| ... # by replacing 'prob' by the name of the function | |||||
| ... ans = self.cau1.prob(value) | |||||
| ... # Evaluate with respect to distribution b. | |||||
| ... ans = self.cau1.prob(value, loc_b, scale_b) | |||||
| ... # `loc` and `scale` must be passed in during function calls | |||||
| ... ans = self.cau2.prob(value, loc_a, scale_a) | |||||
| ... | |||||
| ... # Functions `mode` and `entropy` have the same arguments. | |||||
| ... # Args: | |||||
| ... # loc (Tensor): the location of the distribution. Default: self.loc. | |||||
| ... # scale (Tensor): the scale of the distribution. Default: self.scale. | |||||
| ... | |||||
| ... # Example of `mode`. | |||||
| ... ans = self.cau1.mode() # return 0.0 | |||||
| ... ans = self.cau1.mode(loc_b, scale_b) # return loc_b | |||||
| ... # `loc` and `scale` must be passed in during function calls. | |||||
| ... ans = self.cau2.mode(loc_a, scale_a) | |||||
| ... | |||||
| ... # Interfaces of 'kl_loss' and 'cross_entropy' are the same: | |||||
| ... # Args: | |||||
| ... # dist (str): the type of the distributions. Only "Cauchy" is supported. | |||||
| ... # loc_b (Tensor): the loc of distribution b. | |||||
| ... # scale_b (Tensor): the scale distribution b. | |||||
| ... # loc (Tensor): the loc of distribution a. Default: self.loc. | |||||
| ... # scale (Tensor): the scale distribution a. Default: self.scale. | |||||
| ... | |||||
| ... # Examples of `kl_loss`. `cross_entropy` is similar. | |||||
| ... ans = self.cau1.kl_loss('Cauchy', loc_b, scale_b) | |||||
| ... ans = self.cau1.kl_loss('Cauchy', loc_b, scale_b, loc_a, scale_a) | |||||
| ... # Additional `loc` and `scale` must be passed in. | |||||
| ... ans = self.cau2.kl_loss('Cauchy', loc_b, scale_b, loc_a, scale_a) | |||||
| ... | |||||
| ... # Examples of `sample`. | |||||
| ... # Args: | |||||
| ... # shape (tuple): the shape of the sample. Default: () | |||||
| ... # loc (Tensor): the location of the distribution. Default: self.loc. | |||||
| ... # scale (Tensor): the scale of the distribution. Default: self.scale. | |||||
| ... ans = self.cau1.sample() | |||||
| ... ans = self.cau1.sample((2,3)) | |||||
| ... ans = self.cau1.sample((2,3), loc_b, s_b) | |||||
| ... ans = self.cau2.sample((2,3), loc_a, s_a) | |||||
| >>> cauchy2 = msd.Cauchy(dtype=mindspore.float32) | |||||
| >>> # Here are some tensors used below for testing | |||||
| >>> value = Tensor([1.0, 2.0, 3.0], dtype=mindspore.float32) | |||||
| >>> loc_a = Tensor([2.0], dtype=mindspore.float32) | |||||
| >>> scale_a = Tensor([2.0, 2.0, 2.0], dtype=mindspore.float32) | |||||
| >>> loc_b = Tensor([1.0], dtype=mindspore.float32) | |||||
| >>> scale_b = Tensor([1.0, 1.5, 2.0], dtype=mindspore.float32) | |||||
| >>> # Private interfaces of probability functions corresponding to public interfaces, including | |||||
| >>> # `prob`, `log_prob`, `cdf`, `log_cdf`, `survival_function`, and `log_survival`, have the same arguments as follows. | |||||
| >>> # Args: | |||||
| >>> # value (Tensor): the value to be evaluated. | |||||
| >>> # loc (Tensor): the location of the distribution. Default: self.loc. | |||||
| >>> # scale (Tensor): the scale of the distribution. Default: self.scale. | |||||
| >>> # Examples of `prob`. | |||||
| >>> # Similar calls can be made to other probability functions | |||||
| >>> # by replacing 'prob' by the name of the function | |||||
| >>> ans = cauchy1.prob(value) | |||||
| >>> print(ans) | |||||
| [0.06366198 0.07489645 0.07957747] | |||||
| >>> # Evaluate with respect to distribution b. | |||||
| >>> ans = cauchy1.prob(value, loc_b, scale_b) | |||||
| >>> print(ans) | |||||
| [0.31830987 0.14691226 0.07957747] | |||||
| >>> # `loc` and `scale` must be passed in during function calls | |||||
| >>> ans = cauchy2.prob(value, loc_a, scale_a) | |||||
| >>> print(ans) | |||||
| [0.12732396 0.15915494 0.12732396] | |||||
| >>> # Functions `mode` and `entropy` have the same arguments. | |||||
| >>> # Args: | |||||
| >>> # loc (Tensor): the location of the distribution. Default: self.loc. | |||||
| >>> # scale (Tensor): the scale of the distribution. Default: self.scale. | |||||
| >>> # Example of `mode`. | |||||
| >>> ans = cauchy1.mode() # return 3.0 | |||||
| >>> print(ans) | |||||
| 3.0 | |||||
| >>> ans = cauchy1.mode(loc_b, scale_b) # return loc_b | |||||
| >>> print(ans) | |||||
| [1. 1. 1.] | |||||
| >>> # `loc` and `scale` must be passed in during function calls. | |||||
| >>> ans = cauchy2.mode(loc_a, scale_a) | |||||
| >>> print(ans) | |||||
| [2. 2. 2.] | |||||
| >>> # Interfaces of 'kl_loss' and 'cross_entropy' are the same: | |||||
| >>> # Args: | |||||
| >>> # dist (str): the type of the distributions. Only "Cauchy" is supported. | |||||
| >>> # loc_b (Tensor): the loc of distribution b. | |||||
| >>> # scale_b (Tensor): the scale distribution b. | |||||
| >>> # loc (Tensor): the loc of distribution a. Default: self.loc. | |||||
| >>> # scale (Tensor): the scale distribution a. Default: self.scale. | |||||
| >>> # Examples of `kl_loss`. `cross_entropy` is similar. | |||||
| >>> ans = cauchy1.kl_loss('Cauchy', loc_b, scale_b) | |||||
| >>> print(ans) | |||||
| [0.594707 0.35563278 0.22314358] | |||||
| >>> ans = cauchy1.kl_loss('Cauchy', loc_b, scale_b, loc_a, scale_a) | |||||
| >>> print(ans) | |||||
| [0.22314358 0.09909081 0.0606246 ] | |||||
| >>> # Additional `loc` and `scale` must be passed in. | |||||
| >>> ans = cauchy2.kl_loss('Cauchy', loc_b, scale_b, loc_a, scale_a) | |||||
| >>> print(ans) | |||||
| [0.22314358 0.09909081 0.0606246 ] | |||||
| >>> # Examples of `sample`. | |||||
| >>> # Args: | |||||
| >>> # shape (tuple): the shape of the sample. Default: () | |||||
| >>> # loc (Tensor): the location of the distribution. Default: self.loc. | |||||
| >>> # scale (Tensor): the scale of the distribution. Default: self.scale. | |||||
| >>> ans = cauchy1.sample() | |||||
| >>> print(ans.shape) | |||||
| () | |||||
| >>> ans = cauchy1.sample((2,3)) | |||||
| >>> print(ans.shape) | |||||
| (2, 3) | |||||
| >>> ans = cauchy1.sample((2,3), loc_b, scale_b) | |||||
| >>> print(ans.shape) | |||||
| (2, 3, 3) | |||||
| >>> ans = cauchy2.sample((2,3), loc_a, scale_a) | |||||
| >>> print(ans.shape) | |||||
| (2, 3, 3) | |||||
| """ | """ | ||||
| def __init__(self, | def __init__(self, | ||||
| @@ -275,7 +289,7 @@ class Cauchy(Distribution): | |||||
| loc, scale = self._check_param_type(loc, scale) | loc, scale = self._check_param_type(loc, scale) | ||||
| return loc + scale * self.tan(np.pi * (p - 0.5)) | return loc + scale * self.tan(np.pi * (p - 0.5)) | ||||
| def _kl_loss(self, dist, loc_b, scale_b, loc=None, scale=None): | |||||
| def _kl_loss(self, dist, loc_b, scale_b, loc_a=None, scale_a=None): | |||||
| r""" | r""" | ||||
| Evaluate Cauchy-Cauchy kl divergence, i.e. KL(a||b). | Evaluate Cauchy-Cauchy kl divergence, i.e. KL(a||b). | ||||
| @@ -291,17 +305,17 @@ class Cauchy(Distribution): | |||||
| {4 * scale_a * scale_b}) | {4 * scale_a * scale_b}) | ||||
| """ | """ | ||||
| check_distribution_name(dist, 'Cauchy') | check_distribution_name(dist, 'Cauchy') | ||||
| loc, scale = self._check_param_type(loc, scale) | |||||
| loc_a, scale_a = self._check_param_type(loc_a, scale_a) | |||||
| loc_b = self._check_value(loc_b, 'loc_b') | loc_b = self._check_value(loc_b, 'loc_b') | ||||
| loc_b = self.cast(loc_b, self.parameter_type) | loc_b = self.cast(loc_b, self.parameter_type) | ||||
| scale_b = self._check_value(scale_b, 'scale_b') | scale_b = self._check_value(scale_b, 'scale_b') | ||||
| scale_b = self.cast(scale_b, self.parameter_type) | scale_b = self.cast(scale_b, self.parameter_type) | ||||
| sum_square = self.sq(scale + scale_b) | |||||
| square_diff = self.sq(loc - loc_b) | |||||
| sum_square = self.sq(scale_a + scale_b) | |||||
| square_diff = self.sq(loc_a - loc_b) | |||||
| return self.log(sum_square + square_diff) - \ | return self.log(sum_square + square_diff) - \ | ||||
| self.log(self.const(4.0)) - self.log(scale) - self.log(scale_b) | |||||
| self.log(self.const(4.0)) - self.log(scale_a) - self.log(scale_b) | |||||
| def _cross_entropy(self, dist, loc_b, scale_b, loc=None, scale=None): | |||||
| def _cross_entropy(self, dist, loc_b, scale_b, loc_a=None, scale_a=None): | |||||
| r""" | r""" | ||||
| Evaluate cross entropy between Cauchy distributions. | Evaluate cross entropy between Cauchy distributions. | ||||
| @@ -313,7 +327,7 @@ class Cauchy(Distribution): | |||||
| scale (Tensor): The scale of distribution a. Default: self.scale. | scale (Tensor): The scale of distribution a. Default: self.scale. | ||||
| """ | """ | ||||
| check_distribution_name(dist, 'Cauchy') | check_distribution_name(dist, 'Cauchy') | ||||
| return self._entropy(loc, scale) + self._kl_loss(dist, loc_b, scale_b, loc, scale) | |||||
| return self._entropy(loc_a, scale_a) + self._kl_loss(dist, loc_b, scale_b, loc_a, scale_a) | |||||
| def _sample(self, shape=(), loc=None, scale=None): | def _sample(self, shape=(), loc=None, scale=None): | ||||
| """ | """ | ||||
| @@ -42,55 +42,49 @@ class Gumbel(TransformedDistribution): | |||||
| `kl_loss` and `cross_entropy` are not supported on GPU backend. | `kl_loss` and `cross_entropy` are not supported on GPU backend. | ||||
| Examples: | Examples: | ||||
| >>> import mindspore | |||||
| >>> import mindspore.context as context | |||||
| >>> import mindspore.nn as nn | |||||
| >>> import mindspore.nn.probability.distribution as msd | |||||
| >>> from mindspore import Tensor | |||||
| >>> context.set_context(mode=1, device_target="GPU") | |||||
| >>> # To initialize a Gumbel distribution of `loc` 3.0 and `scale` 4.0. | >>> # To initialize a Gumbel distribution of `loc` 3.0 and `scale` 4.0. | ||||
| >>> gum = msd.Gumbel(3.0, 4.0, dtype=mstype.float32) | |||||
| >>> | |||||
| >>> # The following creates two independent Gumbel distributions. | |||||
| >>> gum = msd.Gumbel([3.0, 3.0], [4.0, 4.0], dtype=mstype.float32) | |||||
| >>> | |||||
| >>> # To use a Gumbel distribution in a network. | |||||
| >>> class net(Cell): | |||||
| ... def __init__(self): | |||||
| ... super(net, self).__init__(): | |||||
| ... self.g1 = msd.Gumbel(0.0, 1.0, dtype=mstype.float32) | |||||
| ... | |||||
| ... # The following calls are valid in construct. | |||||
| ... def construct(self, value, loc_b, scale_b): | |||||
| ... | |||||
| ... # Private interfaces of probability functions corresponding to public interfaces, including | |||||
| ... # `prob`, `log_prob`, `cdf`, `log_cdf`, `survival_function`, and `log_survival`, have the same | |||||
| ... # arguments as follows. | |||||
| ... # Args: | |||||
| ... # value (Tensor): the value to be evaluated. | |||||
| ... | |||||
| ... # Examples of `prob`. | |||||
| ... # Similar calls can be made to other probability functions | |||||
| ... # by replacing 'prob' by the name of the function. | |||||
| ... ans = self.g1.prob(value) | |||||
| ... | |||||
| ... # Functions `mean`, `mode`, sd`, `var`, and `entropy` do not take in any argument. | |||||
| ... ans = self.g1.mean() | |||||
| ... ans = self.g1.mode() | |||||
| ... ans = self.g1.sd() | |||||
| ... ans = self.g1.entropy() | |||||
| ... ans = self.g1.var() | |||||
| ... | |||||
| ... # Interfaces of 'kl_loss' and 'cross_entropy' are the same: | |||||
| ... # Args: | |||||
| ... # dist (str): the type of the distributions. Only "Gumbel" is supported. | |||||
| ... # loc_b (Tensor): the loc of distribution b. | |||||
| ... # scale_b (Tensor): the scale distribution b. | |||||
| ... | |||||
| ... # Examples of `kl_loss`. `cross_entropy` is similar. | |||||
| ... ans = self.g1.kl_loss('Gumbel', loc_b, scale_b) | |||||
| ... ans = self.g1.cross_entropy('Gumbel', loc_b, scale_b) | |||||
| ... | |||||
| ... # Examples of `sample`. | |||||
| ... # Args: | |||||
| ... # shape (tuple): the shape of the sample. Default: () | |||||
| ... | |||||
| ... ans = self.g1.sample() | |||||
| ... ans = self.g1.sample((2,3)) | |||||
| >>> gumbel = msd.Gumbel(3.0, 4.0, dtype=mindspore.float32) | |||||
| >>> # Private interfaces of probability functions corresponding to public interfaces, including | |||||
| >>> # `prob`, `log_prob`, `cdf`, `log_cdf`, `survival_function`, and `log_survival`, have the same | |||||
| >>> # arguments as follows. | |||||
| >>> # Args: | |||||
| >>> # value (Tensor): the value to be evaluated. | |||||
| >>> # Examples of `prob`. | |||||
| >>> # Similar calls can be made to other probability functions | |||||
| >>> # by replacing 'prob' by the name of the function. | |||||
| >>> value = Tensor([1.0, 2.0, 3.0], dtype=mindspore.float32) | |||||
| >>> ans = gumbel.prob(value) | |||||
| >>> print(ans) | |||||
| [0.07926048 0.08889321 0.09196986] | |||||
| >>> # Functions `mean`, `mode`, sd`, `var`, and `entropy` do not take in any argument. | |||||
| >>> ans = gumbel.mean() | |||||
| >>> print(ans) | |||||
| 5.3088627 | |||||
| >>> # Interfaces of 'kl_loss' and 'cross_entropy' are the same: | |||||
| >>> # Args: | |||||
| >>> # dist (str): the type of the distributions. Only "Gumbel" is supported. | |||||
| >>> # loc_b (Tensor): the loc of distribution b. | |||||
| >>> # scale_b (Tensor): the scale distribution b. | |||||
| >>> # Examples of `kl_loss`. `cross_entropy` is similar. | |||||
| >>> loc_b = Tensor([1.0], dtype=mindspore.float32) | |||||
| >>> scale_b = Tensor([1.0, 1.5, 2.0], dtype=mindspore.float32) | |||||
| >>> ans = gumbel.kl_loss('Gumbel', loc_b, scale_b) | |||||
| >>> print(ans) | |||||
| [ 2.5934026 0.03880269 -0.38017237] | |||||
| >>> # Examples of `sample`. | |||||
| >>> # Args: | |||||
| >>> # shape (tuple): the shape of the sample. Default: () | |||||
| >>> ans = gumbel.sample() | |||||
| >>> print(ans.shape) | |||||
| () | |||||
| >>> ans = gumbel.sample((2,3)) | |||||
| >>> print(ans.shape) | |||||
| """ | """ | ||||
| def __init__(self, | def __init__(self, | ||||
| @@ -125,6 +119,7 @@ class Gumbel(TransformedDistribution): | |||||
| self.lgamma = nn.LGamma() | self.lgamma = nn.LGamma() | ||||
| self.log = log_generic | self.log = log_generic | ||||
| self.shape = P.Shape() | self.shape = P.Shape() | ||||
| self.squeeze = P.Squeeze(0) | |||||
| self.sqrt = P.Sqrt() | self.sqrt = P.Sqrt() | ||||
| @property | @property | ||||
| @@ -41,87 +41,104 @@ class LogNormal(msd.TransformedDistribution): | |||||
| `dtype` must be a float type because LogNormal distributions are continuous. | `dtype` must be a float type because LogNormal distributions are continuous. | ||||
| Examples: | Examples: | ||||
| >>> import mindspore | |||||
| >>> import mindspore.context as context | |||||
| >>> import mindspore.nn as nn | |||||
| >>> import mindspore.nn.probability.distribution as msd | |||||
| >>> from mindspore import Tensor | |||||
| >>> context.set_context(mode=1) | |||||
| >>> # To initialize a LogNormal distribution of `loc` 3.0 and `scale` 4.0. | >>> # To initialize a LogNormal distribution of `loc` 3.0 and `scale` 4.0. | ||||
| >>> n = msd.LogNormal(3.0, 4.0, dtype=mstype.float32) | |||||
| >>> | |||||
| >>> # The following creates two independent LogNormal distributions. | |||||
| >>> n = msd.LogNormal([3.0, 3.0], [4.0, 4.0], dtype=mstype.float32) | |||||
| >>> | |||||
| >>> n1 = msd.LogNormal(3.0, 4.0, dtype=mindspore.float32) | |||||
| >>> # A LogNormal distribution can be initialized without arguments. | >>> # A LogNormal distribution can be initialized without arguments. | ||||
| >>> # In this case, `loc` and `scale` must be passed in during function calls. | >>> # In this case, `loc` and `scale` must be passed in during function calls. | ||||
| >>> n = msd.LogNormal(dtype=mstype.float32) | |||||
| >>> n2 = msd.LogNormal(dtype=mindspore.float32) | |||||
| >>> | |||||
| >>> # Here are some tensors used below for testing | |||||
| >>> value = Tensor([1.0, 2.0, 3.0], dtype=mindspore.float32) | |||||
| >>> loc_a = Tensor([2.0], dtype=mindspore.float32) | |||||
| >>> scale_a = Tensor([2.0, 2.0, 2.0], dtype=mindspore.float32) | |||||
| >>> loc_b = Tensor([1.0], dtype=mindspore.float32) | |||||
| >>> scale_b = Tensor([1.0, 1.5, 2.0], dtype=mindspore.float32) | |||||
| >>> | >>> | ||||
| >>> # To use a LogNormal distribution in a network. | |||||
| >>> class net(Cell): | |||||
| ... def __init__(self): | |||||
| ... super(net, self).__init__(): | |||||
| ... self.n1 = msd.LogNormal(0.0, 1.0, dtype=mstype.float32) | |||||
| ... self.n2 = msd.LogNormal(dtype=mstype.float32) | |||||
| ... | |||||
| ... # The following calls are valid in construct. | |||||
| ... def construct(self, value, loc_b, scale_b, loc_a, scale_a): | |||||
| ... | |||||
| ... # Private interfaces of probability functions corresponding to public interfaces, including | |||||
| ... # `prob`, `log_prob`, `cdf`, `log_cdf`, `survival_function`, and `log_survival`, have the same | |||||
| ... # arguments as follows. | |||||
| ... # Args: | |||||
| ... # value (Tensor): the value to be evaluated. | |||||
| ... # loc (Tensor): the loc of distribution. Default: None. If `loc` is passed in as None, | |||||
| ... # the mean of the underlying Normal distribution will be used. | |||||
| ... # scale (Tensor): the scale of distribution. Default: None. If `scale` is passed in as None, | |||||
| ... # the standard deviation of the underlying Normal distribution will be used. | |||||
| ... | |||||
| ... # Examples of `prob`. | |||||
| ... # Similar calls can be made to other probability functions | |||||
| ... # by replacing 'prob' by the name of the function. | |||||
| ... ans = self.n1.prob(value) | |||||
| ... # Evaluate with respect to distribution b. | |||||
| ... ans = self.n1.prob(value, loc_b, scale_b) | |||||
| ... # `loc` and `scale` must be passed in during function calls since they were not passed in construct. | |||||
| ... ans = self.n2.prob(value, loc_a, scale_a) | |||||
| ... | |||||
| ... | |||||
| ... # Functions `mean`, `sd`, `var`, and `entropy` have the same arguments. | |||||
| ... # Args: | |||||
| ... # loc (Tensor): the loc of distribution. Default: None. If `loc` is passed in as None, | |||||
| ... # the mean of the underlying Normal distribution will be used. | |||||
| ... # scale (Tensor): the scale of distribution. Default: None. If `scale` is passed in as None, | |||||
| ... # the standard deviation of the underlying Normal distribution will be used. | |||||
| ... | |||||
| ... # Example of `mean`. `sd`, `var`, and `entropy` are similar. | |||||
| ... ans = self.n1.mean() # return 0.0 | |||||
| ... ans = self.n1.mean(loc_b, scale_b) # return mean_b | |||||
| ... # `loc` and `scale` must be passed in during function calls since they were not passed in construct. | |||||
| ... ans = self.n2.mean(loc_a, scale_a) | |||||
| ... | |||||
| ... | |||||
| ... # Interfaces of 'kl_loss' and 'cross_entropy' are the same: | |||||
| ... # Args: | |||||
| ... # dist (str): the type of the distributions. Only "Normal" is supported. | |||||
| ... # loc_b (Tensor): the loc of distribution b. | |||||
| ... # scale_b (Tensor): the scale distribution b. | |||||
| ... # loc_a (Tensor): the loc of distribution a. Default: None. If `loc` is passed in as None, | |||||
| ... # the mean of the underlying Normal distribution will be used. | |||||
| ... # scale_a (Tensor): the scale distribution a. Default: None. If `scale` is passed in as None, | |||||
| ... # the standard deviation of the underlying Normal distribution will be used. | |||||
| ... | |||||
| ... # Examples of `kl_loss`. `cross_entropy` is similar. | |||||
| ... ans = self.n1.kl_loss('Normal', loc_b, scale_b) | |||||
| ... ans = self.n1.kl_loss('Normal', loc_b, scale_b, loc_a, scale_a) | |||||
| ... # Additional `loc` and `scale` must be passed in since they were not passed in construct. | |||||
| ... ans = self.n2.kl_loss('Normal', loc_b, scale_b, loc_a, scale_a) | |||||
| ... | |||||
| ... # Examples of `sample`. | |||||
| ... # Args: | |||||
| ... # shape (tuple): the shape of the sample. Default: () | |||||
| ... # loc (Tensor): the loc of the distribution. Default: None. If `loc` is passed in as None, | |||||
| ... # the mean of the underlying Normal distribution will be used. | |||||
| ... # scale (Tensor): the scale of the distribution. Default: None. If `scale` is passed in as None, | |||||
| ... # the standard deviation of the underlying Normal distribution will be used. | |||||
| ... ans = self.n1.sample() | |||||
| ... ans = self.n1.sample((2,3)) | |||||
| ... ans = self.n1.sample((2,3), loc_b, scale_b) | |||||
| ... ans = self.n2.sample((2,3), loc_a, scale_a) | |||||
| >>> # Private interfaces of probability functions corresponding to public interfaces, including | |||||
| >>> # `prob`, `log_prob`, `cdf`, `log_cdf`, `survival_function`, and `log_survival`, have the same | |||||
| >>> # arguments as follows. | |||||
| >>> # Args: | |||||
| >>> # value (Tensor): the value to be evaluated. | |||||
| >>> # loc (Tensor): the loc of distribution. Default: None. If `loc` is passed in as None, | |||||
| >>> # the mean of the underlying Normal distribution will be used. | |||||
| >>> # scale (Tensor): the scale of distribution. Default: None. If `scale` is passed in as None, | |||||
| >>> # the standard deviation of the underlying Normal distribution will be used. | |||||
| >>> # Examples of `prob`. | |||||
| >>> # Similar calls can be made to other probability functions | |||||
| >>> # by replacing 'prob' by the name of the function. | |||||
| >>> ans = n1.prob(value) | |||||
| >>> print(ans) | |||||
| [0.07528435 0.04222769 0.02969363] | |||||
| >>> # Evaluate with respect to distribution b. | |||||
| >>> ans = n1.prob(value, loc_b, scale_b) | |||||
| >>> print(ans) | |||||
| [0.24197072 0.13022715 0.0664096 ] | |||||
| >>> # `loc` and `scale` must be passed in during function calls since they were not passed in construct. | |||||
| >>> ans = n2.prob(value, loc_a, scale_a) | |||||
| >>> print(ans) | |||||
| [0.12098535 0.08056299 0.06006904] | |||||
| >>> # Functions `mean`, `sd`, `var`, and `entropy` have the same arguments. | |||||
| >>> # Args: | |||||
| >>> # loc (Tensor): the loc of distribution. Default: None. If `loc` is passed in as None, | |||||
| >>> # the mean of the underlying Normal distribution will be used. | |||||
| >>> # scale (Tensor): the scale of distribution. Default: None. If `scale` is passed in as None, | |||||
| >>> # the standard deviation of the underlying Normal distribution will be used. | |||||
| >>> # Example of `mean`. `sd`, `var`, and `entropy` are similar. | |||||
| >>> ans = n1.mean() | |||||
| >>> print(ans) | |||||
| 59874.14 | |||||
| >>> ans = n1.mean(loc_b, scale_b) | |||||
| >>> print(ans) | |||||
| [ 4.481689 8.372897 20.085537] | |||||
| >>> # `loc` and `scale` must be passed in during function calls since they were not passed in construct. | |||||
| >>> ans = n2.mean(loc_a, scale_a) | |||||
| >>> print(ans) | |||||
| [54.59815 54.59815 54.59815] | |||||
| >>> # Interfaces of 'kl_loss' and 'cross_entropy' are the same: | |||||
| >>> # Args: | |||||
| >>> # dist (str): the type of the distributions. Only "Normal" is supported. | |||||
| >>> # loc_b (Tensor): the loc of distribution b. | |||||
| >>> # scale_b (Tensor): the scale distribution b. | |||||
| >>> # loc_a (Tensor): the loc of distribution a. Default: None. If `loc` is passed in as None, | |||||
| >>> # the mean of the underlying Normal distribution will be used. | |||||
| >>> # scale_a (Tensor): the scale distribution a. Default: None. If `scale` is passed in as None, | |||||
| >>> # the standard deviation of the underlying Normal distribution will be used. | |||||
| >>> # Examples of `kl_loss`. `cross_entropy` is similar. | |||||
| >>> ans = n1.kl_loss('LogNormal', loc_b, scale_b) | |||||
| >>> print(ans) | |||||
| [8.113706 2.963615 1.3068528] | |||||
| >>> ans = n1.kl_loss('LogNormal', loc_b, scale_b, loc_a, scale_a) | |||||
| >>> print(ans) | |||||
| [1.3068528 0.32342905 0.125 ] | |||||
| >>> # Additional `loc` and `scale` must be passed in since they were not passed in construct. | |||||
| >>> ans = n2.kl_loss('LogNormal', loc_b, scale_b, loc_a, scale_a) | |||||
| >>> print(ans) | |||||
| [1.3068528 0.32342905 0.125 ] | |||||
| >>> # Examples of `sample`. | |||||
| >>> # Args: | |||||
| >>> # shape (tuple): the shape of the sample. Default: () | |||||
| >>> # loc (Tensor): the loc of the distribution. Default: None. If `loc` is passed in as None, | |||||
| >>> # the mean of the underlying Normal distribution will be used. | |||||
| >>> # scale (Tensor): the scale of the distribution. Default: None. If `scale` is passed in as None, | |||||
| >>> # the standard deviation of the underlying Normal distribution will be used. | |||||
| >>> ans = n1.sample() | |||||
| >>> print(ans.shape) | |||||
| () | |||||
| >>> ans = n1.sample((2,3)) | |||||
| >>> print(ans.shape) | |||||
| (2, 3) | |||||
| >>> ans = n1.sample((2,3), loc_b, scale_b) | |||||
| >>> print(ans.shape) | |||||
| (2, 3, 3) | |||||
| >>> ans = n2.sample((2,3), loc_a, scale_a) | |||||
| >>> print(ans.shape) | |||||
| (2, 3, 3) | |||||
| """ | """ | ||||
| def __init__(self, | def __init__(self, | ||||
| @@ -154,6 +171,8 @@ class LogNormal(msd.TransformedDistribution): | |||||
| self.shape = P.Shape() | self.shape = P.Shape() | ||||
| self.sq = P.Square() | self.sq = P.Square() | ||||
| self.sqrt = P.Sqrt() | self.sqrt = P.Sqrt() | ||||
| self.cast = P.Cast() | |||||
| self.squeeze = P.Squeeze(0) | |||||
| self.zeroslike = P.ZerosLike() | self.zeroslike = P.ZerosLike() | ||||
| @property | @property | ||||
| @@ -221,6 +240,35 @@ class LogNormal(msd.TransformedDistribution): | |||||
| mean, sd = self._check_param_type(loc, scale) | mean, sd = self._check_param_type(loc, scale) | ||||
| return mean + 0.5 + self.log(sd) + 0.5 * self.log_2pi | return mean + 0.5 + self.log(sd) + 0.5 * self.log_2pi | ||||
| def _cdf(self, value, loc=None, scale=None): | |||||
| r""" | |||||
| Compute the cdf via the below formula, | |||||
| where g is the exp bijector, | |||||
| and P is the cdf of the underlying normal dist | |||||
| .. math:: | |||||
| Y = g(X) | |||||
| P(Y <= a) = P(X <= g^{-1}(a)) | |||||
| """ | |||||
| mean, sd = self._check_param_type(loc, scale) | |||||
| inverse_value = self.bijector("inverse", value) | |||||
| return self.distribution("cdf", inverse_value, mean, sd) | |||||
| def _log_prob(self, value, loc=None, scale=None): | |||||
| r""" | |||||
| Compute the log prob via the below formula, | |||||
| where g is the exp bijector, | |||||
| and P is the pdf of the underlying normal dist | |||||
| .. math:: | |||||
| Y = g(X) | |||||
| Py(a) = Px(g^{-1}(a)) * (g^{-1})'(a) | |||||
| \log(Py(a)) = \log(Px(g^{-1}(a))) + \log((g^{-1})'(a)) | |||||
| """ | |||||
| mean, sd = self._check_param_type(loc, scale) | |||||
| inverse_value = self.bijector("inverse", value) | |||||
| unadjust_prob = self.distribution("log_prob", inverse_value, mean, sd) | |||||
| log_jacobian = self.bijector("inverse_log_jacobian", value) | |||||
| return unadjust_prob + log_jacobian | |||||
| def _cross_entropy(self, dist, loc_b, scale_b, loc_a=None, scale_a=None): | def _cross_entropy(self, dist, loc_b, scale_b, loc_a=None, scale_a=None): | ||||
| r""" | r""" | ||||
| Evaluate cross entropy between lognormal distributions. | Evaluate cross entropy between lognormal distributions. | ||||
| @@ -252,3 +300,20 @@ class LogNormal(msd.TransformedDistribution): | |||||
| """ | """ | ||||
| check_distribution_name(dist, 'LogNormal') | check_distribution_name(dist, 'LogNormal') | ||||
| return self.distribution("kl_loss", 'Normal', loc_b, scale_b, loc_a, scale_a) | return self.distribution("kl_loss", 'Normal', loc_b, scale_b, loc_a, scale_a) | ||||
| def _sample(self, shape=(), loc=None, scale=None): | |||||
| r""" | |||||
| Generate samples via mapping the samples from the underlying normal dist. | |||||
| """ | |||||
| shape = self.checktuple(shape, 'shape') | |||||
| mean, sd = self._check_param_type(loc, scale) | |||||
| if shape == (): | |||||
| sample_shape = (1,) | |||||
| else: | |||||
| sample_shape = shape | |||||
| org_sample = self.distribution("sample", sample_shape, mean, sd) | |||||
| org_sample = self.cast(org_sample, self.dtype) | |||||
| value = self.bijector("forward", org_sample) | |||||
| if shape == (): | |||||
| value = self.squeeze(value) | |||||
| return value | |||||
| @@ -40,63 +40,75 @@ class Logistic(Distribution): | |||||
| `dtype` must be a float type because Logistic distributions are continuous. | `dtype` must be a float type because Logistic distributions are continuous. | ||||
| Examples: | Examples: | ||||
| >>> # To initialize a Logistic distribution of loc 3.0 and scale 4.0. | |||||
| >>> import mindspore | |||||
| >>> import mindspore.nn as nn | |||||
| >>> import mindspore.nn.probability.distribution as msd | >>> import mindspore.nn.probability.distribution as msd | ||||
| >>> n = msd.Logistic(3.0, 4.0, dtype=mstype.float32) | |||||
| >>> | |||||
| >>> # The following creates two independent Logistic distributions. | |||||
| >>> n = msd.Logistic([3.0, 3.0], [4.0, 4.0], dtype=mstype.float32) | |||||
| >>> | |||||
| >>> from mindspore import Tensor | |||||
| >>> # To initialize a Logistic distribution of loc 3.0 and scale 4.0. | |||||
| >>> l1 = msd.Logistic(3.0, 4.0, dtype=mindspore.float32) | |||||
| >>> # A Logistic distribution can be initialized without arguments. | >>> # A Logistic distribution can be initialized without arguments. | ||||
| >>> # In this case, `loc` and `scale` must be passed in through arguments. | >>> # In this case, `loc` and `scale` must be passed in through arguments. | ||||
| >>> n = msd.Logistic(dtype=mstype.float32) | |||||
| >>> l2 = msd.Logistic(dtype=mindspore.float32) | |||||
| >>> | |||||
| >>> # Here are some tensors used below for testing | |||||
| >>> value = Tensor([1.0, 2.0, 3.0], dtype=mindspore.float32) | |||||
| >>> loc_a = Tensor([2.0], dtype=mindspore.float32) | |||||
| >>> scale_a = Tensor([2.0, 2.0, 2.0], dtype=mindspore.float32) | |||||
| >>> loc_b = Tensor([1.0], dtype=mindspore.float32) | |||||
| >>> scale_b = Tensor([1.0, 1.5, 2.0], dtype=mindspore.float32) | |||||
| >>> | >>> | ||||
| >>> # To use a Normal distribution in a network. | |||||
| >>> class net(Cell): | |||||
| ... def __init__(self): | |||||
| ... super(net, self).__init__(): | |||||
| ... self.l1 = msd.Logistic(0.0, 1.0, dtype=mstype.float32) | |||||
| ... self.l2 = msd.Logistic(dtype=mstype.float32) | |||||
| ... | |||||
| ... # The following calls are valid in construct. | |||||
| ... def construct(self, value, loc_b, scale_b, loc_a, scale_a): | |||||
| ... | |||||
| ... # Private interfaces of probability functions corresponding to public interfaces, including | |||||
| ... # `prob`, `log_prob`, `cdf`, `log_cdf`, `survival_function`, and `log_survival`, have the same arguments as follows. | |||||
| ... # Args: | |||||
| ... # value (Tensor): the value to be evaluated. | |||||
| ... # loc (Tensor): the location of the distribution. Default: self.loc. | |||||
| ... # scale (Tensor): the scale of the distribution. Default: self.scale. | |||||
| ... | |||||
| ... # Examples of `prob`. | |||||
| ... # Similar calls can be made to other probability functions | |||||
| ... # by replacing 'prob' by the name of the function | |||||
| ... ans = self.l1.prob(value) | |||||
| ... # Evaluate with respect to distribution b. | |||||
| ... ans = self.l1.prob(value, loc_b, scale_b) | |||||
| ... # `loc` and `scale` must be passed in during function calls | |||||
| ... ans = self.l2.prob(value, loc_a, scale_a) | |||||
| ... | |||||
| ... # Functions `mean`, `mode`, `sd`, `var`, and `entropy` have the same arguments. | |||||
| ... # Args: | |||||
| ... # loc (Tensor): the location of the distribution. Default: self.loc. | |||||
| ... # scale (Tensor): the scale of the distribution. Default: self.scale. | |||||
| ... | |||||
| ... # Example of `mean`. `mode`, `sd`, `var`, and `entropy` are similar. | |||||
| ... ans = self.l1.mean() # return 0.0 | |||||
| ... ans = self.l1.mean(loc_b, scale_b) # return loc_b | |||||
| ... # `loc` and `scale` must be passed in during function calls. | |||||
| ... ans = self.l2.mean(loc_a, scale_a) | |||||
| ... | |||||
| ... # Examples of `sample`. | |||||
| ... # Args: | |||||
| ... # shape (tuple): the shape of the sample. Default: () | |||||
| ... # loc (Tensor): the location of the distribution. Default: self.loc. | |||||
| ... # scale (Tensor): the scale of the distribution. Default: self.scale. | |||||
| ... ans = self.l1.sample() | |||||
| ... ans = self.l1.sample((2,3)) | |||||
| ... ans = self.l1.sample((2,3), loc_b, scale_b) | |||||
| ... ans = self.l2.sample((2,3), loc_a, scale_a) | |||||
| >>> # Private interfaces of probability functions corresponding to public interfaces, including | |||||
| >>> # `prob`, `log_prob`, `cdf`, `log_cdf`, `survival_function`, and `log_survival`, have the same arguments as follows. | |||||
| >>> # Args: | |||||
| >>> # value (Tensor): the value to be evaluated. | |||||
| >>> # loc (Tensor): the location of the distribution. Default: self.loc. | |||||
| >>> # scale (Tensor): the scale of the distribution. Default: self.scale. | |||||
| >>> # Examples of `prob`. | |||||
| >>> # Similar calls can be made to other probability functions | |||||
| >>> # by replacing 'prob' by the name of the function | |||||
| >>> ans = l1.prob(value) | |||||
| >>> print(ans) | |||||
| [0.05875093 0.06153353 0.0625 ] | |||||
| >>> # Evaluate with respect to distribution b. | |||||
| >>> ans = l1.prob(value, loc_b, scale_b) | |||||
| >>> print(ans) | |||||
| [0.25 0.14943825 0.09830598] | |||||
| >>> # `loc` and `scale` must be passed in during function calls | |||||
| >>> ans = l1.prob(value, loc_a, scale_a) | |||||
| >>> print(ans) | |||||
| [0.11750185 0.125 0.11750185] | |||||
| >>> # Functions `mean`, `mode`, `sd`, `var`, and `entropy` have the same arguments. | |||||
| >>> # Args: | |||||
| >>> # loc (Tensor): the location of the distribution. Default: self.loc. | |||||
| >>> # scale (Tensor): the scale of the distribution. Default: self.scale. | |||||
| >>> # Example of `mean`. `mode`, `sd`, `var`, and `entropy` are similar. | |||||
| >>> ans = l1.mean() | |||||
| >>> print(ans) | |||||
| 3.0 | |||||
| >>> ans = l1.mean(loc_b, scale_b) | |||||
| >>> print(ans) | |||||
| [1. 1. 1.] | |||||
| >>> # `loc` and `scale` must be passed in during function calls. | |||||
| >>> ans = l1.mean(loc_a, scale_a) | |||||
| >>> print(ans) | |||||
| [2. 2. 2.] | |||||
| >>> # Examples of `sample`. | |||||
| >>> # Args: | |||||
| >>> # shape (tuple): the shape of the sample. Default: () | |||||
| >>> # loc (Tensor): the location of the distribution. Default: self.loc. | |||||
| >>> # scale (Tensor): the scale of the distribution. Default: self.scale. | |||||
| >>> ans = l1.sample() | |||||
| >>> print(ans.shape) | |||||
| () | |||||
| >>> ans = l1.sample((2,3)) | |||||
| >>> print(ans.shape) | |||||
| (2, 3) | |||||
| >>> ans = l1.sample((2,3), loc_b, scale_b) | |||||
| >>> print(ans.shape) | |||||
| (2, 3, 3) | |||||
| >>> ans = l1.sample((2,3), loc_a, scale_a) | |||||
| >>> print(ans.shape) | |||||
| (2, 3, 3) | |||||
| """ | """ | ||||
| def __init__(self, | def __init__(self, | ||||
| @@ -200,7 +200,7 @@ class Uniform(Distribution): | |||||
| self.checktensor(high, 'high') | self.checktensor(high, 'high') | ||||
| else: | else: | ||||
| high = self.high | high = self.high | ||||
| return high, low | |||||
| return low, high | |||||
| def _range(self, low=None, high=None): | def _range(self, low=None, high=None): | ||||
| r""" | r""" | ||||