def col2im_indices(cols, x_shape, filter=(2, 2), padding=0, stride=(1, 1)): """ An implementation of col2im based on fancy indexing and np.add.at Args: cols: [B*OH*OW, kH*kW*Cin] x_shape: Shape of initial input (B, H, W, Cin) filter: Shape of filter (kH, kW) Returns: [B, H, W, Cin] """ N, H, W, C = x_shape H_padded, W_padded = H + 2 * padding, W + 2 * padding x_padded = np.zeros((N, C, H_padded, W_padded), dtype=cols.dtype) k, i, j = get_im2col_indices((N, C, H, W), filter[0], filter[1], padding, stride) # cols => [B*OH*OW, kH*kW*Cin] # cols_reshaped => [B, OH*OW, kH*kW*Cin] cols_reshaped = cols.reshape(N, -1, C * filter[0] * filter[1]) # [B, C * kH * kW, OH*OW] cols_reshaped = cols_reshaped.transpose(0, 2, 1) idx = np.array(range(x_padded.shape[0])).reshape((x_padded.shape[0], 1, 1)) np.scatter_add(x_padded.astype(np.float32), (idx.astype(np.uint64), k.astype( np.uint64), i.astype(np.uint64), j.astype(np.uint64)), cols_reshaped.astype(np.float32)) # np.add.at(x_padded, (slice(None), k, i, j), cols_reshaped) if padding == 0: return x_padded.transpose(0, 2, 3, 1) return x_padded[:, :, padding:-padding, padding:-padding].transpose(0, 2, 3, 1)
def test_scatter_add(self): a = cupy.zeros((3, ), dtype=numpy.float32) i = cupy.array([1, 1], numpy.int32) v = cupy.array([2., 1.], dtype=numpy.float32) with testing.assert_warns(DeprecationWarning): cupy.scatter_add(a, i, v) testing.assert_array_equal(a, cupy.array([0, 3, 0]))
def col2im_indices(self, cols): field_height, field_width, padding, stride = self.k, self.k, self.p, self.s N, C, H, W = self.x_shape H_padded, W_padded = H + 2 * padding, W + 2 * padding x_padded = cp.zeros((N, C, H_padded, W_padded), dtype=cols.dtype) k, i, j = self.get_im2col_indices() cols_reshaped = cols.reshape(C * field_height * field_width, -1, N) cols_reshaped = cols_reshaped.transpose(2, 0, 1).astype(cp.float32) cp.scatter_add(x_padded, (slice(None), k, i, j), cols_reshaped) if padding == 0: return x_padded return x_padded[:, :, padding:-padding, padding:-padding]
def column_to_image(cols, images_shape, filter_shape, stride, output_shape='same'): batch_size, channels, height, width = images_shape pad_h, pad_w = determine_padding(filter_shape, output_shape) height_padded = height + pad_h[0] + pad_h[1] width_padded = width + pad_w[0] + pad_w[1] images_padded = cp.zeros( (batch_size, channels, height_padded, width_padded)) k, i, j = get_im2col_indices(images_shape, filter_shape, (pad_h, pad_w), stride) cols = cp.reshape( cols, (channels * filter_shape[0] * filter_shape[1], -1, batch_size)) cols = cp.transpose(cols, (2, 0, 1)) cp.scatter_add(images_padded, (slice(None), k, i, j), cols) return images_padded[:, :, pad_h[0]:height + pad_h[0], pad_w[0]:width + pad_w[0]]
def test_scatter_add(self): a = cupy.zeros((3,), dtype=numpy.float32) i = cupy.array([1, 1], numpy.int32) v = cupy.array([2., 1.], dtype=numpy.float32) cupy.scatter_add(a, i, v) testing.assert_array_equal(a, cupy.array([0, 3, 0]))