def backward(self, indices, grad_outputs): xvar, Wvar = self.get_retained_inputs() x = xvar.data W = Wvar.data gyvar, = grad_outputs gy = gyvar.data xp = backend.get_array_module(x, W) stride_row, stride_col = self.sy, self.sx output_row, output_col = W.shape[1], W.shape[2] ret = [] if 0 in indices: gx = xp.zeros_like(x) for i in moves.range(output_row): for j in moves.range(output_col): slice_row = slice(i * stride_row, i * stride_row + W.shape[4]) slice_col = slice(j * stride_col, j * stride_col + W.shape[5]) # ochans * ichans * krows * kcols W_slice = W[:, i, j, ...] # nsamps * ochans gy_slice = gy[..., i, j] # -> nsamps * ichans * krows * kcols gx[:, :, slice_row, slice_col] += xp.tensordot(gy_slice, W_slice, axes=[(1, ), (0, )]) ret.append( chainer.functions.cast(variable.as_variable(gx), x.dtype)) if 1 in indices: gW = xp.empty_like(W) for i in moves.range(output_row): for j in moves.range(output_col): slice_row = slice(i * stride_row, i * stride_row + W.shape[4]) slice_col = slice(j * stride_col, j * stride_col + W.shape[5]) # nsamps * inchans * krows * kcols x_slice = x[:, :, slice_row, slice_col] # nsamps * outchans * 1 * 1 gy_slice = gy[:, :, i, j] gW[:, i, j, :, :, :] = xp.tensordot(gy_slice, x_slice, axes=[(0, ), (0, )]) ret.append( chainer.functions.cast(variable.as_variable(gW), W.dtype)) if 2 in indices: gb = chainer.functions.sum(gyvar, axis=0) ret.append(gb) return ret
def backward(self, indices, grad_outputs): xvar, Wvar = self.get_retained_inputs() x = xvar.data W = Wvar.data gyvar, = grad_outputs gy = gyvar.data xp = backend.get_array_module(x, W) stride_row, stride_col = self.sy, self.sx output_row, output_col = W.shape[1], W.shape[2] ret = [] if 0 in indices: gx = xp.zeros_like(x) for i in moves.range(output_row): for j in moves.range(output_col): slice_row = slice(i * stride_row, i * stride_row + W.shape[4]) slice_col = slice(j * stride_col, j * stride_col + W.shape[5]) # ochans * ichans * krows * kcols W_slice = W[:, i, j, ...] # nsamps * ochans gy_slice = gy[..., i, j] # -> nsamps * ichans * krows * kcols gx[:, :, slice_row, slice_col] += xp.tensordot( gy_slice, W_slice, axes=[(1,), (0,)] ) ret.append(chainer.functions.cast(variable.as_variable(gx), x.dtype)) if 1 in indices: gW = xp.empty_like(W) for i in moves.range(output_row): for j in moves.range(output_col): slice_row = slice(i * stride_row, i * stride_row + W.shape[4]) slice_col = slice(j * stride_col, j * stride_col + W.shape[5]) # nsamps * inchans * krows * kcols x_slice = x[:, :, slice_row, slice_col] # nsamps * outchans * 1 * 1 gy_slice = gy[:, :, i, j] gW[:, i, j, :, :, :] = xp.tensordot( gy_slice, x_slice, axes=[(0,), (0,)] ) ret.append(chainer.functions.cast(variable.as_variable(gW), W.dtype)) if 2 in indices: gb = chainer.functions.sum(gyvar, axis=0) ret.append(gb) return ret
def backward(self, indexes, grad_outputs): if self.grad is None: grad = (self.xp.ones(self.input_shape, self.input_dtype), ) else: grad = self.grad return tuple(None if g is None else variable.as_variable(g) for g in grad)
def backward(self, inputs, grad_outputs): grad = self.grad return tuple(None if g is None else variable.as_variable(g) for g in grad)
def backward(self, inputs, grad_outputs): grad = self.grad return tuple( None if g is None else variable.as_variable(g) for g in grad)