【pytorch】torch.nn.Unfold操作

📅 2026/7/19 10:27:50 👁️ 阅读次数 📝 编程学习
【pytorch】torch.nn.Unfold操作

说明

一个代码里涉及到了unfold的操作,看了半天官网都没整明白维度怎么变化的,参考这个链接搞明白了:
https://blog.csdn.net/ViatorSun/article/details/119940759
https://zhuanlan.zhihu.com/p/361140988

维度计算

输入( N, C, H, W)
输出(N,C×∏(kernel_size),L)
L 是通过卷积核滑动裁剪后,得到的区块的数量。

C×∏(kernel_size)是怎么来的?

从第一个参考链接的图可以看到,就是窗口滑动的时候,把窗口同一个位置的值放在了一个通道,所以窗口有多少个像素,就变成了多少个通道。
用参考博客的代码做一个示例:

inputs=torch.randn(1,2,4,4)print(inputs.size())print(inputs)unfold=torch.nn.Unfold(kernel_size=(2,2),stride=2)patches=unfold(inputs)print(patches.size())print(patches)

输出结果

torch.Size([1,2,4,4])tensor([[[[0.4448,-1.8525,-1.8243,-1.0243],[0.0224,-1.2402,-0.7154,-1.2538],[-0.6515,-0.6022,0.2263,-1.6286],[0.2067,0.8257,-1.9318,1.0372]],[[2.4799,-0.5248,-0.3170,1.5934],[-0.3643,1.1624,-1.5762,-0.1827],[-0.0553,0.1629,-1.3280,-0.8468],[0.0671,1.6328,1.1706,1.7891]]]])torch.Size([1,8,4])tensor([[[0.4448,-1.8243,-0.6515,0.2263],[-1.8525,-1.0243,-0.6022,-1.6286],[0.0224,-0.7154,0.2067,-1.9318],[-1.2402,-1.2538,0.8257,1.0372],[2.4799,-0.3170,-0.0553,-1.3280],[-0.5248,1.5934,0.1629,-0.8468],[-0.3643,-1.5762,0.0671,1.1706],[1.1624,-0.1827,1.6328,1.7891]]])

用两个窗口的情况来举例,每个位置对应的结果情况如下:

更容易看的例子:

importtorch# 输入: 1张图, 2通道, 4x4x=torch.tensor([[# 通道0[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]],[# 通道1[17,18,19,20],[21,22,23,24],[25,26,27,28],[29,30,31,32]]]).unsqueeze(0)# 添加batch维度 -> [1, 2, 4, 4]print(f"输入形状:{x.shape}")# 输出: 输入形状: torch.Size([1, 2, 4, 4])x=x.float()# 转为 float32unfolder=torch.nn.Unfold(kernel_size=(3,3),stride=1,padding=1,dilation=1)output=unfolder(x)print(f"有padding输出形状:{output.shape}")# 输出: torch.Size([1, 18, 16])# 解释: [B=1, C*K*K=18, 输出位置数= 4*4=16]print(output)
原始图像 (4x4): ┌──┬──┬──┬──┐ │ 1│ 2│ 3│ 4│ ├──┼──┼──┼──┤ │ 5│ 6│ 7│ 8│ ├──┼──┼──┼──┤ │ 9│10│11│12│ ├──┼──┼──┼──┤ │13│14│15│16│ └──┴──┴──┴──┘ padding=1 后 (6x6,边缘补0): ┌──┬──┬──┬──┬──┬──┐ │ 0│ 0│ 0│ 0│ 0│ 0│ ├──┼──┼──┼──┼──┼──┤ │ 0│ 1│ 2│ 3│ 4│ 0│ ← 原图像被包围 ├──┼──┼──┼──┼──┼──┤ │ 0│ 5│ 6│ 7│ 8│ 0│ ├──┼──┼──┼──┼──┼──┤ │ 0│ 9│10│11│12│ 0│ ├──┼──┼──┼──┼──┼──┤ │ 0│13│14│15│16│ 0│ ├──┼──┼──┼──┼──┼──┤ │ 0│ 0│ 0│ 0│ 0│ 0│ └──┴──┴──┴──┴──┴──┘

有padding输出形状: torch.Size([1, 18, 16])
tensor([[[ 0., 0., 0., 0., 0., 1., 2., 3., 0., 5., 6., 7., 0., 9.,
10., 11.],
[ 0., 0., 0., 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.,
11., 12.],
[ 0., 0., 0., 0., 2., 3., 4., 0., 6., 7., 8., 0., 10., 11.,
12., 0.],
[ 0., 1., 2., 3., 0., 5., 6., 7., 0., 9., 10., 11., 0., 13.,
14., 15.],
[ 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14.,
15., 16.],
[ 2., 3., 4., 0., 6., 7., 8., 0., 10., 11., 12., 0., 14., 15.,
16., 0.],
[ 0., 5., 6., 7., 0., 9., 10., 11., 0., 13., 14., 15., 0., 0.,
0., 0.],
[ 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16., 0., 0.,
0., 0.],
[ 6., 7., 8., 0., 10., 11., 12., 0., 14., 15., 16., 0., 0., 0.,
0., 0.],前9个通道的第一个元素就是第一个窗口(0,0,0,0,1,2,0,5,6)
[ 0., 0., 0., 0., 0., 17., 18., 19., 0., 21., 22., 23., 0., 25.,
26., 27.],
[ 0., 0., 0., 0., 17., 18., 19., 20., 21., 22., 23., 24., 25., 26.,
27., 28.],
[ 0., 0., 0., 0., 18., 19., 20., 0., 22., 23., 24., 0., 26., 27.,
28., 0.],
[ 0., 17., 18., 19., 0., 21., 22., 23., 0., 25., 26., 27., 0., 29.,
30., 31.],
[17., 18., 19., 20., 21., 22., 23., 24., 25., 26., 27., 28., 29., 30.,
31., 32.],
[18., 19., 20., 0., 22., 23., 24., 0., 26., 27., 28., 0., 30., 31.,
32., 0.],
[ 0., 21., 22., 23., 0., 25., 26., 27., 0., 29., 30., 31., 0., 0.,
0., 0.],
[21., 22., 23., 24., 25., 26., 27., 28., 29., 30., 31., 32., 0., 0.,
0., 0.],
[22., 23., 24., 0., 26., 27., 28., 0., 30., 31., 32., 0., 0., 0.,
0., 0.]]])