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.

initializer.py 28 kB

code check for master # Conflicts: # mindspore/common/initializer.py # mindspore/nn/cell.py # # 似乎您正在做一个拣选提交。如果不对,请删除文件 # .git/CHERRY_PICK_HEAD # 然后重试。 # 请为您的变更输入提交说明。以 '#' 开始的行将被忽略,而一个空的提交 # 说明将会终止提交。 # # 日期: Fri Aug 13 18:40:19 2021 +0800 # # 位于分支 code_review_r1.3 # 您的分支与上游分支 'ma/r1.3' 一致。 # # 您在执行拣选提交 ffda6be35c 的操作。 # # 要提交的变更: # 修改: mindspore/common/__init__.py # 修改: mindspore/common/_register_for_tensor.py # 修改: mindspore/common/api.py # 修改: mindspore/common/dtype.py # 修改: mindspore/common/initializer.py # 修改: mindspore/common/monad.py # 修改: mindspore/common/parameter.py # 修改: mindspore/common/seed.py # 修改: mindspore/common/tensor.py # 修改: mindspore/nn/cell.py # 修改: mindspore/nn/metrics/__init__.py # 修改: mindspore/nn/metrics/confusion_matrix.py # 修改: mindspore/nn/metrics/error.py # 修改: mindspore/nn/metrics/fbeta.py # 修改: mindspore/nn/metrics/loss.py # 修改: mindspore/nn/metrics/metric.py # 修改: mindspore/nn/metrics/precision.py # 修改: mindspore/nn/metrics/recall.py # 修改: mindspore/nn/metrics/topk.py # 修改: mindspore/train/callback/_checkpoint.py # 修改: mindspore/train/model.py # 修改: mindspore/train/serialization.py # # Conflicts: # mindspore/common/api.py # mindspore/common/initializer.py # mindspore/nn/metrics/confusion_matrix.py # # 似乎您正在做一个拣选提交。如果不对,请删除文件 # .git/CHERRY_PICK_HEAD # 然后重试。 # 请为您的变更输入提交说明。以 '#' 开始的行将被忽略,而一个空的提交 # 说明将会终止提交。 # # 日期: Fri Aug 13 18:40:19 2021 +0800 # # 位于分支 code_review_master # 您的分支与上游分支 'ma/master' 一致。 # # 您在执行拣选提交 743f9fbff3 的操作。 # # 要提交的变更: # 修改: mindspore/common/__init__.py # 修改: mindspore/common/_monad.py # 修改: mindspore/common/_register_for_tensor.py # 修改: mindspore/common/api.py # 修改: mindspore/common/dtype.py # 修改: mindspore/common/initializer.py # 修改: mindspore/common/parameter.py # 修改: mindspore/common/seed.py # 修改: mindspore/common/tensor.py # 修改: mindspore/nn/cell.py # 修改: mindspore/nn/metrics/__init__.py # 修改: mindspore/nn/metrics/confusion_matrix.py # 修改: mindspore/nn/metrics/error.py # 修改: mindspore/nn/metrics/fbeta.py # 修改: mindspore/nn/metrics/loss.py # 修改: mindspore/nn/metrics/metric.py # 修改: mindspore/nn/metrics/precision.py # 修改: mindspore/nn/metrics/recall.py # 修改: mindspore/nn/metrics/topk.py # 修改: mindspore/train/callback/_checkpoint.py # 修改: mindspore/train/model.py # 修改: mindspore/train/serialization.py #
4 years ago
5 years ago
4 years ago
code check for master # Conflicts: # mindspore/common/initializer.py # mindspore/nn/cell.py # # 似乎您正在做一个拣选提交。如果不对,请删除文件 # .git/CHERRY_PICK_HEAD # 然后重试。 # 请为您的变更输入提交说明。以 '#' 开始的行将被忽略,而一个空的提交 # 说明将会终止提交。 # # 日期: Fri Aug 13 18:40:19 2021 +0800 # # 位于分支 code_review_r1.3 # 您的分支与上游分支 'ma/r1.3' 一致。 # # 您在执行拣选提交 ffda6be35c 的操作。 # # 要提交的变更: # 修改: mindspore/common/__init__.py # 修改: mindspore/common/_register_for_tensor.py # 修改: mindspore/common/api.py # 修改: mindspore/common/dtype.py # 修改: mindspore/common/initializer.py # 修改: mindspore/common/monad.py # 修改: mindspore/common/parameter.py # 修改: mindspore/common/seed.py # 修改: mindspore/common/tensor.py # 修改: mindspore/nn/cell.py # 修改: mindspore/nn/metrics/__init__.py # 修改: mindspore/nn/metrics/confusion_matrix.py # 修改: mindspore/nn/metrics/error.py # 修改: mindspore/nn/metrics/fbeta.py # 修改: mindspore/nn/metrics/loss.py # 修改: mindspore/nn/metrics/metric.py # 修改: mindspore/nn/metrics/precision.py # 修改: mindspore/nn/metrics/recall.py # 修改: mindspore/nn/metrics/topk.py # 修改: mindspore/train/callback/_checkpoint.py # 修改: mindspore/train/model.py # 修改: mindspore/train/serialization.py # # Conflicts: # mindspore/common/api.py # mindspore/common/initializer.py # mindspore/nn/metrics/confusion_matrix.py # # 似乎您正在做一个拣选提交。如果不对,请删除文件 # .git/CHERRY_PICK_HEAD # 然后重试。 # 请为您的变更输入提交说明。以 '#' 开始的行将被忽略,而一个空的提交 # 说明将会终止提交。 # # 日期: Fri Aug 13 18:40:19 2021 +0800 # # 位于分支 code_review_master # 您的分支与上游分支 'ma/master' 一致。 # # 您在执行拣选提交 743f9fbff3 的操作。 # # 要提交的变更: # 修改: mindspore/common/__init__.py # 修改: mindspore/common/_monad.py # 修改: mindspore/common/_register_for_tensor.py # 修改: mindspore/common/api.py # 修改: mindspore/common/dtype.py # 修改: mindspore/common/initializer.py # 修改: mindspore/common/parameter.py # 修改: mindspore/common/seed.py # 修改: mindspore/common/tensor.py # 修改: mindspore/nn/cell.py # 修改: mindspore/nn/metrics/__init__.py # 修改: mindspore/nn/metrics/confusion_matrix.py # 修改: mindspore/nn/metrics/error.py # 修改: mindspore/nn/metrics/fbeta.py # 修改: mindspore/nn/metrics/loss.py # 修改: mindspore/nn/metrics/metric.py # 修改: mindspore/nn/metrics/precision.py # 修改: mindspore/nn/metrics/recall.py # 修改: mindspore/nn/metrics/topk.py # 修改: mindspore/train/callback/_checkpoint.py # 修改: mindspore/train/model.py # 修改: mindspore/train/serialization.py #
4 years ago
4 years ago
4 years ago
code check for master # Conflicts: # mindspore/common/initializer.py # mindspore/nn/cell.py # # 似乎您正在做一个拣选提交。如果不对,请删除文件 # .git/CHERRY_PICK_HEAD # 然后重试。 # 请为您的变更输入提交说明。以 '#' 开始的行将被忽略,而一个空的提交 # 说明将会终止提交。 # # 日期: Fri Aug 13 18:40:19 2021 +0800 # # 位于分支 code_review_r1.3 # 您的分支与上游分支 'ma/r1.3' 一致。 # # 您在执行拣选提交 ffda6be35c 的操作。 # # 要提交的变更: # 修改: mindspore/common/__init__.py # 修改: mindspore/common/_register_for_tensor.py # 修改: mindspore/common/api.py # 修改: mindspore/common/dtype.py # 修改: mindspore/common/initializer.py # 修改: mindspore/common/monad.py # 修改: mindspore/common/parameter.py # 修改: mindspore/common/seed.py # 修改: mindspore/common/tensor.py # 修改: mindspore/nn/cell.py # 修改: mindspore/nn/metrics/__init__.py # 修改: mindspore/nn/metrics/confusion_matrix.py # 修改: mindspore/nn/metrics/error.py # 修改: mindspore/nn/metrics/fbeta.py # 修改: mindspore/nn/metrics/loss.py # 修改: mindspore/nn/metrics/metric.py # 修改: mindspore/nn/metrics/precision.py # 修改: mindspore/nn/metrics/recall.py # 修改: mindspore/nn/metrics/topk.py # 修改: mindspore/train/callback/_checkpoint.py # 修改: mindspore/train/model.py # 修改: mindspore/train/serialization.py # # Conflicts: # mindspore/common/api.py # mindspore/common/initializer.py # mindspore/nn/metrics/confusion_matrix.py # # 似乎您正在做一个拣选提交。如果不对,请删除文件 # .git/CHERRY_PICK_HEAD # 然后重试。 # 请为您的变更输入提交说明。以 '#' 开始的行将被忽略,而一个空的提交 # 说明将会终止提交。 # # 日期: Fri Aug 13 18:40:19 2021 +0800 # # 位于分支 code_review_master # 您的分支与上游分支 'ma/master' 一致。 # # 您在执行拣选提交 743f9fbff3 的操作。 # # 要提交的变更: # 修改: mindspore/common/__init__.py # 修改: mindspore/common/_monad.py # 修改: mindspore/common/_register_for_tensor.py # 修改: mindspore/common/api.py # 修改: mindspore/common/dtype.py # 修改: mindspore/common/initializer.py # 修改: mindspore/common/parameter.py # 修改: mindspore/common/seed.py # 修改: mindspore/common/tensor.py # 修改: mindspore/nn/cell.py # 修改: mindspore/nn/metrics/__init__.py # 修改: mindspore/nn/metrics/confusion_matrix.py # 修改: mindspore/nn/metrics/error.py # 修改: mindspore/nn/metrics/fbeta.py # 修改: mindspore/nn/metrics/loss.py # 修改: mindspore/nn/metrics/metric.py # 修改: mindspore/nn/metrics/precision.py # 修改: mindspore/nn/metrics/recall.py # 修改: mindspore/nn/metrics/topk.py # 修改: mindspore/train/callback/_checkpoint.py # 修改: mindspore/train/model.py # 修改: mindspore/train/serialization.py #
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
5 years ago
5 years ago
5 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
5 years ago
5 years ago
4 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761
  1. # Copyright 2020-2021 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. """Initializer for cell parameters."""
  16. import numbers
  17. import math
  18. from functools import reduce
  19. import numpy as np
  20. from scipy.stats import truncnorm
  21. from .seed import get_seed, _get_graph_seed
  22. from . import dtype as mstype
  23. from .tensor import Tensor
  24. from .._c_expression import random_normal
  25. _INITIALIZER_ALIAS = dict()
  26. class Initializer:
  27. """
  28. The abstract base class of the initializer.
  29. Args:
  30. kwargs (dict): Keyword arguments for Initializer.
  31. """
  32. def __init__(self, **kwargs):
  33. self._kwargs = kwargs
  34. self._seed = None
  35. @property
  36. def seed(self):
  37. if self._seed is None:
  38. seed, seed2 = _get_graph_seed(get_seed(), "init")
  39. else:
  40. seed, seed2 = self._seed + 1, 0
  41. return seed, seed2
  42. @seed.setter
  43. def seed(self, value):
  44. self._seed = value
  45. def _initialize(self, *kwargs):
  46. raise NotImplementedError('Must be overridden!')
  47. def __call__(self, arr):
  48. return self._initialize(arr)
  49. def _register(*aliases):
  50. """Return the alias register."""
  51. def alias_reg(cls):
  52. name = cls.__name__
  53. name = name.lower()
  54. if name not in _INITIALIZER_ALIAS:
  55. _INITIALIZER_ALIAS[name] = cls
  56. for alias in aliases:
  57. if alias not in _INITIALIZER_ALIAS:
  58. _INITIALIZER_ALIAS[alias] = cls
  59. return cls
  60. return alias_reg
  61. def _assignment(arr, num):
  62. """Assign the value of `num` to `arr`."""
  63. if arr.shape == ():
  64. arr = arr.reshape(1)
  65. arr[:] = num
  66. arr = arr.reshape(())
  67. else:
  68. if isinstance(num, np.ndarray):
  69. arr[:] = num[:]
  70. else:
  71. arr[:] = num
  72. return arr
  73. @_register('zeros')
  74. class Zero(Initializer):
  75. """
  76. Generates an array with constant value of zero in order to initialize a tensor.
  77. Examples:
  78. >>> import mindspore
  79. >>> from mindspore.common.initializer import initializer, Zero
  80. >>> tensor1 = initializer(Zero(), [1, 2, 3], mindspore.float32)
  81. >>> tensor2 = initializer('zeros', [1, 2, 3], mindspore.float32)
  82. """
  83. def _initialize(self, arr):
  84. _assignment(arr, 0)
  85. @_register('ones')
  86. class One(Initializer):
  87. """
  88. Generates an array with constant value of one in order to initialize a tensor.
  89. Examples:
  90. >>> import mindspore
  91. >>> from mindspore.common.initializer import initializer, One
  92. >>> tensor1 = initializer(One(), [1, 2, 3], mindspore.float32)
  93. >>> tensor2 = initializer('ones', [1, 2, 3], mindspore.float32)
  94. """
  95. def _initialize(self, arr):
  96. _assignment(arr, 1)
  97. def _calculate_fan_in_and_fan_out(shape):
  98. """
  99. calculate fan_in and fan_out
  100. Args:
  101. shape (tuple): input shape.
  102. Returns:
  103. Tuple, a tuple with two elements, the first element is `n_in` and the second element is `n_out`.
  104. """
  105. dimensions = len(shape)
  106. if dimensions < 2:
  107. raise ValueError("'fan_in' and 'fan_out' can not be computed for tensor with fewer than"
  108. " 2 dimensions, but got dimensions {}.".format(dimensions))
  109. if dimensions == 2: # Linear
  110. fan_in = shape[1]
  111. fan_out = shape[0]
  112. else:
  113. num_input_fmaps = shape[1]
  114. num_output_fmaps = shape[0]
  115. receptive_field_size = 1
  116. for i in range(2, dimensions):
  117. receptive_field_size *= shape[i]
  118. fan_in = num_input_fmaps * receptive_field_size
  119. fan_out = num_output_fmaps * receptive_field_size
  120. return fan_in, fan_out
  121. def _calculate_correct_fan(shape, mode):
  122. """
  123. Calculate fan.
  124. Args:
  125. shape (tuple): input shape.
  126. mode (str): only support fan_in and fan_out.
  127. Returns:
  128. fan_in or fan_out.
  129. """
  130. mode = mode.lower()
  131. valid_modes = ['fan_in', 'fan_out']
  132. if mode not in valid_modes:
  133. raise ValueError("'mode' {} not supported, please use one of {}".format(mode, valid_modes))
  134. fan_in, fan_out = _calculate_fan_in_and_fan_out(shape)
  135. return fan_in if mode == 'fan_in' else fan_out
  136. def _calculate_gain(nonlinearity, param=None):
  137. """
  138. Calculate gain.
  139. Args:
  140. nonlinearity (str): nonlinearity function.
  141. param (str): used to calculate negative_slope.
  142. Returns:
  143. number.
  144. """
  145. linear_fns = ['linear', 'conv1d', 'conv2d', 'conv3d', 'conv_transpose1d', 'conv_transpose2d', 'conv_transpose3d']
  146. if nonlinearity in linear_fns or nonlinearity == 'sigmoid':
  147. res = 1
  148. elif nonlinearity == 'tanh':
  149. res = 5.0 / 3
  150. elif nonlinearity == 'relu':
  151. res = math.sqrt(2.0)
  152. elif nonlinearity == 'leaky_relu':
  153. if param is None:
  154. negative_slope = 0.01
  155. elif not isinstance(param, bool) and isinstance(param, int) or isinstance(param, float):
  156. # True/False are instances of int, hence check above
  157. negative_slope = param
  158. else:
  159. raise ValueError("'negative_slope' {} is not a valid number. When 'nonlinearity' has been set to "
  160. "'leaky_relu', 'negative_slope' should be int or float type, but got "
  161. "{}.".format(param, type(param)))
  162. res = math.sqrt(2.0 / (1 + negative_slope ** 2))
  163. else:
  164. raise ValueError("The argument 'nonlinearity' should be one of ['sigmoid', 'tanh', 'relu' or 'leaky_relu'], "
  165. "but got {}.".format(nonlinearity))
  166. return res
  167. def _calculate_in_and_out(arr):
  168. """
  169. Calculate n_in and n_out.
  170. Args:
  171. arr (Array): Input array.
  172. Returns:
  173. Tuple, a tuple with two elements, the first element is `n_in` and the second element is `n_out`.
  174. """
  175. dim = len(arr.shape)
  176. if dim < 2:
  177. raise ValueError("If initialize data with xavier uniform, the dimension of data must be greater than 1, "
  178. "but got {}.".format(dim))
  179. n_in = arr.shape[1]
  180. n_out = arr.shape[0]
  181. if dim > 2:
  182. counter = reduce(lambda x, y: x * y, arr.shape[2:])
  183. n_in *= counter
  184. n_out *= counter
  185. return n_in, n_out
  186. @_register('xavier_uniform')
  187. class XavierUniform(Initializer):
  188. r"""
  189. Generates an array with values sampled from Xavier uniform distribution
  190. :math:`{U}(-\text{boundary}, \text{boundary})` in order to initialize a tensor, where:
  191. .. math::
  192. boundary = gain * \sqrt{\frac{6}{n_{in} + n_{out}}}
  193. - where :math:`gain` is an optional scaling factor.
  194. - where :math:`n_{in}` is the number of input units in the weight tensor.
  195. - where :math:`n_{out}` is the number of output units in the weight tensor.
  196. For details of XavierUniform algorithm, please check
  197. `<http://proceedings.mlr.press/v9/glorot10a.html>`_.
  198. Args:
  199. gain (float): An optional scaling factor. Default: 1.
  200. Examples:
  201. >>> import mindspore
  202. >>> from mindspore.common.initializer import initializer, XavierUniform
  203. >>> tensor1 = initializer(XavierUniform(), [1, 2, 3], mindspore.float32)
  204. >>> tensor2 = initializer('xavier_uniform', [1, 2, 3], mindspore.float32)
  205. """
  206. def __init__(self, gain=1):
  207. super(XavierUniform, self).__init__(gain=gain)
  208. self.gain = gain
  209. def _initialize(self, arr):
  210. n_in, n_out = _calculate_fan_in_and_fan_out(arr.shape)
  211. boundary = self.gain * math.sqrt(6.0 / (n_in + n_out))
  212. data = np.random.uniform(-boundary, boundary, arr.shape)
  213. _assignment(arr, data)
  214. @_register('he_uniform')
  215. class HeUniform(Initializer):
  216. r"""
  217. Generates an array with values sampled from HeKaiming Uniform distribution
  218. :math:`{U}(-\text{boundary}, \text{boundary})` in order to initialize a tensor, where
  219. .. math::
  220. boundary = \sqrt{\frac{6}{(1 + a^2) \times \text{fan_in}}}
  221. which is the bound of the HeUniform distribution.
  222. For details of HeUniform algorithm, please check
  223. `<https://arxiv.org/abs/1502.01852>`_.
  224. Args:
  225. negative_slope (int, float, bool): The negative slope of the rectifier used after this layer
  226. (only used when `nonlinearity` is 'leaky_relu'). Default: 0.
  227. mode (str): Either 'fan_in' or 'fan_out'. Choosing 'fan_in' preserves the magnitude of the
  228. variance of the weights in the forward pass. Choosing 'fan_out' preserves the magnitudes
  229. in the backwards pass. Default: fan_in.
  230. nonlinearity (str): The non-linear function, recommended to use only with 'relu' or 'leaky_relu'.
  231. Default: leaky_relu.
  232. Examples:
  233. >>> import mindspore
  234. >>> from mindspore.common.initializer import initializer, HeUniform
  235. >>> tensor1 = initializer(HeUniform(), [1, 2, 3], mindspore.float32)
  236. >>> tensor2 = initializer('he_uniform', [1, 2, 3], mindspore.float32)
  237. """
  238. def __init__(self, negative_slope=0, mode='fan_in', nonlinearity='leaky_relu'):
  239. super(HeUniform, self).__init__(negative_slope=negative_slope, mode=mode, nonlinearity=nonlinearity)
  240. self.negative_slope = negative_slope
  241. self.mode = mode
  242. self.nonlinearity = nonlinearity
  243. def _initialize(self, arr):
  244. fan = _calculate_correct_fan(arr.shape, self.mode)
  245. gain = _calculate_gain(self.nonlinearity, self.negative_slope)
  246. std = gain / math.sqrt(fan)
  247. boundary = math.sqrt(3.0) * std
  248. data = np.random.uniform(-boundary, boundary, arr.shape)
  249. _assignment(arr, data)
  250. @_register('he_normal')
  251. class HeNormal(Initializer):
  252. r"""
  253. Generates an array with values sampled from HeKaiming Normal distribution
  254. :math:`{N}(0, \text{sigma}^2)` in order to initialize a tensor, where
  255. .. math::
  256. sigma = \frac{gain} {\sqrt{N}}
  257. where :math:`gain` is an optional scaling factor. :math: `N` is the number of input units of the weight tensor,
  258. if `mode` is 'fan_in'. If `mode` is 'fan_out', it is the number of output units.
  259. For details of HeUniform algorithm, please check `<https://arxiv.org/abs/1502.01852>`_.
  260. Args:
  261. negative_slope (int, float, bool): The negative slope of the rectifier used after this layer
  262. (only used when `nonlinearity` is 'leaky_relu'). Default: 0.
  263. mode (str): Either 'fan_in' or 'fan_out'. Choosing 'fan_in' preserves the magnitude of the
  264. variance of the weights in the forward pass. Choosing 'fan_out' preserves the magnitudes
  265. in the backwards pass. Default: fan_in.
  266. nonlinearity (str): The non-linear function, recommended to use only with 'relu' or 'leaky_relu'.
  267. Default: leaky_relu.
  268. Examples:
  269. >>> import mindspore
  270. >>> from mindspore.common.initializer import initializer, HeNormal
  271. >>> tensor1 = initializer(HeNormal(), [1, 2, 3], mindspore.float32)
  272. >>> tensor2 = initializer('he_normal', [1, 2, 3], mindspore.float32)
  273. """
  274. def __init__(self, negative_slope=0, mode='fan_in', nonlinearity='leaky_relu'):
  275. super(HeNormal, self).__init__(negative_slope=negative_slope, mode=mode, nonlinearity=nonlinearity)
  276. self.negative_slope = negative_slope
  277. self.mode = mode
  278. self.nonlinearity = nonlinearity
  279. def _initialize(self, arr):
  280. fan = _calculate_correct_fan(arr.shape, self.mode)
  281. gain = _calculate_gain(self.nonlinearity, self.negative_slope)
  282. std = gain / math.sqrt(fan)
  283. data = np.random.normal(0, std, arr.shape)
  284. _assignment(arr, data)
  285. class Constant(Initializer):
  286. """
  287. Generates an array with constant value in order to initialize a tensor.
  288. Args:
  289. value (Union[int, numpy.ndarray]): The value to initialize.
  290. Examples:
  291. >>> import mindspore
  292. >>> from mindspore.common.initializer import initializer
  293. >>> tensor1 = initializer(0, [1, 2, 3], mindspore.float32)
  294. >>> tensor2 = initializer(5, [1, 2, 3], mindspore.float32)
  295. """
  296. def __init__(self, value):
  297. super(Constant, self).__init__(value=value)
  298. self.value = value
  299. def _initialize(self, arr):
  300. _assignment(arr, self.value)
  301. @_register()
  302. class Identity(Initializer):
  303. """
  304. Initialize a 2 dimension identity matrix to fill the input tensor.
  305. Raises:
  306. ValueError: If the dimension of input tensor is not equal to 2.
  307. Examples:
  308. >>> import mindspore
  309. >>> from mindspore.common.initializer import initializer, Identity
  310. >>> tensor1 = initializer(Identity(), [2, 3], mindspore.float32)
  311. >>> tensor2 = initializer('identity', [2, 3], mindspore.float32)
  312. """
  313. def _initialize(self, arr):
  314. if len(arr.shape) != 2:
  315. raise ValueError('For Identity initializer, the dimension of the initialized tensor should be 2, '
  316. 'but got {}.'.format(len(arr.shape)))
  317. value = np.eye(arr.shape[0], arr.shape[1])
  318. _assignment(arr, value)
  319. @_register()
  320. class Sparse(Initializer):
  321. """
  322. Initialize a 2 dimension sparse matrix to fill the input tensor. The non-zero positions will be filled with
  323. the value sampled from the normal distribution :math:`{N}(0, 0.01)`
  324. Args:
  325. sparsity (float): The fraction of elements being set to zero in each column.
  326. sigma (float): The standard deviation of the normal distribution. Default: 0.01.
  327. Raises:
  328. ValueError: If the dimension of input tensor is not equal to 2.
  329. Examples:
  330. >>> import mindspore
  331. >>> from mindspore.common.initializer import initializer, Sparse
  332. >>> tensor1 = initializer(Sparse(sparsity=0.1, sigma=0.01), [5, 8], mindspore.float32)
  333. """
  334. def __init__(self, sparsity, sigma=0.01):
  335. super(Sparse, self).__init__()
  336. self.sparsity = sparsity
  337. self.sigma = sigma
  338. def _initialize(self, arr):
  339. if len(arr.shape) != 2:
  340. raise ValueError('For Sparse initializer, the dimension of the initialized tensor should be 2, '
  341. 'but got {}.'.format(len(arr.shape)))
  342. rows, cols = arr.shape
  343. zero_num = int(np.ceil(self.sparsity * rows))
  344. data = np.random.normal(0, self.sigma, arr.shape)
  345. for col_idx in range(cols):
  346. row_idx = np.random.permutation(list(range(rows)))[: zero_num]
  347. data[row_idx, col_idx] = 0.
  348. _assignment(arr, data)
  349. @_register()
  350. class Dirac(Initializer):
  351. """Initialize input tensor with the Dirac delta function. It tries to preserves the identity of
  352. input for convolution layers. For group convolution, each group of channels will be preserved respectively.
  353. Args:
  354. groups (int): The number of group in convolution layer. Default: 1.
  355. Raises:
  356. ValueError: If the value of group is not in [3, 4, 5].
  357. ValueError: The first dimension of the initialized tensor cannot be divisible by group.
  358. Examples:
  359. >>> import mindspore
  360. >>> from mindspore.common.initializer import initializer, Dirac
  361. >>> tensor1 = initializer(Dirac(groups=2), [6, 4, 3, 3], mindspore.float32)
  362. >>> tensor2 = initializer("dirac", [6, 4, 3, 3], mindspore.float32)
  363. """
  364. def __init__(self, groups=1):
  365. super(Dirac, self).__init__()
  366. self.groups = groups
  367. def _initialize(self, arr):
  368. dimension = len(arr.shape)
  369. data = np.zeros(arr.shape)
  370. if dimension not in [3, 4, 5]:
  371. raise ValueError("For Dirac initializer, only support "
  372. "to initialize tensor with dimension of 3, 4 or 5, but got {}.".format(dimension))
  373. shapes = arr.shape
  374. if shapes[0] % self.groups != 0:
  375. raise ValueError("For Dirac initializer, the first dimension of"
  376. "the initialized tensor must be divisible by group, "
  377. "but got {}/{}.".format(shapes[0], self.groups))
  378. out_channel_per_group = shapes[0] // self.groups
  379. min_dim = min(out_channel_per_group, shapes[1])
  380. for group in range(self.groups):
  381. for dim in range(min_dim):
  382. if dimension == 3:
  383. data[group * out_channel_per_group + dim, dim, shapes[2]//2] = 1
  384. elif dimension == 4:
  385. data[group * out_channel_per_group + dim, dim, shapes[2] // 2, shapes[3] // 2] = 1
  386. else:
  387. data[group * out_channel_per_group + dim, dim, shapes[2] // 2, shapes[3] // 2, shapes[4] // 2] = 1
  388. _assignment(arr, data)
  389. @_register()
  390. class Orthogonal(Initializer):
  391. r"""
  392. Initialize a (semi) orthogonal matrix to fill the input tensor. The dimension of input tensor must have at least 2
  393. dimensions. If the dimension is greater than 2, the trailing dimensions will be flattened.
  394. Args:
  395. gain (float): An optional scaling factor. Default: 1.
  396. Raises:
  397. ValueError: If the dimension of input tensor is less than 2.
  398. Examples:
  399. >>> import mindspore
  400. >>> from mindspore.common.initializer import initializer, Orthogonal
  401. >>> tensor1 = initializer(Orthogonal(gain=2.), [2, 3, 4], mindspore.float32)
  402. >>> tensor2 = initializer('orthogonal', [2, 3, 4], mindspore.float32)
  403. """
  404. def __init__(self, gain=1.):
  405. super(Orthogonal, self).__init__(gain=gain)
  406. self.gain = gain
  407. def _initialize(self, arr):
  408. if len(arr.shape) < 2:
  409. raise ValueError('For Orthogonal initializer, the dimension of the initialized tensor should'
  410. ' be no less than 2, but got {}.'.format(len(arr.shape)))
  411. rows = arr.shape[0]
  412. cols = np.prod(arr.shape) // rows
  413. data = np.random.normal(0, 1, size=(rows, cols))
  414. if rows < cols:
  415. data = data.T
  416. q, r = np.linalg.qr(data)
  417. d = np.diag(r)
  418. ph = np.sign(d)
  419. q *= ph
  420. if rows < cols:
  421. q = q.T
  422. q = q * self.gain
  423. _assignment(arr, q.reshape(arr.shape))
  424. @_register()
  425. class VarianceScaling(Initializer):
  426. r"""
  427. Randomly initialize an array with scaling to fill the input tensor.
  428. When distribution is truncated_normal or untruncated_normal, the value will be sampled from truncated or
  429. untruncated normal distribution with a mean of 0 and a scaled standard deviation :math:`stddev = sqrt(scale/n)`.
  430. :math:`n` will be the number of input units if mode is fan_in, the number of output units if mode is fan_out,
  431. the average of fan_in and fan_out if mode is fan_avg.
  432. When distribution is uniform, the value will be sampled from a uniform distribution within the limit of
  433. [`-sqrt(3*scale/n)`, `sqrt(3*scale/n)`].
  434. Args:
  435. scale (float): The scaling factor. Default: 1.0.
  436. mode (str): Should be 'fan_in', 'fan_out' or 'fan_avg'. Default: 'fan_in'.
  437. distribution(str): The type of distribution chose to sample values. Default: 'truncated_normal'.
  438. Raises:
  439. ValueError: If scale is not greater than 0.
  440. ValueError: If mode is not fan_in, fan_out or fan_avg.
  441. ValueError: If distribution is not uniform, truncated_normal or untruncated_normal.
  442. Examples:
  443. >>> import mindspore
  444. >>> from mindspore.common.initializer import initializer, VarianceScaling
  445. >>> tensor1 = initializer(VarianceScaling(scale=1.0, mode='fan_out',
  446. ... distribution='untruncated_normal'), [2, 3], mindspore.float32)
  447. >>> tensor2 = initializer('varianceScaling', [2, 3], mindspore.float32)
  448. """
  449. def __init__(self, scale=1.0, mode='fan_in', distribution='truncated_normal'):
  450. super(VarianceScaling, self).__init__(scale=scale, mode=mode, distribution=distribution)
  451. if scale <= 0.:
  452. raise ValueError("For VarianceScaling initializer, scale must be greater than 0, but got {}.".format(scale))
  453. if mode not in ['fan_in', 'fan_out', 'fan_avg']:
  454. raise ValueError('For VarianceScaling initializer, mode must be fan_in, '
  455. 'fan_out or fan_avg, but got {}.'.format(mode))
  456. if distribution not in ['uniform', 'truncated_normal', 'untruncated_normal']:
  457. raise ValueError('For VarianceScaling initializer, distribution must be uniform, '
  458. 'truncated_norm or untruncated_norm, but got {}.'.format(distribution))
  459. self.scale = scale
  460. self.mode = mode
  461. self.distribution = distribution
  462. def _initialize(self, arr):
  463. scale = self.scale
  464. fan_in, fan_out = _calculate_fan_in_and_fan_out(arr.shape)
  465. if self.mode == 'fan_in':
  466. scale /= max(1., fan_in)
  467. elif self.mode == 'fan_out':
  468. scale /= max(1., fan_out)
  469. else:
  470. scale /= max(1., (fan_in + fan_out) / 2.)
  471. if self.distribution == 'truncated_norm':
  472. stddev = np.sqrt(scale) / 0.87962566103423978
  473. data = truncnorm.rvs(-2, 2, loc=0, scale=stddev, size=arr.shape, random_state=None)
  474. elif self.distribution == 'untruncated_normal':
  475. stddev = np.sqrt(scale)
  476. data = np.random.normal(0, stddev, arr.shape)
  477. else:
  478. limit = np.sqrt(3.0 * scale)
  479. data = np.random.uniform(-limit, limit, arr.shape)
  480. _assignment(arr, data)
  481. @_register()
  482. class Uniform(Initializer):
  483. r"""
  484. Generates an array with values sampled from Uniform distribution :math:`{U}(-\text{scale}, \text{scale})` in order
  485. to initialize a tensor.
  486. Args:
  487. scale (float): The bound of the Uniform distribution. Default: 0.07.
  488. Examples:
  489. >>> import mindspore
  490. >>> from mindspore.common.initializer import initializer, Uniform
  491. >>> tensor1 = initializer(Uniform(), [1, 2, 3], mindspore.float32)
  492. >>> tensor2 = initializer('uniform', [1, 2, 3], mindspore.float32)
  493. """
  494. def __init__(self, scale=0.07):
  495. super(Uniform, self).__init__(scale=scale)
  496. self.scale = scale
  497. def _initialize(self, arr):
  498. tmp = np.random.uniform(-self.scale, self.scale, arr.shape)
  499. _assignment(arr, tmp)
  500. @_register()
  501. class Normal(Initializer):
  502. r"""
  503. Generates an array with values sampled from Normal distribution :math:`{N}(\text{sigma}, \text{mean})` in order to
  504. initialize a tensor.
  505. .. math::
  506. f(x) = \frac{1} {\sqrt{2*π} * sigma}exp(-\frac{(x - mean)^2} {2*{sigma}^2})
  507. Args:
  508. sigma (float): The standard deviation of Normal distribution. Default: 0.01.
  509. mean (float): The mean of Normal distribution. Default: 0.0.
  510. Examples:
  511. >>> import mindspore
  512. >>> from mindspore.common.initializer import initializer, Normal
  513. >>> tensor1 = initializer(Normal(), [1, 2, 3], mindspore.float32)
  514. >>> tensor2 = initializer('normal', [1, 2, 3], mindspore.float32)
  515. """
  516. def __init__(self, sigma=0.01, mean=0.0):
  517. super(Normal, self).__init__(sigma=sigma, mean=mean)
  518. self.sigma = sigma
  519. self.mean = mean
  520. def _initialize(self, arr):
  521. seed, seed2 = self.seed
  522. output_tensor = Tensor(np.zeros(arr.shape, dtype=np.float32))
  523. random_normal(arr.shape, seed, seed2, output_tensor)
  524. output_data = output_tensor.asnumpy()
  525. output_data = output_data * self.sigma + self.mean
  526. _assignment(arr, output_data)
  527. @_register()
  528. class TruncatedNormal(Initializer):
  529. r"""
  530. Generates an array with values sampled from Truncated Normal distribution in order to initialize a tensor.
  531. Args:
  532. sigma (float): The standard deviation of Truncated Normal distribution. Default: 0.01.
  533. Examples:
  534. >>> import mindspore
  535. >>> from mindspore.common.initializer import initializer, TruncatedNormal
  536. >>> tensor1 = initializer(TruncatedNormal(), [1, 2, 3], mindspore.float32)
  537. >>> tensor2 = initializer('truncatedNormal', [1, 2, 3], mindspore.float32)
  538. """
  539. def __init__(self, sigma=0.01):
  540. super(TruncatedNormal, self).__init__(sigma=sigma)
  541. self.sigma = sigma
  542. def _initialize(self, arr):
  543. tmp = truncnorm.rvs(-2, 2, loc=0, scale=self.sigma, size=arr.shape, random_state=None)
  544. _assignment(arr, tmp)
  545. def initializer(init, shape=None, dtype=mstype.float32):
  546. """
  547. Create and initialize a tensor.
  548. Args:
  549. init (Union[Tensor, str, Initializer, numbers.Number]): Initialize value.
  550. - `str`: The `init` should be the alias of the class inheriting from `Initializer` and the corresponding
  551. class will be called in practice. The value of 'init' can be "normal", "ones" or "zeros", etc.
  552. - `Initializer`: The `init` should be the class inheriting from `Initializer` to initialize tensor.
  553. - `numbers.Number`: The `Constant` will be called to initialize tensor.
  554. shape (Union[tuple, list, int]): The shape of the initialized tensor. Default: None.
  555. dtype (:class:`mindspore.dtype`): The type of data in initialized tensor. Default: mindspore.float32.
  556. Returns:
  557. Tensor, return is Tensor object.
  558. Raises:
  559. TypeError: The type of the argument 'init' is not correct.
  560. ValueError: The shape of the tensor which is passed through 'init' is not the same as that passed by 'shape'.
  561. Examples:
  562. >>> import mindspore
  563. >>> from mindspore.common.initializer import initializer, One
  564. >>> tensor1 = initializer('ones', [1, 2, 3], mindspore.float32)
  565. >>> tensor2 = initializer(One(), [1, 2, 3], mindspore.float32)
  566. >>> tensor3 = initializer(0, [1, 2, 3], mindspore.float32)
  567. """
  568. if not isinstance(init, (Tensor, numbers.Number, str, Initializer)):
  569. raise TypeError("The type of the 'init' argument should be 'Tensor', 'number', 'string' "
  570. "or 'initializer', but got {}.".format(type(init)))
  571. if isinstance(init, Tensor):
  572. init_shape = init.shape
  573. shape = shape if isinstance(shape, (tuple, list)) else [shape]
  574. if shape is not None and init_shape != tuple(shape):
  575. raise ValueError("The shape of the 'init' argument should be same as the argument 'shape', but got the "
  576. "'init' shape {} and the 'shape' {}.".format(list(init.shape), shape))
  577. return init
  578. if isinstance(shape, list):
  579. shape = tuple(shape)
  580. elif isinstance(shape, numbers.Number):
  581. shape = (shape,)
  582. for value in shape if shape is not None else ():
  583. if not isinstance(value, int) or value <= 0:
  584. raise ValueError(f"The argument 'shape' is invalid, the value of 'shape' must be positive integer, "
  585. f"but got {shape}")
  586. if isinstance(init, str):
  587. init = _INITIALIZER_ALIAS[init.lower()]()
  588. if init is None:
  589. raise ValueError("The class corresponding to '{}' was not found.".format(init))
  590. elif isinstance(init, numbers.Number):
  591. init = Constant(init)
  592. shape = shape if shape is not None else init.shape
  593. init_obj = Tensor(dtype=dtype, shape=shape, init=init)
  594. return init_obj
  595. __all__ = [
  596. 'Initializer',
  597. 'initializer',
  598. 'TruncatedNormal',
  599. 'Normal',
  600. 'Uniform',
  601. 'HeUniform',
  602. 'HeNormal',
  603. 'XavierUniform',
  604. 'One',
  605. 'Zero',
  606. 'Constant',
  607. 'Identity',
  608. 'Sparse',
  609. 'Dirac',
  610. 'Orthogonal',
  611. 'VarianceScaling']