def convolution_2d_backward_x(x, W, gy, sy, sx, ph, pw): xp = cuda.get_array_module(W) _, _, h, w = x.shape gcol = xp.tensordot(W, gy, (0, 1)) gcol = xp.rollaxis(gcol, 3) gx = col2im(gcol, sy, sx, ph, pw, h, w) return gx
def backward_relu(x, y, gy): xp = cuda.get_array_module(x) if cuda.cudnn_enabled and xp == cuda.cupy: gx = cudnn.activation_backward(x, y, gy, _mode) else: gx = (x > 0) * gy return gx
def forward_relu(x): xp = cuda.get_array_module(x) if cuda.cudnn_enabled and xp == cuda.cupy: y = cudnn.activation_forward(x, _mode) else: y = xp.maximum(x, 0) return y
def convolution_2d_forward(x, W, b, sy, sx, ph, pw, cover_all, dy, dx, cls): xp = cuda.get_array_module(x) _, _, kh, kw = W.shape col = im2col(x, kh, kw, sy, sx, ph, pw, cover_all=cover_all, dy=dy, dx=dx) cls.col = col y = xp.tensordot(col, W, ((1, 2, 3), (1, 2, 3))) if b is not None: y += b y = xp.rollaxis(y, 3, 1) return y
def col2im(col, sy, sx, ph, pw, h, w, dy=1, dx=1): xp = cuda.get_array_module(col) n, c, kh, kw, out_h, out_w = col.shape img = xp.zeros((n, c, h + 2 * ph + sy - 1, w + 2 * pw + sx - 1), dtype=col.dtype) for j in range(kh): jdy = j * dy j_lim = jdy + sy * out_h for i in range(kw): idx = i * dx i_lim = idx + sx * out_w img[:, :, jdy:j_lim:sy, idx:i_lim:sx] += col[:, :, j, i] return img[:, :, ph:h + ph, pw:w + pw]
def im2col(img, kh, kw, sy, sx, ph, pw, pval=0, cover_all=False, dy=1, dx=1, out_h=None, out_w=None): xp = cuda.get_array_module(img) n, c, h, w = img.shape if out_h is None: out_h = get_conv_outsize(h, kh, sy, ph, cover_all, dy) if out_w is None: out_w = get_conv_outsize(w, kw, sx, pw, cover_all, dx) img = xp.pad(img, ((0, 0), (0, 0), (ph, ph + sy - 1), (pw, pw + sx - 1)), mode='constant', constant_values=(pval,)) col = xp.ndarray((n, c, kh, kw, out_h, out_w), dtype=img.dtype) for j in range(kh): jdy = j * dy j_lim = jdy + sy * out_h for i in range(kw): idx = i * dx i_lim = idx + sx * out_w col[:, :, j, i, :, :] = img[:, :, jdy:j_lim:sy, idx:i_lim:sx] return col
def get_item_backward(x, slices, gy): xp = cuda.get_array_module(x) gx = xp.zeros_like(x) gx[slices] = gy return gx
def _calc_gx1(x0, x1, gy): xp = cuda.get_array_module(x0) return x0**x1 * xp.log(x0)
def _log(x): xp = cuda.get_array_module(x) return xp.log(x)
def convolution_2d_backward_W(col, gy): xp = cuda.get_array_module(col) gW = xp.tensordot(gy, col, ((0, 2, 3), (0, 4, 5))) return gW
def linear_forward(x, W, b): xp = cuda.get_array_module(x) y = xp.dot(x, W.T) if b is not None: y += b return y
def linear_backward_x(W, gy): xp = cuda.get_array_module(W) gx = xp.dot(gy, W) return gx
def linear_backward_b(gy): xp = cuda.get_array_module(gy) gb = xp.sum(gy, axis=0) return gb
def linear_backward_W(x, gy): xp = cuda.get_array_module(x) gW = xp.dot(gy.T, x) return gW
def sum_forward(x): xp = cuda.get_array_module(x) return xp.sum(x)
def sum_backward(x, gy): xp = cuda.get_array_module(x) return xp.ones_like(x) * gy