|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- from __future__ import absolute_import
- import numpy as np
- from .Node import Op
- from .._base import DNNL_LIB
- from ..cpu_links import avg_pool as cpu_avg_pool
- from ..gpu_links import CuDNN_average_pooling2d
- from ..cpu_links import avg_pool_gradient as cpu_avg_pool_gradient
- from ..gpu_links import CuDNN_average_pooling2d_gradient
-
-
- class Avg_Pool2dOp(Op):
- def __init__(self, node_A, kernel_H, kernel_W, padding, stride, ctx=None):
- super().__init__(Avg_Pool2dOp, [node_A], ctx)
- self.padding = padding
- self.stride = stride
- self.kernel_H = kernel_H
- self.kernel_W = kernel_W
-
- def np_average_pooling(self, input, kernel_H, kernel_W, padding=0, stride=1):
- N, C, H, W = input.shape
- assert((H + 2 * padding - kernel_H) % stride == 0)
- assert((W + 2 * padding - kernel_W) % stride == 0)
- pooled_H = (H + 2 * padding - kernel_H) // stride + 1
- pooled_W = (W + 2 * padding - kernel_W) // stride + 1
- pooled_layer = np.zeros(
- shape=(N, C, pooled_H, pooled_W), dtype=np.float32)
- pooling_size = kernel_H * kernel_W
- for n in range(N):
- for c in range(C):
- for h in range(pooled_H):
- for w in range(pooled_W):
- hs = h * stride - padding
- ws = w * stride - padding
- hend = min(hs + kernel_H, H)
- wend = min(ws + kernel_W, W)
- hs = max(hs, 0)
- ws = max(ws, 0)
- for i in range(hs, hend):
- for j in range(ws, wend):
- pooled_layer[n][c][h][w] += input[n][c][i][j]
- pooled_layer[n][c][h][w] /= pooling_size
- return pooled_layer
-
- def compute(self, input_vals, output_val, stream_handle=None):
- if self.on_cpu:
- if DNNL_LIB['DnnlAvgPool']:
- cpu_avg_pool(
- input_vals[0], self.kernel_H, self.kernel_W, output_val, self.padding, self.stride)
- else:
- output_val[:] = self.np_average_pooling(
- input_vals[0].asnumpy(), self.kernel_H, self.kernel_W, self.padding, self.stride)
- else:
- CuDNN_average_pooling2d(
- input_vals[0], self.kernel_H, self.kernel_W, output_val, self.padding, self.stride, stream_handle)
-
- def gradient(self, output_grad):
- return [avg_pool2d_gradient_op(self, output_grad, self.inputs[0], self.kernel_H, self.kernel_W, self.padding, self.stride, ctx=self.raw_ctx)]
-
- def infer_shape(self, input_shapes):
- """Need to handle input_vals[0].shape != input_vals[1].shape"""
- assert len(input_shapes) == 1
- N, C, H, W = input_shapes[0]
- p_H = (H + 2 * self.padding - self.kernel_H) // self.stride + 1
- p_W = (W + 2 * self.padding - self.kernel_W) // self.stride + 1
- return (N, C, p_H, p_W)
-
-
- class Avg_Pool2d_GradientOp(Op):
- def __init__(self, node_out, node_out_gradient, node_in, kernel_H, kernel_W, padding, stride, ctx=None):
- super().__init__(Avg_Pool2d_GradientOp, [
- node_out, node_out_gradient, node_in], ctx)
- self.padding = padding
- self.stride = stride
- self.kernel_H = kernel_H
- self.kernel_W = kernel_W
-
- def np_average_pooling_gradient(self, gradient_y, kernel_H, kernel_W, padding=0, stride=1):
- N, C, pooled_H, pooled_W = gradient_y.shape
- H = (pooled_H - 1) * stride + kernel_H - 2 * padding
- W = (pooled_W - 1) * stride + kernel_W - 2 * padding
-
- gradient_x = np.zeros(shape=(N, C, H, W), dtype=np.float32)
- pooling_size = kernel_H * kernel_W
- for n in range(N):
- for c in range(C):
- for h in range(pooled_H):
- for w in range(pooled_W):
- hs = h * stride - padding
- ws = w * stride - padding
- hend = min(hs + kernel_H, H)
- wend = min(ws + kernel_W, W)
- hs = max(hs, 0)
- ws = max(ws, 0)
- for i in range(hs, hend):
- for j in range(ws, wend):
- gradient_x[n][c][i][j] += gradient_y[n][c][h][w] / \
- pooling_size
-
- return gradient_x
-
- def compute(self, input_vals, output_val, stream_handle=None):
- if self.on_cpu:
- if DNNL_LIB['DnnlAvgPool_Gradient']:
- cpu_avg_pool_gradient(
- input_vals[1], self.kernel_H, self.kernel_W, output_val, self.padding, self.stride)
- else:
- output_val[:] = self.np_average_pooling_gradient(
- input_vals[1].asnumpy(), self.kernel_H, self.kernel_W, self.padding, self.stride)
- else:
- CuDNN_average_pooling2d_gradient(
- input_vals[0], input_vals[1], input_vals[2], self.kernel_H, self.kernel_W, output_val, self.padding, self.stride, stream_handle)
-
- def gradient(self, output_grad):
- raise NotImplementedError
-
- def infer_shape(self, input_shapes):
- assert len(input_shapes) == 3
- return input_shapes[2]
-
-
- def avg_pool2d_op(node_A, kernel_H, kernel_W, padding, stride, ctx=None):
- """Average pooling node.
-
- Parameters:
- ----
- node_A : Node
- Input node.
- kernel_H :
- Kernel height.
- kernel_W :
- Kernel width.
- padding :
- Padding size.
- stride :
- Stride size.
-
- Returns:
- ----
- A new Node instance created by Op.
-
- """
- return Avg_Pool2dOp(node_A, kernel_H, kernel_W, padding, stride, ctx=ctx)
-
-
- def avg_pool2d_gradient_op(node_out, node_out_gradient, node_in, kernel_H, kernel_W, padding, stride, ctx=None):
- """Gradient node of average pooling.
-
- Parameters:
- ----
- node_out : Node
- Output node of average pooling.
- node_out_gradient : Node
- Previous gradient node.
- node_in : Node
- Input node of average pooling.
- kernel_H :
- Kernel height.
- kernel_W :
- Kernel width.
- padding :
- Padding size.
- stride :
- Stride size.
-
- Returns:
- ----
- A new Node instance created by Op.
-
- """
- return Avg_Pool2d_GradientOp(node_out, node_out_gradient, node_in, kernel_H, kernel_W, padding, stride, ctx=ctx)
|