def _forward_grouped_convolution_xp(self, x, W, b, xp): # G: group count # N: batch size # xC: input channels # yC: output channels G = self.groups N, xC = x.shape[:2] x_size = x.shape[2:] yCg = W.shape[1] yC = yCg * G xCg = xC // G k_size = W.shape[2:] dims = len(k_size) if xC % G != 0: raise TypeError('The number of groups must be ' 'a divisor of that of input channels') x = xp.rollaxis(x, 1) # (xC, N, x_size...) x = x.reshape(G, xCg, N * convolution_nd._prod(x_size)) W = W.reshape(G, xCg, yCg * convolution_nd._prod(k_size)) W = W.transpose(0, 2, 1) # (G, yCg*k_size, xCg) # (G, yCg*k_size, N*x_size) = (G, yCg*k_size, xCg) @ (G, xCg, N*x_size) col = convolution_2d._matmul(W, x).astype(x.dtype, copy=False) col = col.reshape((yC,) + k_size + (N,) + x_size) col = xp.rollaxis(col, dims + 1) # (N, yC, k_size..., x_size...) y = conv_nd.col2im_nd(col, self.stride, self.pad, self.outs, dilate=self.dilate) if b is not None: y += b.reshape(1, yC, *((1,) * dims)) return y,
def check_col2im_nd(self, ksize, stride, pad, gpu): dims = self.dims outs = tuple(conv_nd.get_conv_outsize(d, k, s, p) for (d, k, s, p) in zip(dims, ksize, stride, pad)) col_shape = (2, 3) + ksize + outs col = numpy.random.uniform(-1, 1, col_shape).astype(numpy.float32) if gpu: col_data = cuda.to_gpu(col) else: col_data = col img = conv_nd.col2im_nd(col_data, stride, pad, dims) img = cuda.to_cpu(img) img_shape = (2, 3) + dims self.assertEqual(img.shape, img_shape) for n in moves.range(2): for c in moves.range(3): for xs in itertools.product( *[moves.range(d) for d in dims]): v = numpy.float32(0.0) for dxs in itertools.product( *[moves.range(k) for k in ksize]): oxs = tuple((x + p - dx) // s for (x, p, dx, s) in zip(xs, pad, dxs, stride)) if all((x + p - dx) % s == 0 for (x, p, dx, s) in zip(xs, pad, dxs, stride)) and \ all(0 <= ox < out for (ox, out) in zip(oxs, outs)): col_index = (n, c) + dxs + oxs v += col[col_index] img_index = (n, c) + xs self.assertAlmostEqual(img[img_index], v)
def _forward_grouped_convolution_xp(self, x, W, b, xp): # G: group count # N: batch size # xC: input channels # yC: output channels G = self.groups N, xC = x.shape[:2] x_size = x.shape[2:] yCg = W.shape[1] yC = yCg * G xCg = xC // G k_size = W.shape[2:] dims = len(k_size) if xC % G != 0: raise TypeError('The number of groups must be ' 'a divisor of that of input channels') x = xp.rollaxis(x, 1) # (xC, N, x_size...) x = x.reshape(G, xCg, N * utils.size_of_shape(x_size)) W = W.reshape(G, xCg, yCg * utils.size_of_shape(k_size)) W = W.transpose(0, 2, 1) # (G, yCg*k_size, xCg) # (G, yCg*k_size, N*x_size) = (G, yCg*k_size, xCg) @ (G, xCg, N*x_size) col = convolution_2d._matmul(W, x).astype(x.dtype, copy=False) col = col.reshape((yC, ) + k_size + (N, ) + x_size) col = xp.rollaxis(col, dims + 1) # (N, yC, k_size..., x_size...) y = conv_nd.col2im_nd(col, self.stride, self.pad, self.outs, dilate=self.dilate) if b is not None: y += b.reshape(1, yC, *((1, ) * dims)) return y,