This is not a trivial operation, and this solution is not very trivial or intuitive either.
Looking at result with shape=(2, 5), you can think of a and b as two 2x3 patches of result taken with stride=2. Like this illustration:
![enter image description here]()
We can use pytorch's unfold to "recover" the green (a) and blue (b) patches from result ("recover" up to the averaged values):
from torch.nn import functional as nnf
recovered = nnf.unfold(result, kernel_size=(2,3), stride=2)
The result is:
tensor([[[1., 4.],
[2., 6.],
[4., 7.],
[1., 4.],
[2., 6.],
[4., 7.]]])
The patches were recovered (as column vectors).
Now that we understand how to get a and b from result, we can use fold to perform the "inverse" operation and go from b and b to result.
First, we need to flatten concatenate a and b to the shape fold expects (mimicking the output of unfold, two "flatten" patches of 3x2 elements):
uf = torch.cat((a.view(1, 6, 1), b.view(1, 6, 1)), dim=2)
We can now "fold" the patches
raw = nnf.fold(uf, (2,5), kernel_size=(2,3), stride=2)
We are not there yet, when there are overlapping elements fold sums up the overlapping elements, resulting with
tensor([[[[1., 2., 8., 6., 7.],
[1., 2., 8., 6., 7.]]]])
To count how many elements were summed for each entry in result, we can simply "fold" an all ones tensor
counter = nnf.fold(torch.ones_like(uf), (2, 5), kernel_size=(2, 3), stride=2)
And finally, we can recover result:
result = raw / counter
tensor([[[[1., 2., 4., 6., 7.],
[1., 2., 4., 6., 7.]]]])
Piece of cake.