class torch.nn.Unfold(kernel_size: Union[T, Tuple[T, ...]], dilation: Union[T, Tuple[T, ...]] = 1, padding: Union[T, Tuple[T, ...]] = 0, stride: Union[T, Tuple[T, ...]] = 1)
Extracts sliding local blocks from a batched input tensor.
Consider a batched
input tensor of shape , where is the batch dimension, is the channel dimension, and represent arbitrary spatial dimensions. This operation flattens each sliding
kernel_size-sized block within the spatial dimensions of
input into a column (i.e., last dimension) of a 3-D
output tensor of shape , where is the total number of values within each block (a block has spatial locations each containing a -channeled vector), and is the total number of such blocks:
where is formed by the spatial dimensions of
input ( above), and is over all spatial dimensions.
output at the last dimension (column dimension) gives all values within a certain block.
dilation arguments specify how the sliding blocks are retrieved.
stridecontrols the stride for the sliding blocks.
paddingcontrols the amount of implicit zero-paddings on both sides for
paddingnumber of points for each dimension before reshaping.
dilationcontrols the spacing between the kernel points; also known as the à trous algorithm. It is harder to describe, but this link has a nice visualization of what
strideis an int or a tuple of length 1, their values will be replicated across all spatial dimensions.
Fold calculates each combined value in the resulting large tensor by summing all values from all containing blocks.
Unfold extracts the values in the local blocks by copying from the large tensor. So, if the blocks overlap, they are not inverses of each other.
>>> fold_params = dict(kernel_size=..., dilation=..., padding=..., stride=...) >>> fold = nn.Fold(output_size=..., **fold_params) >>> unfold = nn.Unfold(**fold_params)
Then for any (supported)
input tensor the following equality holds:
fold(unfold(input)) == divisor * input
divisor is a tensor that depends only on the shape and dtype of the
>>> input_ones = torch.ones(input.shape, dtype=input.dtype) >>> divisor = fold(unfold(input_ones))
divisor tensor contains no zero elements, then
unfold operations are inverses of each other (up to constant divisor).
Currently, only 4-D input tensors (batched image-like tensors) are supported.
>>> unfold = nn.Unfold(kernel_size=(2, 3)) >>> input = torch.randn(2, 5, 3, 4) >>> output = unfold(input) >>> # each patch contains 30 values (2x3=6 vectors, each of 5 channels) >>> # 4 blocks (2x3 kernels) in total in the 3x4 input >>> output.size() torch.Size([2, 30, 4]) >>> # Convolution is equivalent with Unfold + Matrix Multiplication + Fold (or view to output shape) >>> inp = torch.randn(1, 3, 10, 12) >>> w = torch.randn(2, 3, 4, 5) >>> inp_unf = torch.nn.functional.unfold(inp, (4, 5)) >>> out_unf = inp_unf.transpose(1, 2).matmul(w.view(w.size(0), -1).t()).transpose(1, 2) >>> out = torch.nn.functional.fold(out_unf, (7, 8), (1, 1)) >>> # or equivalently (and avoiding a copy), >>> # out = out_unf.view(1, 2, 7, 8) >>> (torch.nn.functional.conv2d(inp, w) - out).abs().max() tensor(1.9073e-06)
© 2019 Torch Contributors
Licensed under the 3-clause BSD License.