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.

Concat.py 3.9 kB

5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. from __future__ import absolute_import
  2. from .Node import Op
  3. import numpy as np
  4. from .._base import DNNL_LIB
  5. from ..cpu_links import concat as cpu_concat
  6. from ..cpu_links import concat_gradient as cpu_concat_gradient
  7. from ..gpu_links import concat
  8. from ..gpu_links import concat_gradient
  9. class ConcatOp(Op):
  10. def __init__(self, node_A, node_B, axis=0, ctx=None):
  11. super().__init__(ConcatOp, [node_A, node_B], ctx)
  12. self.axis = axis
  13. def compute(self, input_vals, output_val, stream_handle=None):
  14. if self.on_cpu:
  15. if DNNL_LIB['DnnlConcat']:
  16. cpu_concat(input_vals[0], input_vals[1], output_val, self.axis)
  17. else:
  18. output_val[:] = np.concatenate(
  19. (input_vals[0].asnumpy(), input_vals[1].asnumpy()), self.axis)
  20. else:
  21. concat(input_vals[0], input_vals[1],
  22. output_val, self.axis, stream_handle)
  23. def gradient(self, output_grad):
  24. return [concat_gradient_op(output_grad, self.inputs[0], self.axis, idx=0, ctx=self.raw_ctx),
  25. concat_gradient_op(output_grad, self.inputs[1], self.axis, idx=1, ctx=self.raw_ctx)]
  26. def infer_shape(self, input_shapes):
  27. assert len(input_shapes) == 2
  28. assert len(input_shapes[0]) == len(input_shapes[1])
  29. for i in range(self.axis):
  30. assert input_shapes[0][i] == input_shapes[1][i]
  31. for i in range(self.axis+1, len(input_shapes[0])):
  32. assert input_shapes[0][i] == input_shapes[1][i]
  33. out_shape = list(input_shapes[0])
  34. out_shape[self.axis] = out_shape[self.axis] + \
  35. input_shapes[1][self.axis]
  36. return tuple(out_shape)
  37. class Concat_gradientOP(Op):
  38. def __init__(self, grad_node, input_node, axis, idx, ctx=None):
  39. super().__init__(Concat_gradientOP, [grad_node, input_node], ctx)
  40. self.axis = axis
  41. self.idx = idx
  42. def compute(self, input_vals, output_val, stream_handle=None):
  43. if self.on_cpu:
  44. if 'cpu_Concat_Gradient' in DNNL_LIB:
  45. cpu_concat_gradient(
  46. input_vals[0], output_val, self.axis, self.idx)
  47. else:
  48. output_val[:] = concat_backward(
  49. input_vals[0].asnumpy(), self.idx, self.axis)
  50. else:
  51. concat_gradient(input_vals[0], output_val,
  52. self.axis, self.idx, stream_handle)
  53. def gradient(self, output_grad):
  54. raise NotImplementedError
  55. def infer_shape(self, input_shapes):
  56. assert len(input_shapes) == 2
  57. return input_shapes[1]
  58. def concat_op(node_A, node_B, axis=0, ctx=None):
  59. """Concatenates given variables along an axis.
  60. Parameters:
  61. ----
  62. node_A : Node
  63. The first node to be concated.
  64. node_B : Node
  65. The second node to be concated.
  66. axis :
  67. The axis along which two nodes are concated.
  68. Returns:
  69. ----
  70. A new Node instance created by Op.
  71. """
  72. return ConcatOp(node_A, node_B, axis, ctx=ctx)
  73. def concat_gradient_op(grad_node, input_node, axis, idx, ctx=None):
  74. """Gradient node of concat operation.
  75. Parameters:
  76. ----
  77. grad_node : Node
  78. Previous gradient node.
  79. input_node : Node
  80. axis :
  81. Axis along which to be concatenated.
  82. idx :
  83. The index of concatenation.
  84. Returns:
  85. ----
  86. A new Node instance created by Op.
  87. """
  88. return Concat_gradientOP(grad_node, input_node, axis, idx, ctx=ctx)
  89. def concat_backward(grad, idx, axis=0):
  90. if axis == 0:
  91. gradient_x1 = grad[:idx]
  92. gradient_x2 = grad[idx:]
  93. elif axis == 1:
  94. gradient_x1 = grad[:, :idx]
  95. gradient_x2 = grad[:, idx:]
  96. elif axis == 2:
  97. gradient_x1 = grad[:, :, :idx]
  98. gradient_x2 = grad[:, :, idx:]
  99. else:
  100. gradient_x1 = grad[:, :, :, :idx]
  101. gradient_x2 = grad[:, :, :, idx:]
  102. return [gradient_x1, gradient_x2]