def forward(self, x): flow = self.block(x) x = self.conv1(x) x = P.im2col(x, 5, 1, 0) flow = P.im2col(flow, 5, 1, 0) x = x * flow x = P.col2im(x, 5, 1, 0) return x
def test_im2col_batch(self): src = Variable(torch.randn(4, 8, 7, 7).cuda()) k = 1 pad = 0 s = (1, 1) dst = P.im2col(src, k, s, pad) back = P.col2im(dst, k, s, pad) self.assertEqual((src - back).data.abs().max(), 0)
def im2patch(x, patchsize, stride, padding=None, returnpadding=False): padtop, padbottom, padleft, padright = calc_padding(x, patchsize, stride, padding) xpad = F.pad(x, pad=(padleft, padright, padtop, padbottom)) x2col = pyinn.im2col(xpad, [patchsize]*2, [stride]*2, [0,0]) if returnpadding: return x2col, (padtop, padbottom, padleft, padright) else: return x2col
def im2col_X(model, X, conv_index): # GPU implementation of im2col import pyinn as P this_X = P.im2col(X, model.features[conv_index].kernel_size[0], model.features[conv_index].stride[0], model.features[conv_index].padding[0]).detach() this_X_data = this_X.data this_X_data = this_X_data.permute(0, 4, 5, 1, 2, 3) this_X_data_flatten = this_X_data.contiguous().view( this_X_data.size(0) * this_X_data.size(1) * this_X_data.size(2), -1) del this_X, this_X_data return this_X_data_flatten
def nd2col(input_nd, kernel_size, stride=1, padding=0, output_padding=0, dilation=1, transposed=False, use_pyinn_if_possible=False): """ Shape: - Input: :math:`(N, C, L_{in})` - Output: :math:`(N, C, *kernel_size, *L_{out})` where :math:`L_{out} = floor((L_{in} + 2 * padding - dilation * (kernel_size - 1) - 1) / stride + 1)` for non-transposed :math:`L_{out} = (L_{in} - 1) * stride - 2 * padding + dilation * (kernel_size - 1) + 1 + output_padding` for transposed """ n_dims = len(input_nd.shape[2:]) kernel_size = (kernel_size, ) * n_dims if isinstance( kernel_size, Number) else kernel_size stride = (stride, ) * n_dims if isinstance(stride, Number) else stride padding = (padding, ) * n_dims if isinstance(padding, Number) else padding output_padding = (output_padding, ) * n_dims if isinstance( output_padding, Number) else output_padding dilation = (dilation, ) * n_dims if isinstance(dilation, Number) else dilation if transposed: assert n_dims == 2, 'Only 2D is supported for fractional strides.' w_one = input_nd.new_ones(1, 1, 1, 1) pad = [(k - 1) * d - p for (k, d, p) in zip(kernel_size, dilation, padding)] input_nd = F.conv_transpose2d(input_nd, w_one, stride=stride) input_nd = F.pad(input_nd, (pad[1], pad[1] + output_padding[1], pad[0], pad[0] + output_padding[0])) stride = _pair(1) padding = _pair(0) (bs, nch), in_sz = input_nd.shape[:2], input_nd.shape[2:] out_sz = tuple([ ((i + 2 * p - d * (k - 1) - 1) // s + 1) for (i, k, d, p, s) in zip(in_sz, kernel_size, dilation, padding, stride) ]) # Use PyINN if possible (about 15% faster) TODO confirm the speed-up if n_dims == 2 and dilation == 1 and has_pyinn and torch.cuda.is_available( ) and use_pyinn_if_possible: output = P.im2col(input_nd, kernel_size, stride, padding) else: output = F.unfold(input_nd, kernel_size, dilation, padding, stride) out_shape = (bs, nch) + tuple(kernel_size) + out_sz output = output.view(*out_shape).contiguous() return output
def main(): window = np.array([150, 150]) overlap = np.array([75, 75]) lena = scipy.misc.face(True) print lena.shape # lena = torch.from_numpy(lena.transpose(2, 0, 1)) lena = torch.from_numpy(lena).unsqueeze(0) lena = Variable(lena.float()).cuda() ################################################## # Unfold and convolution #------------------------------------------------- # lena = lena.unfold(0, window[0], window[0] - overlap[0]).unfold(1, window[1], window[0] - overlap[1]) # s = lena.size() # lena = lena.contiguous().view(s[0]*s[1], 1, window[0],window[1]) # mask = make_identifier_mask(s[0], s[1]) # mask = torch.from_numpy(mask.transpose(2, 0, 1)).unsqueeze(1) # print mask.size() # print lena.size() # plt.ion() # for i in xrange(s[0]*s[1]): # t = F.conv_transpose2d(Variable(mask[i].unsqueeze(0)).float(), Variable(lena[i].unsqueeze(0)).float()) # plt.imshow(t.data.squeeze().numpy()) # plt.draw() # plt.pause(0.3) ################################################## # pyinn #------------------------------------------------- lena = P.im2col(lena, window, window - overlap, [0, 0]) # (768 x 1024) -> (1 x 150 x 150 x 7 x 9) s = lena.data.size() plot = torchvision.utils.make_grid(lena.squeeze().transpose( 0, 2).transpose(1, 3).contiguous().view(s[-1] * s[-2], 1, 150, 150).data, nrow=5, padding=10, normalize=True) plt.imshow(plot.cpu().numpy().transpose(1, 2, 0)) plt.show() lena = P.col2im(lena, window, window - overlap, [0, 0]) # (1 x 750 x 950) plt.imshow(lena.cpu().data.squeeze().numpy()) plt.show() pass
def _compute_gaussian(self, input, gaussian, norm=None): if norm is not None: input = input * norm shape = input.shape num_channels = shape[1] bs = shape[0] if self.blur > 1: off_0 = (self.blur - self.npixels[0] % self.blur) % self.blur off_1 = (self.blur - self.npixels[1] % self.blur) % self.blur pad_0 = int(math.ceil(off_0 / 2)) pad_1 = int(math.ceil(off_1 / 2)) input = torch.nn.functional.avg_pool2d(input, kernel_size=self.blur, padding=(pad_0, pad_1), count_include_pad=False) npixels = [ math.ceil(self.npixels[0] / self.blur), math.ceil(self.npixels[1] / self.blur) ] assert (npixels[0] == input.shape[2]) assert (npixels[1] == input.shape[3]) else: npixels = self.npixels if self.verbose: show_memusage(name="Init") if self.pyinn: input_col = P.im2col(input, self.filter_size, 1, self.span) else: # An alternative implementation of num2col. # # This has implementation uses the torch 0.4 im2col operation. # This implementation was not avaible when we did the experiments # published in our paper. So less "testing" has been done. # # It is around ~20% slower then the pyinn implementation but # easier to use as it removes a dependency. input_unfold = F.unfold(input, self.filter_size, 1, self.span) input_unfold = input_unfold.view(bs, num_channels, self.filter_size, self.filter_size, npixels[0], npixels[1]) input_col = input_unfold k_sqr = self.filter_size * self.filter_size if self.verbose: show_memusage(name="Im2Col") product = gaussian * input_col if self.verbose: show_memusage(name="Product") product = product.view( [bs, num_channels, k_sqr, npixels[0], npixels[1]]) message = product.sum(2) if self.verbose: show_memusage(name="FinalNorm") if self.blur > 1: in_0 = self.npixels[0] in_1 = self.npixels[1] message = message.view(bs, num_channels, npixels[0], npixels[1]) with warnings.catch_warnings(): warnings.simplefilter("ignore") # Suppress warning regarding corner alignment message = torch.nn.functional.upsample(message, scale_factor=self.blur, mode='bilinear') message = message[:, :, pad_0:pad_0 + in_0, pad_1:in_1 + pad_1] message = message.contiguous() message = message.view(shape) assert (message.shape == shape) if norm is not None: message = norm * message return message
def _compute_gaussian(self, input, gaussian, norm=None): if norm is not None: input = input * norm shape = input.shape num_channels = shape[1] bs = shape[0] if self.blur > 1: off_0 = (self.blur - self.npixels[0] % self.blur) % self.blur off_1 = (self.blur - self.npixels[1] % self.blur) % self.blur pad_0 = int(math.ceil(off_0 / 2)) pad_1 = int(math.ceil(off_1 / 2)) input = torch.nn.functional.avg_pool2d(input, kernel_size=self.blur, padding=(pad_0, pad_1), count_include_pad=False) npixels = [math.ceil(self.npixels[0] / self.blur), math.ceil(self.npixels[1] / self.blur)] assert(npixels[0] == input.shape[2]) assert(npixels[1] == input.shape[3]) else: npixels = self.npixels if self.verbose: show_memusage(name="Init") if self.pyinn: input_col = P.im2col(input, self.filter_size, 1, self.span) else: # An alternative implementation of num2col. # # This has implementation uses the torch 0.4 im2col operation. # This implementation was not avaible when we did the experiments # published in our paper. So less "testing" has been done. # # It is around ~20% slower then the pyinn implementation but # easier to use as it removes a dependency. input_unfold = F.unfold(input, self.filter_size, 1, self.span) input_unfold = input_unfold.view( bs, num_channels, self.filter_size, self.filter_size, npixels[0], npixels[1]) input_col = input_unfold k_sqr = self.filter_size * self.filter_size if self.verbose: show_memusage(name="Im2Col") product = gaussian * input_col if self.verbose: show_memusage(name="Product") product = product.view([bs, num_channels, k_sqr, npixels[0], npixels[1]]) message = product.sum(2) if self.verbose: show_memusage(name="FinalNorm") if self.blur > 1: in_0 = self.npixels[0] in_1 = self.npixels[1] message = message.view(bs, num_channels, npixels[0], npixels[1]) with warnings.catch_warnings(): warnings.simplefilter("ignore") # Suppress warning regarding corner alignment message = torch.nn.functional.upsample(message, scale_factor=self.blur, mode='bilinear') message = message[:, :, pad_0:pad_0 + in_0, pad_1:in_1 + pad_1] message = message.contiguous() message = message.view(shape) assert(message.shape == shape) if norm is not None: message = norm * message return message