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.

LayerNorm.py 13 kB

5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. from __future__ import absolute_import
  2. from .Node import Op
  3. import numpy as np
  4. from .. import ndarray
  5. from ..gpu_links import layer_normalization
  6. from ..gpu_links import layer_normalization_gradient
  7. from ..gpu_links import layer_normalization_inference
  8. class Layer_NormalizationOp(Op):
  9. def __init__(self, node_in, ln_scale, ln_bias, eps=0.01, ctx=None):
  10. super().__init__(Layer_NormalizationOp,
  11. [node_in, ln_scale, ln_bias], ctx)
  12. self.eps = eps
  13. self.save_mean = None
  14. self.save_var = None
  15. self.data_shape = None
  16. def compute(self, input_vals, output_val, stream_handle=None, inference=False):
  17. if inference:
  18. if self.on_cpu:
  19. input_vals = [n.asnumpy() for n in input_vals]
  20. data_type = input_vals[0].dtype
  21. std = np.sqrt(self.save_var + self.eps, dtype=data_type)
  22. centered_input = input_vals[0] - self.save_mean
  23. normed_input = centered_input / std
  24. bc_shape = [1] * len(input_vals[0].shape)
  25. bc_shape[-1] = input_vals[0].shape[-1]
  26. output_val[:] = input_vals[1].reshape(bc_shape) * normed_input + \
  27. input_vals[2].reshape(bc_shape)
  28. else:
  29. layer_normalization_inference(input_vals[0], input_vals[1], input_vals[2],
  30. self.save_mean, self.save_var, output_val, self.eps, stream_handle)
  31. else:
  32. local_shape = list(input_vals[0].shape)
  33. local_shape[-1] = 1
  34. local_shape = tuple(local_shape)
  35. if self.on_cpu:
  36. input_vals = [n.asnumpy() for n in input_vals]
  37. data_type = input_vals[0].dtype
  38. if self.data_shape is None:
  39. self.save_mean = np.empty(local_shape, dtype=np.float32)
  40. self.save_var = np.empty(local_shape, dtype=np.float32)
  41. self.data_shape = local_shape
  42. elif self.data_shape != local_shape:
  43. del self.save_mean
  44. del self.save_var
  45. self.save_mean = np.empty(local_shape, dtype=np.float32)
  46. self.save_var = np.empty(local_shape, dtype=np.float32)
  47. self.data_shape = local_shape
  48. self.save_mean[:] = input_vals[0].mean(
  49. axis=-1, dtype=data_type, keepdims=True)
  50. self.save_var[:] = input_vals[0].var(
  51. axis=-1, dtype=data_type, keepdims=True)
  52. std = np.sqrt(self.save_var + self.eps, dtype=data_type)
  53. centered_input = input_vals[0] - self.save_mean
  54. normed_input = centered_input / std
  55. bc_shape = [1] * len(input_vals[0].shape)
  56. bc_shape[-1] = input_vals[0].shape[-1]
  57. output_val[:] = input_vals[1].reshape(bc_shape) * normed_input + \
  58. input_vals[2].reshape(bc_shape)
  59. else:
  60. if self.data_shape is None:
  61. dev_id = input_vals[0].handle.contents.ctx.device_id
  62. self.save_mean = ndarray.empty(
  63. local_shape, ctx=ndarray.gpu(dev_id))
  64. self.save_var = ndarray.empty(
  65. local_shape, ctx=ndarray.gpu(dev_id))
  66. self.data_shape = local_shape
  67. elif self.data_shape != local_shape:
  68. del self.save_mean
  69. del self.save_var
  70. dev_id = input_vals[0].handle.contents.ctx.device_id
  71. self.save_mean = ndarray.empty(
  72. local_shape, ctx=ndarray.gpu(dev_id))
  73. self.save_var = ndarray.empty(
  74. local_shape, ctx=ndarray.gpu(dev_id))
  75. self.data_shape = local_shape
  76. layer_normalization(input_vals[0], input_vals[1], input_vals[2],
  77. self.save_mean, self.save_var, output_val, self.eps, stream_handle)
  78. def gradient(self, output_grad):
  79. ln_gradient_node = layer_normalization_gradient_op(
  80. output_grad, self.inputs[0], self.inputs[1], self, self.eps, ctx=self.raw_ctx)
  81. data_gradient = layer_normalization_gradient_of_data_op(
  82. ln_gradient_node, self.inputs[0], ctx=self.raw_ctx)
  83. scale_gradient = layer_normalization_gradient_of_scale_op(
  84. ln_gradient_node, self.inputs[1], ctx=self.raw_ctx)
  85. bias_gradient = layer_normalization_gradient_of_bias_op(
  86. ln_gradient_node, self.inputs[2], ctx=self.raw_ctx)
  87. return [data_gradient, scale_gradient, bias_gradient]
  88. def infer_shape(self, input_shapes):
  89. assert len(input_shapes) == 3
  90. assert len(input_shapes[1]) == len(input_shapes[2]) == 1
  91. assert input_shapes[0][-1] == input_shapes[1][0] == input_shapes[2][0]
  92. return input_shapes[0]
  93. class Layer_Normalization_GradientOp(Op):
  94. def __init__(self, out_gradient, in_node, ln_scale, forward_node, eps, ctx=None):
  95. super().__init__(Layer_Normalization_GradientOp,
  96. [out_gradient, in_node, ln_scale], ctx)
  97. self.tmp_gradient_in_arr = None
  98. self.tmp_gradient_ln_bias = None
  99. self.tmp_gradient_ln_scale = None
  100. self.data_shape = None
  101. self.forward_node = forward_node
  102. self.eps = eps
  103. def compute(self, input_vals, output_val, stream_handle=None):
  104. if self.on_cpu:
  105. if self.tmp_gradient_ln_bias is None:
  106. shapeln = input_vals[2].shape
  107. self.data_shape = tuple(input_vals[0].shape)
  108. self.tmp_gradient_ln_scale = np.empty(
  109. shape=shapeln, dtype=np.float32)
  110. self.tmp_gradient_ln_bias = np.empty(
  111. shape=shapeln, dtype=np.float32)
  112. self.tmp_gradient_in_arr = np.empty(
  113. shape=self.data_shape, dtype=np.float32)
  114. elif self.data_shape != tuple(input_vals[0].shape):
  115. self.data_shape = tuple(input_vals[0].shape)
  116. del self.tmp_gradient_in_arr
  117. self.tmp_gradient_in_arr = np.empty(
  118. shape=self.data_shape, dtype=np.float32)
  119. red_axis = tuple(range(input_vals[0].ndim - 1))
  120. self.tmp_gradient_ln_bias[:] = input_vals[0].sum(red_axis) # (X,)
  121. std = np.sqrt(self.forward_node.save_var + self.eps) # (N, 1)
  122. x_centered = input_vals[1] - self.forward_node.save_mean # (N, X)
  123. x_norm = x_centered / std # (N, X)
  124. self.tmp_gradient_ln_scale[:] = (
  125. input_vals[0] * x_norm).sum(red_axis) # (X,)
  126. last_dim = input_vals[1].shape[-1]
  127. dx_norm = input_vals[0] * input_vals[2].reshape(
  128. [1] * (input_vals[0].ndim - 1) + [-1]) # (N, X)
  129. dvar = (dx_norm * x_centered).sum(axis=-1, keepdims=True) * -0.5 / (
  130. self.forward_node.save_var + self.eps) / std # (N, 1)
  131. dx_mu_1 = dx_norm / std # (N, X)
  132. dx_mu_2 = dvar * 2 * x_centered / last_dim # (N, X)
  133. dx_1 = dx_mu_1 + dx_mu_2 # (N, X)
  134. dx_2 = -1 * dx_1.sum(axis=-1, keepdims=True) / last_dim # (N, 1)
  135. self.tmp_gradient_in_arr[:] = dx_1 + dx_2 # (N, X)
  136. else:
  137. if self.tmp_gradient_ln_bias is None:
  138. shapeln = input_vals[2].shape
  139. self.data_shape = tuple(input_vals[0].shape)
  140. self.tmp_gradient_ln_bias = ndarray.empty(
  141. shape=shapeln, ctx=input_vals[0].ctx)
  142. self.tmp_gradient_ln_scale = ndarray.empty(
  143. shape=shapeln, ctx=input_vals[0].ctx)
  144. self.tmp_gradient_in_arr = ndarray.empty(
  145. shape=self.data_shape, ctx=input_vals[0].ctx)
  146. elif self.data_shape != tuple(input_vals[0].shape):
  147. self.data_shape = tuple(input_vals[0].shape)
  148. del self.tmp_gradient_in_arr
  149. self.tmp_gradient_in_arr = ndarray.empty(
  150. shape=self.data_shape, ctx=input_vals[0].ctx)
  151. layer_normalization_gradient(input_vals[0], input_vals[1], input_vals[2],
  152. self.tmp_gradient_in_arr, self.tmp_gradient_ln_scale,
  153. self.tmp_gradient_ln_bias, self.forward_node.save_mean,
  154. self.forward_node.save_var, self.eps, stream_handle)
  155. def gradient(self, output_grad):
  156. raise NotImplementedError
  157. def infer_shape(self, input_shapes):
  158. return (1,)
  159. class Layer_Normalization_Gradient_of_DataOp(Op):
  160. def __init__(self, ln_gradient, in_arr, ctx=None):
  161. super().__init__(Layer_Normalization_Gradient_of_DataOp,
  162. [ln_gradient, in_arr], ctx)
  163. def compute(self, input_vals, output_val, stream_handle=None):
  164. if self.on_cpu:
  165. output_val[:] = self.inputs[0].tmp_gradient_in_arr
  166. else:
  167. self.inputs[0].tmp_gradient_in_arr.copyto(output_val)
  168. def gradient(self, output_grad):
  169. raise NotImplementedError
  170. def infer_shape(self, input_shapes):
  171. return input_shapes[1]
  172. class Layer_Normalization_Gradient_of_ScaleOp(Op):
  173. def __init__(self, ln_gradient, in_scale, ctx=None):
  174. super().__init__(Layer_Normalization_Gradient_of_ScaleOp,
  175. [ln_gradient, in_scale], ctx)
  176. def compute(self, input_vals, output_val, stream_handle=None):
  177. if self.on_cpu:
  178. output_val[:] = self.inputs[0].tmp_gradient_ln_scale
  179. else:
  180. self.inputs[0].tmp_gradient_ln_scale.copyto(output_val)
  181. def gradient(self, output_grad):
  182. raise NotImplementedError
  183. def infer_shape(self, input_shapes):
  184. return input_shapes[1]
  185. class Layer_Normalization_Gradient_of_BiasOp(Op):
  186. def __init__(self, ln_gradient, in_bias, ctx=None):
  187. super().__init__(Layer_Normalization_Gradient_of_BiasOp,
  188. [ln_gradient, in_bias], ctx)
  189. def compute(self, input_vals, output_val, stream_handle=None):
  190. if self.on_cpu:
  191. output_val[:] = self.inputs[0].tmp_gradient_ln_bias
  192. else:
  193. self.inputs[0].tmp_gradient_ln_bias.copyto(output_val)
  194. def gradient(self, output_grad):
  195. raise NotImplementedError
  196. def infer_shape(self, input_shapes):
  197. return input_shapes[1]
  198. def layer_normalization_op(node_in, ln_scale, ln_bias, eps=0.01, ctx=None):
  199. """Layer normalization node.
  200. Parameters:
  201. ----
  202. node_in : Node
  203. Input data.
  204. ln_scale : float
  205. scaling parameter
  206. ln_bias :
  207. learnable bias parameter
  208. eps : float
  209. Epsilon value for numerical stability.
  210. Returns:
  211. ----
  212. A new Node instance created by Op.
  213. """
  214. return Layer_NormalizationOp(node_in, ln_scale, ln_bias, eps, ctx=ctx)
  215. def layer_normalization_gradient_op(out_gradient, in_node, ln_scale, forward_node, eps, ctx=None):
  216. """Gradient node of layer normalization.
  217. Parameters:
  218. ----
  219. out_gradient :
  220. The gradient array.
  221. in_node : Node
  222. Input node of ln layer.
  223. ln_scale :
  224. Scaling parameter.
  225. Returns:
  226. ----
  227. A new Node instance created by Op.
  228. """
  229. return Layer_Normalization_GradientOp(out_gradient, in_node, ln_scale, forward_node, eps, ctx=ctx)
  230. def layer_normalization_gradient_of_data_op(ln_gradient, in_arr, ctx=None):
  231. """Gradient node of data of layer normalization.
  232. Parameters:
  233. ----
  234. ln_gradient :
  235. The gradient array.
  236. in_arr : Node
  237. Input array of ln layer.
  238. Returns:
  239. ----
  240. A new Node instance created by Op.
  241. """
  242. return Layer_Normalization_Gradient_of_DataOp(ln_gradient, in_arr, ctx=ctx)
  243. def layer_normalization_gradient_of_scale_op(ln_gradient, in_scale, ctx=None):
  244. """Gradient node of scale parameter of layer normalization.
  245. Parameters:
  246. ----
  247. ln_gradient :
  248. The gradient array.
  249. in_scale :
  250. Scaling parameter of ln layer.
  251. Returns:
  252. ----
  253. A new Node instance created by Op.
  254. """
  255. return Layer_Normalization_Gradient_of_ScaleOp(ln_gradient, in_scale, ctx=ctx)
  256. def layer_normalization_gradient_of_bias_op(ln_gradient, in_bias, ctx=None):
  257. """Gradient node of bias parameter of layer normalization.
  258. Parameters:
  259. ----
  260. ln_gradient :
  261. The gradient array.
  262. in_bias :
  263. Bias parameter of ln layer.
  264. Returns:
  265. ----
  266. A new Node instance created by Op.
  267. """
  268. return Layer_Normalization_Gradient_of_BiasOp(ln_gradient, in_bias, ctx=ctx)