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.

initializers.py 10 kB

4 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. from hetu.gpu_ops import Variable
  2. from hetu import cpu_links as cpu_op
  3. from hetu import gpu_links as gpu_op
  4. from hetu import ndarray
  5. import numpy as np
  6. import ctypes
  7. class BaseInit(object):
  8. def __init__(self, shape):
  9. self.shape = tuple(shape)
  10. def __call__(self, node, seed, np_rand=None, stream=None):
  11. self.node = node
  12. self.seed = seed + node.id
  13. node.tensor_value = ndarray.empty(self.shape, ctx=node.ctx)
  14. if ndarray.is_gpu_ctx(node.ctx):
  15. self.init_on_gpu(stream)
  16. else:
  17. self.init_on_cpu(np_rand)
  18. def init_on_gpu(self, stream):
  19. raise NotImplementedError
  20. def init_on_cpu(self, np_rand):
  21. raise NotImplementedError
  22. def init_on_ps(self, comm, nid, param_type, init_type, arg1, arg2, seed, opt):
  23. # param types: Dense 0, Sparse 1, CacheSparse 2
  24. if param_type == 0:
  25. length = np.prod(self.shape)
  26. width = 1
  27. else:
  28. assert len(self.shape) == 2
  29. length = self.shape[0]
  30. width = self.shape[1]
  31. comm.InitTensor(nid, ctypes.c_int(param_type), ctypes.c_int(length), ctypes.c_int(width),
  32. ctypes.c_int(init_type), ctypes.c_double(arg1), ctypes.c_double(arg2), ctypes.c_ulonglong(seed), opt[0], opt[1], opt[2])
  33. class ConstantInit(BaseInit):
  34. def __init__(self, constant, shape):
  35. super().__init__(shape)
  36. self.constant = constant
  37. def init_on_gpu(self, stream):
  38. gpu_op.array_set(self.node.tensor_value, self.constant, stream)
  39. def init_on_cpu(self, np_rand):
  40. from ._base import DNNL_LIB
  41. if DNNL_LIB['cpu_ArraySet']:
  42. cpu_op.array_set(self.node.tensor_value, self.constant)
  43. else:
  44. self.node.tensor_value[:] = np.full(
  45. self.shape, self.constant).astype(np.float32)
  46. def init_on_ps(self, comm, nid, param_type, seed, opt):
  47. super().init_on_ps(comm, nid, param_type, 0, self.constant, 1.0, seed, opt)
  48. class ZerosInit(ConstantInit):
  49. def __init__(self, shape):
  50. super().__init__(0.0, shape)
  51. class OnesInit(ConstantInit):
  52. def __init__(self, shape):
  53. super().__init__(1.0, shape)
  54. class UniformInit(BaseInit):
  55. def __init__(self, low, high, shape):
  56. super().__init__(shape)
  57. self.low = low
  58. self.high = high
  59. def init_on_gpu(self, stream):
  60. gpu_op.uniform_init(self.node.tensor_value, self.low,
  61. self.high, self.seed, stream)
  62. def init_on_cpu(self, np_rand):
  63. from ._base import DNNL_LIB
  64. if DNNL_LIB['cpu_UniformInit']:
  65. cpu_op.uniform_init(self.node.tensor_value,
  66. self.low, self.high, self.seed)
  67. else:
  68. self.node.tensor_value[:] = np_rand.uniform(
  69. low=self.low, high=self.high, size=self.shape).astype(np.float32)
  70. def init_on_ps(self, comm, nid, param_type, seed, opt):
  71. super().init_on_ps(comm, nid, param_type, 1, self.low, self.high, seed, opt)
  72. class GeneralizedXavierUniformInit(UniformInit):
  73. def __init__(self, gain, mode, shape):
  74. assert mode in ('fan_in', 'fan_out',
  75. 'avg'), 'Mode %s not valid.' % mode
  76. assert gain > 0, 'Gain value %s not valid.' % str(gain)
  77. assert len(
  78. shape) >= 2, 'Generalized xavier requires shape to be at least 2D.'
  79. hw_scale = 1 if len(shape) == 2 else np.prod(shape[2:])
  80. fan_in = hw_scale * shape[1]
  81. fan_out = hw_scale * shape[0]
  82. if mode == 'fan_in':
  83. factor = fan_in
  84. elif mode == 'fan_out':
  85. factor = fan_out
  86. else:
  87. factor = (fan_in + fan_out) / 2.0
  88. limit = np.sqrt(gain / factor)
  89. super().__init__(-limit, limit, shape)
  90. class XavierUniformInit(GeneralizedXavierUniformInit):
  91. def __init__(self, shape):
  92. super().__init__(3.0, 'avg', shape)
  93. class HeUniformInit(GeneralizedXavierUniformInit):
  94. def __init__(self, shape):
  95. super().__init__(6.0, 'fan_in', shape)
  96. class LecunUniformInit(GeneralizedXavierUniformInit):
  97. def __init__(self, shape):
  98. super().__init__(3.0, 'fan_in', shape)
  99. class NormalInit(BaseInit):
  100. def __init__(self, mean, stddev, shape):
  101. super().__init__(shape)
  102. self.mean = mean
  103. self.stddev = stddev
  104. def init_on_gpu(self, stream):
  105. gpu_op.normal_init(self.node.tensor_value, self.mean,
  106. self.stddev, self.seed, stream)
  107. def init_on_cpu(self, np_rand):
  108. from ._base import DNNL_LIB
  109. if DNNL_LIB['cpu_NormalInit']:
  110. cpu_op.normal_init(self.node.tensor_value,
  111. self.mean, self.stddev, self.seed)
  112. else:
  113. self.node.tensor_value[:] = np_rand.normal(
  114. loc=self.mean, scale=self.stddev, size=self.shape).astype(np.float32)
  115. def init_on_ps(self, comm, nid, param_type, seed, opt):
  116. super().init_on_ps(comm, nid, param_type, 2, self.mean, self.stddev, seed, opt)
  117. class GeneralizedXavierNormalInit(NormalInit):
  118. def __init__(self, gain, mode, shape):
  119. assert mode in ('fan_in', 'fan_out', 'avg'), 'Mode not allowed.'
  120. assert gain > 0, 'Gain value not allowed.'
  121. assert len(
  122. shape) >= 2, 'Generalized xavier requires shape to be at least 2D.'
  123. hw_scale = 1 if len(shape) == 2 else np.prod(shape[2:])
  124. fan_in = hw_scale * shape[1]
  125. fan_out = hw_scale * shape[0]
  126. if mode == 'fan_in':
  127. factor = fan_in
  128. elif mode == 'fan_out':
  129. factor = fan_out
  130. else:
  131. factor = (fan_in + fan_out) / 2.0
  132. scale = np.sqrt(gain / factor)
  133. super().__init__(0, scale, shape)
  134. class XavierNormalInit(GeneralizedXavierNormalInit):
  135. def __init__(self, shape):
  136. super().__init__(1.0, 'avg', shape)
  137. class HeNormalInit(GeneralizedXavierNormalInit):
  138. def __init__(self, shape):
  139. super().__init__(2.0, 'fan_in', shape)
  140. class LecunNormalInit(GeneralizedXavierNormalInit):
  141. def __init__(self, shape):
  142. super().__init__(1.0, 'fan_in', shape)
  143. class TruncatedNormalInit(BaseInit):
  144. def __init__(self, mean, stddev, shape):
  145. super().__init__(shape)
  146. self.mean = mean
  147. self.stddev = stddev
  148. def init_on_gpu(self, stream):
  149. gpu_op.truncated_normal_init(
  150. self.node.tensor_value, self.mean, self.stddev, self.seed, stream)
  151. def init_on_cpu(self, np_rand):
  152. from ._base import DNNL_LIB
  153. if DNNL_LIB['cpu_TruncatedNormalInit']:
  154. cpu_op.truncated_normal_init(
  155. self.node.tensor_value, self.mean, self.stddev, self.seed)
  156. else:
  157. # this function cannot use np_rand
  158. from scipy.stats import truncnorm
  159. self.node.tensor_value[:] = truncnorm(
  160. -2.0, 2.0, loc=self.mean, scale=self.stddev).rvs(self.shape).astype(np.float32)
  161. def init_on_ps(self, comm, nid, param_type, seed, opt):
  162. super().init_on_ps(comm, nid, param_type, 3, self.mean, self.stddev, seed, opt)
  163. # here we provide easy APIs
  164. def zeros(shape, name=None, trainable=True, ctx=None):
  165. if name is None:
  166. name = 'zeros_initializer'
  167. init = ZerosInit(shape)
  168. return Variable(name=name, initializer=init, trainable=trainable, ctx=ctx)
  169. def ones(shape, name=None, trainable=True, ctx=None):
  170. if name is None:
  171. name = 'ones_initializer'
  172. init = OnesInit(shape)
  173. return Variable(name=name, initializer=init, trainable=trainable, ctx=ctx)
  174. def constant(shape, fill_value=0.0, name=None, trainable=True, ctx=None):
  175. if name is None:
  176. name = 'constant_initializer'
  177. init = ConstantInit(fill_value, shape)
  178. return Variable(name=name, initializer=init, trainable=trainable, ctx=ctx)
  179. def truncated_normal(shape, mean=0.0, stddev=1.0, name=None, trainable=True, ctx=None):
  180. if name is None:
  181. name = 'truncated_normal_initializer'
  182. init = TruncatedNormalInit(mean, stddev, shape)
  183. return Variable(name=name, initializer=init, trainable=trainable, ctx=ctx)
  184. def random_normal(shape, mean=0.0, stddev=1.0, name=None, trainable=True, ctx=None):
  185. if name is None:
  186. name = 'random_normal_initializer'
  187. init = NormalInit(mean, stddev, shape)
  188. return Variable(name=name, initializer=init, trainable=trainable, ctx=ctx)
  189. def random_uniform(shape, minval=-1.0, maxval=1.0, name=None, trainable=True, ctx=None):
  190. if name is None:
  191. name = 'random_uniform_initializer'
  192. init = UniformInit(minval, maxval, shape)
  193. return Variable(name=name, initializer=init, trainable=trainable, ctx=ctx)
  194. def xavier_normal(shape, name=None, trainable=True, ctx=None):
  195. if name is None:
  196. name = 'xavier_normal_initializer'
  197. init = XavierNormalInit(shape)
  198. return Variable(name=name, initializer=init, trainable=trainable, ctx=ctx)
  199. def xavier_uniform(shape, name=None, trainable=True, ctx=None):
  200. if name is None:
  201. name = 'xavier_uniform_initializer'
  202. init = XavierUniformInit(shape)
  203. return Variable(name=name, initializer=init, trainable=trainable, ctx=ctx)
  204. def he_normal(shape, name=None, trainable=True, ctx=None):
  205. if name is None:
  206. name = 'he_normal_initializer'
  207. init = HeNormalInit(shape)
  208. return Variable(name=name, initializer=init, trainable=trainable, ctx=ctx)
  209. def he_uniform(shape, name=None, trainable=True, ctx=None):
  210. if name is None:
  211. name = 'he_uniform_initializer'
  212. init = HeUniformInit(shape)
  213. return Variable(name=name, initializer=init, trainable=trainable, ctx=ctx)
  214. def lecun_normal(shape, name=None, trainable=True, ctx=None):
  215. if name is None:
  216. name = 'lecun_normal_initializer'
  217. init = LecunNormalInit(shape)
  218. return Variable(name=name, initializer=init, trainable=trainable, ctx=ctx)
  219. def lecun_uniform(shape, name=None, trainable=True, ctx=None):
  220. if name is None:
  221. name = 'lecun_uniform_initializer'
  222. init = LecunUniformInit(shape)
  223. return Variable(name=name, initializer=init, trainable=trainable, ctx=ctx)