Bridge Oracle中文网
领取MOLI红包
你的位置:Bridge Oracle中文网 > Jen-Hsun Huang中文网 >
pytorch中的nn.Unfold()函数和fold()函数解读
发布日期:2025-01-03 18:41    点击次数:78
pytorch的nn.Unfold()函数和fold()函数 1.nn.Unfold()函数 描述:pytorch中的nn.Unfold()函数,在图像处理领域,经常需要用到卷积操作,但是有时我们只需要在图片上进行滑动的窗口操作,将图片切割成patch,而不需要进行卷积核和图片值的卷积乘法操作。 这是就需要用到nn.Unfold()函数,该函数是从一个batch图片中,提取出滑动的局部区域块,也就是卷积操作中的提取kernel filter对应的滑动窗口。 该函数的输入是(bs,c,h,w),其中bs为batch-size,C是channel的个数。 而该函数的输出是(bs,Cxkernel_size[0]xkernel_size[1],L)其中L是特征图或者图片的尺寸根据kernel_size的长宽滑动裁剪后得到的多个patch的数量。 该方法的主要应用场景是将图片切割成不同的patch,配合一下代码实现 结果: 2.nn.Fold()函数 该函数是nn.Unfold()函数的逆操作。 nn.functional.fold/unfold 官方文档:fold, unfold 作用:fold和unfold的作用恰好相反,unfold是用一个滑窗来提取图像中的像素值,类似于卷积操作,但是只提取不计算,fold恰好相反将滑窗提取的值返回为一个图像 input: 输入tensorkernel_size: 提取时的滑窗大小dilation: 滑窗是否有空洞padding: 是否对原图进行填充stride: 滑窗移动的步长 下面举一个例子直观解释 执行过程很简单,用一个 2 × 2 的窗在图上滑动,步长为2,第一次覆盖的内容为1256,第二次为3478,以此类推,每次滑窗的结果用一个列向量表示,列数就是滑窗提取的次数。 如果我们要得到每次滑窗的结果,例如第一次提取的结果,用表达式x[:,:,0]即可 input: 输入tensoroutput_size: 输出图像的大小(必须指定)kernel_size: 在图像中填充的形状dilation: 滑窗是否有空洞padding: 是否对原图进行填充stride: 存放窗的tensor时移动的步长 网上很少有讲这个函数的,都说是unfold的逆过程,我们依然用几个例子来对其进行详细的解释 1. 第一个例子 fold函数是如何执行的呢,他会提取unfold函数的每一列,首先提取1256这一列,然后根据kernel_size的大小将1256重新resize并填到output的第一个位置,如下 随后提取第二列2.6.10.14,resize为 2 × 2 2\times 2 2×2的形状,根据步长为2添加到output的下一个位置,并以此类推 注意:output,kernel以及stride必须满足一定的关系(参考文档) 知道原理以后我们可以自由操作上述tensor,但是注意,如果步长等设置不合适的话,最后的结果是有overlap的,下面我们展示两个例子 2. 第二个例子 自由操作tensor overlap的情况 根据上述讲的可以自己推一下 3. kernel size小于列向量的情况 上面讲了,fold每次都会对列向量进行提取,之前的例子都是kernel size等于列向量,如果我们的kernel size小于列向量就会出现以下情况 解释一下,我们第一次提取的应该是1256,但是由于我们的kernel太小了, 1 × 1 = 1 ,只能提取一个元素,因此就是1,我们的output size是 2 × 2 ,步长为1,所以第一次提取的结果如下 第二次提取时,就需要移动了,提取的不是列向量中的2,而是横向移动的3,接着放到刚才那个元素后面 之后的过程以此类推,直到我们提取到11,这时我们的行向量提取完了,但是列向量没有,所以我们从第二列开始重复刚才的过程即可,可以看到最终我们输出向量大小为[1,4,2,2],4就是我们提取了4次行向量,两个2就是每次提取的大小(即output size) 最后加一个复杂的具有padding的例子 padding就是在对tensor进行操作之前在tensor四周补0或其他的值。例子中仅对unfold进行padding,如果对fold进行padding也同理 总结 以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。