Extract all nxm blocks

If I have a 5x5 tensor, then, how do I get all 9 3x3 blocks from it, so that resulting tensor is of shape [9, 3, 3] or if these 3x3 blocks are flattened then [9, 9] shape. for example,

x = torch.randn(5, 5)

suppose x is

tensor([[ 0.5756,  0.2463,  1.3940,  0.8473, -0.8371],
        [ 0.9690,  1.4913, -0.2129,  0.8331, -0.6322],
        [-0.0348, -1.6920, -0.0157,  0.6159,  0.1038],
        [-1.0790,  1.4303,  0.3861,  0.1293,  0.4582],
        [ 0.2815, -1.1944, -0.7612,  0.6595,  1.4611]])

then resulting tensor should be like,

tensor([[0.5756,  0.2463,  1.3940, 0.9690,  1.4913, -0.2129, -0.0348, -1.6920, -0.0157],
 [0.2463, 1.3940,  0.8473, 1.4913, -0.2129,  0.8331, -1.6920, -0.0157,  0.6159],
...
[-0.0157,  0.6159,  0.1038, 0.3861,  0.1293,  0.4582, -0.7612,  0.6595,  1.4611]])

without using for loop

is unfold a way to do this, but I get a bit different result when I use unfold

for example if I want all (2x3) blocks

import torch.nn as nn
x = torch.randn(1, 1, 5, 5)
x
tensor([[[[-0.0197,  1.0647, -0.2223,  0.6515,  0.4126],
          [ 0.2328,  0.3959, -0.2910, -0.3321, -0.7934],
          [-0.5428, -0.8354, -0.4103, -0.8781,  0.6794],
          [ 0.0659, -1.7829,  0.0720, -0.3183,  2.2014],
          [-0.8724, -0.1767, -1.3356,  1.0183, -0.0641]]]])
a = nn.Unfold((2, 3))
a(x)

it give me something like this,

tensor([[[-0.0197,  1.0647, -0.2223,  0.2328,  0.3959, -0.2910, -0.5428,
          -0.8354, -0.4103,  0.0659, -1.7829,  0.0720],
         [ 1.0647, -0.2223,  0.6515,  0.3959, -0.2910, -0.3321, -0.8354,
          -0.4103, -0.8781, -1.7829,  0.0720, -0.3183],
         [-0.2223,  0.6515,  0.4126, -0.2910, -0.3321, -0.7934, -0.4103,
          -0.8781,  0.6794,  0.0720, -0.3183,  2.2014],
         [ 0.2328,  0.3959, -0.2910, -0.5428, -0.8354, -0.4103,  0.0659,
          -1.7829,  0.0720, -0.8724, -0.1767, -1.3356],
         [ 0.3959, -0.2910, -0.3321, -0.8354, -0.4103, -0.8781, -1.7829,
           0.0720, -0.3183, -0.1767, -1.3356,  1.0183],
         [-0.2910, -0.3321, -0.7934, -0.4103, -0.8781,  0.6794,  0.0720,
          -0.3183,  2.2014, -1.3356,  1.0183, -0.0641]]])

but this is not what I want,
how should I change this, to get 2x3 size blocks from input?

one way that I found, is to reshape this tensor,

a(x).reshape(1, 12, 6)

which gives

tensor([[[-0.0197,  1.0647, -0.2223,  0.2328,  0.3959, -0.2910],
         [-0.5428, -0.8354, -0.4103,  0.0659, -1.7829,  0.0720],
         [ 1.0647, -0.2223,  0.6515,  0.3959, -0.2910, -0.3321],
         [-0.8354, -0.4103, -0.8781, -1.7829,  0.0720, -0.3183],
         [-0.2223,  0.6515,  0.4126, -0.2910, -0.3321, -0.7934],
         [-0.4103, -0.8781,  0.6794,  0.0720, -0.3183,  2.2014],
         [ 0.2328,  0.3959, -0.2910, -0.5428, -0.8354, -0.4103],
         [ 0.0659, -1.7829,  0.0720, -0.8724, -0.1767, -1.3356],
         [ 0.3959, -0.2910, -0.3321, -0.8354, -0.4103, -0.8781],
         [-1.7829,  0.0720, -0.3183, -0.1767, -1.3356,  1.0183],
         [-0.2910, -0.3321, -0.7934, -0.4103, -0.8781,  0.6794],
         [ 0.0720, -0.3183,  2.2014, -1.3356,  1.0183, -0.0641]]])

I think so this works, but when I add channel to input, then this fails.

edit:
I found one way,

x.unfold(2, 2, 1).unfold(3, 3, 1)

2 sized slices for each row, and 3 sized slices for each column
if I wanted (4, 4) slices
then,

x.unfold(2, 4, 1).unfold(3, 4, 1)