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.

Pad.py 4.4 kB

5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. from __future__ import absolute_import
  2. from .Node import Op
  3. from .._base import DNNL_LIB
  4. from ..cpu_links import pad as cpu_pad
  5. from ..cpu_links import pad_gradient as cpu_pad_gradient
  6. from ..gpu_links import pad
  7. from ..gpu_links import pad_gradient
  8. class PadOp(Op):
  9. def __init__(self, node_A, paddings, mode="CONSTANT", constant_values=0, ctx=None):
  10. """Creates a node that represents np.sum(node_A, axis=0).
  11. Only support common-case axis=0 reduction for simplicity of gradient.
  12. """
  13. super().__init__(PadOp, [node_A], ctx)
  14. self.paddings = paddings
  15. self.mode = mode
  16. self.constant_values = constant_values
  17. def compute(self, input_vals, output_val, stream_handle=None):
  18. if self.on_cpu:
  19. if DNNL_LIB['cpu_Pad']:
  20. cpu_pad(input_vals[0], output_val,
  21. self.paddings, self.mode, constant_values=0)
  22. else:
  23. output_val[:] = pad_np(input_vals[0].asnumpy(
  24. ), self.paddings, self.mode, constant_values=0)
  25. else:
  26. pad(input_vals[0], output_val, self.paddings,
  27. self.mode, self.constant_values, stream_handle)
  28. def gradient(self, output_grad):
  29. return [pad_gradient_op(output_grad, self.paddings, self.mode, ctx=self.raw_ctx)]
  30. def infer_shape(self, input_shapes):
  31. assert len(input_shapes) == 1
  32. out_shape = list(input_shapes[0])
  33. pad_len = len(self.paddings)
  34. for i in range(4):
  35. if(i - (4 - pad_len) >= 0):
  36. out_shape[i] = out_shape[i] + self.paddings[i -
  37. (4 - pad_len)][0] + self.paddings[i - (4 - pad_len)][1]
  38. return tuple(out_shape)
  39. class Pad_GradientOp(Op):
  40. def __init__(self, node_A, paddings, mode="CONSTANT", ctx=None):
  41. """Creates a node that represents np.sum(node_A, axis=0).
  42. Only support common-case axis=0 reduction for simplicity of gradient.
  43. """
  44. super().__init__(Pad_GradientOp, [node_A], ctx)
  45. self.paddings = paddings
  46. self.mode = mode
  47. def compute(self, input_vals, output_val, stream_handle=None):
  48. if self.on_cpu:
  49. if DNNL_LIB['cpu_Pad_Gradient']:
  50. cpu_pad_gradient(
  51. input_vals[0], output_val, self.paddings, self.mode)
  52. else:
  53. output_val[:] = pad_np_gradient(
  54. input_vals[0].asnumpy(), self.paddings)
  55. else:
  56. pad_gradient(input_vals[0], output_val,
  57. self.paddings, self.mode, stream_handle)
  58. def gradient(self, output_grad):
  59. raise NotImplementedError
  60. def infer_shape(self, input_shapes):
  61. assert len(input_shapes) == 1
  62. out_shape = list(input_shapes[0])
  63. pad_len = len(self.paddings)
  64. for i in range(4):
  65. if(i - (4 - pad_len) >= 0):
  66. out_shape[i] = out_shape[i] - self.paddings[i -
  67. (4 - pad_len)][0] - self.paddings[i - (4 - pad_len)][1]
  68. return tuple(out_shape)
  69. def pad_op(node_A, paddings, mode="CONSTANT", constant_values=0, ctx=None):
  70. """Pad an input variable.
  71. Parameters:
  72. ----
  73. node_A : Node
  74. The Node to be padded.
  75. paddings : Node
  76. padding edge
  77. mode :
  78. CONSTANT/REFLECT/SYMMETRIC
  79. constant_values: scalar value
  80. padding values
  81. Returns:
  82. ----
  83. A new Node instance created by Op.
  84. """
  85. return PadOp(node_A, paddings, mode, constant_values, ctx=ctx)
  86. def pad_gradient_op(node_A, paddings, mode="CONSTANT", ctx=None):
  87. """Gradient node of pad operation.
  88. Parameters:
  89. ----
  90. node_A : Node
  91. The Node to be padded.
  92. paddings : Node
  93. padding edge
  94. mode :
  95. CONSTANT/REFLECT/SYMMETRIC
  96. Returns:
  97. ----
  98. A new Node instance created by Op.
  99. """
  100. return Pad_GradientOp(node_A, paddings, mode, ctx=ctx)
  101. def pad_np(node_A, paddings, mode="constant", constant_values=0):
  102. import numpy as np
  103. return np.pad(node_A, paddings, mode=mode.lower(), constant_values=(constant_values, constant_values))
  104. def pad_np_gradient(grad, paddings):
  105. slices = []
  106. for c in paddings:
  107. e = None if c[1] == 0 else -c[1]
  108. slices.append(slice(c[0], e))
  109. return grad[tuple(slices)]