查看: 133|回复: 3

PyTorch中unfold使用指南:滑动窗口原理与图像patch切分实战

[复制链接]
发表于 2 小时前 | 显示全部楼层 |阅读模式
在PyTorch中,unfold是一个用于滑动窗口数据提取的操作,它不执行卷积或池化等计算,只负责将张量沿指定维度切分成多个局部区域。理解unfold的原理对于实现Vision Transformer中的patch embedding、滑动窗口特征提取等任务至关重要。

一、unfold基本格式与参数
调用方式:x.unfold(dimension, size, step)
- dimension:切分的维度索引
- size:窗口大小
- step:每次滑动的步长

返回的新张量中,原维度位置变为窗口数量维度,末尾新增一个维度表示窗口内元素个数。

二、一维张量例子
  1. import torch
  2. x = torch.tensor([1, 2, 3, 4, 5, 6])
  3. y = x.unfold(0, 3, 1)
  4. print(y)
  5. # tensor([[1, 2, 3],
  6. #         [2, 3, 4],
  7. #         [3, 4, 5],
  8. #         [4, 5, 6]])
  9. print(y.shape)  # [4, 3]
复制代码
原长度6被拆成4个窗口,每个窗口长度3。

三、size与step的关系
1. step < size:窗口重叠。例如unfold(0,3,1)得到4个窗口,相邻窗口有2个元素重叠,常用于滑动窗口特征提取。
2. step == size:窗口不重叠。例如unfold(0,3,3)得到[[1,2,3],[4,5,6]],图像切patch时通常采用此方式。
3. step > size:窗口间有空隙,部分数据被跳过。例如unfold(0,2,3)得到[[1,2],[4,5]],中间的元素3未被使用。

四、窗口数量计算公式
假设原始长度为L,窗口大小size,步长step,则窗口数量为 floor((L - size) / step) + 1。注意unfold不会自动补边,剩余数据不足一个完整窗口时会被舍弃。例如L=6,size=3,step=2,窗口数为floor((6-3)/2)+1=2。

五、unfold为什么多出一维
unfold将一个维度拆解为两个维度:窗口数量维度和窗口内部大小维度。窗口数量维度保留在原位置,窗口内部大小维度追加到最后。例如原始维度长度为6,执行unfold(0,3,1)后,原维度变成4(窗口数),末尾新增维度3(窗口大小)。

六、图像中的unfold:两次切分实现patch提取
图像张量通常为[B, C, H, W]。为了沿高度和宽度方向分别用unfold切分,需要先通过permute将通道维度移到末尾:[B, H, W, C]。
  1. x = x.permute(0, 2, 3, 1)  # [B, H, W, C]
复制代码
第一次unfold沿高度方向(第1维):
  1. x = x.unfold(1, patch_size, patch_size)  # [B, H_num, W, C, patch_H]
复制代码
第二次unfold沿宽度方向(第2维):
  1. x = x.unfold(2, patch_size, patch_size)  # [B, H_num, W_num, C, patch_H, patch_W]
复制代码
最后通过contiguous和view整理成标准patch格式:
  1. x = x.contiguous().view(B, -1, C, patch_size, patch_size)  # [B, N, C, patch_size, patch_size]
复制代码
其中N = H_num × W_num,即每张图片的patch总数。

七、实战例子:32×32图像切16×16 patch
输入形状[1, 3, 32, 32],patch_size=16。
- permute后:[1, 32, 32, 3]
- 第一次unfold(高度方向):[1, 2, 32, 3, 16](32/16=2)
- 第二次unfold(宽度方向):[1, 2, 2, 3, 16, 16](32/16=2)
- view后:[1, 4, 3, 16, 16](N=2×2=4)

八、实战例子:224×224图像切16×16 patch
输入形状[B, 3, 224, 224],patch_size=16。
高度方向窗口数:224/16=14;宽度方向窗口数:224/16=14。
最终输出形状:[B, 196, 3, 16, 16],每张图片得到196个patch。

通过掌握unfold的参数含义和维度变换规律,开发者可以灵活实现各种滑动窗口操作,在图像分割、Patch Embedding、局部特征提取等场景中高效编码。
回复

使用道具 举报

发表于 1 小时前 | 显示全部楼层

Re: PyTorch中unfold使用指南:滑动窗口原理与图像patch切分实战

感谢楼主的详细讲解!之前对unfold的维度变化一直有点绕,特别是图像里两次unfold配合permute和view的操作,看了你的实战例子后豁然开朗。之前做ViT的patch embedding时用的是torch.nn.functional.unfold,但参数和维度处理跟你这里说的思路一致,现在终于理解底层原理了。另外想请教一下:如果图像尺寸不能被patch_size整除,除了手动padding之外,unfold是否有内置的补边选项?还是必须自己先pad再unfold?
回复 支持 反对

使用道具 举报

发表于 1 小时前 | 显示全部楼层

Re: PyTorch中unfold使用指南:滑动窗口原理与图像patch切分实战

感谢楼主分享这么详细的PyTorch `unfold` 教程!之前一直对滑动窗口切分 patch 的维度变换有点迷糊,看了你的解释尤其是两次 unflod 加 permute 和 view 的那部分,一下子就清晰了。实战例子从 32×32 到 224×224 的对比也很直观,窗口数量公式和补边问题也提醒得很及时。收藏了,以后做 ViT 就照着这个思路来!
回复 支持 反对

使用道具 举报

发表于 1 小时前 | 显示全部楼层

Re: PyTorch中unfold使用指南:滑动窗口原理与图像patch切分实战

感谢楼主的详细讲解!这篇文章把unfold的维度变化和slide窗口原理梳理得非常清晰,尤其是图像patch切分中两次unfold配合permute的思路,对理解ViT的patch embedding实现很有帮助。之前自己写patch切分时总搞不清维度顺序,看了你列出的实战例子(比如224→16那种),配合窗口数公式,一下子就豁然开朗了。 另外想请教一个问题:当step < size有重叠时,如果后续要还原回原始形状(比如做unfold→处理→fold),楼主有没有遇到过边界处理上的坑?比如unfold舍弃的尾端数据,fold时是否会自动补齐?期待你后续的讨论。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-7-5 13:03 , Processed in 0.033966 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部