【PyTorch】F.pad的四种模式详解:从基础填充到循环边界处理

张开发
2026/4/18 0:42:17 15 分钟阅读

分享文章

【PyTorch】F.pad的四种模式详解:从基础填充到循环边界处理
1. 为什么需要填充操作在深度学习任务中我们经常会遇到数据维度不匹配的情况。比如处理图像时不同尺寸的图片需要统一大小才能输入网络处理序列数据时不同长度的文本需要对齐才能批量处理。这时候就需要用到填充padding操作。PyTorch中的F.pad函数就是专门用来解决这个问题的。我第一次接触这个函数是在做图像分类项目时发现不同尺寸的图片无法组成一个batch。当时尝试了各种方法最后发现F.pad是最优雅的解决方案。它不仅支持常规的零填充还提供了多种边界处理方式这在图像处理中特别有用。2. F.pad基础用法详解2.1 函数参数说明F.pad的基本语法是这样的F.pad(input, pad, modeconstant, value0)让我拆解一下各个参数input要填充的张量可以是1D、2D或3Dpad一个元组指定每个维度要填充的数量mode填充模式这是本文重点要讲的内容value仅当modeconstant时有效指定填充值2.2 基本填充示例先看一个最简单的1D张量填充例子import torch import torch.nn.functional as F x torch.tensor([1, 2, 3]) padded F.pad(x, (1, 2)) # 左边填充1个0右边填充2个0 print(padded) # 输出tensor([0, 1, 2, 3, 0, 0])这里(1,2)表示在第一个维度也是唯一维度左边填充1个元素右边填充2个元素。默认使用0填充因为mode默认是constant。3. 四种填充模式深度解析3.1 constant模式默认模式constant模式是最简单的填充方式用固定值填充边缘。除了默认的0我们可以指定任何填充值x torch.tensor([[1, 2], [3, 4]]) padded F.pad(x, (1, 1, 1, 1), modeconstant, value9) print(padded) 输出 tensor([[9, 9, 9, 9], [9, 1, 2, 9], [9, 3, 4, 9], [9, 9, 9, 9]]) 注意这里的pad参数(1,1,1,1)表示第一个1最后一维列左边填充1个第二个1最后一维右边填充1个第三个1倒数第二维行上边填充1个第四个1倒数第二维下边填充1个3.2 reflect模式reflect模式就像在边缘放了一面镜子会反射张量边界附近的值。这种模式在图像处理中特别有用可以避免引入突兀的填充值。x torch.tensor([1, 2, 3, 4]) padded F.pad(x, (2, 2), modereflect) print(padded) # 输出tensor([3, 2, 1, 2, 3, 4, 3, 2])可以看到填充的值是原始张量的镜像反射左边填充的两个值3,2对应原始张量的2,1从边界开始反向右边填充的两个值3,2对应原始张量的3,4从边界开始反向3.3 replicate模式replicate模式简单复制边缘值进行填充。这种模式适合处理渐变信号可以保持边缘的连续性。x torch.tensor([1, 2, 3, 4]) padded F.pad(x, (2, 2), modereplicate) print(padded) # 输出tensor([1, 1, 1, 2, 3, 4, 4, 4])可以看到左边填充的两个值都是第一个元素1的复制右边填充的两个值都是最后一个元素4的复制3.4 circular模式circular模式就像把张量首尾相连从另一端绕过来取值填充。这种模式在处理周期性信号时特别有用。x torch.tensor([1, 2, 3, 4]) padded F.pad(x, (2, 2), modecircular) print(padded) # 输出tensor([3, 4, 1, 2, 3, 4, 1, 2])填充的值来自张量的另一端左边填充的3,4来自张量末尾的两个值右边填充的1,2来自张量开头的两个值4. 不同维度的填充实践4.1 1D张量填充1D填充最简单只需要指定左右两边的填充量。我在处理时间序列数据时经常用到。# 温度数据序列 temps torch.tensor([22.1, 22.3, 22.0, 21.9, 22.2]) # 左右各填充2个值 padded F.pad(temps, (2, 2), modereplicate) print(padded) # 输出tensor([22.1, 22.1, 22.1, 22.3, 22.0, 21.9, 22.2, 22.2, 22.2])4.2 2D张量填充2D填充需要指定四个值(左,右,上,下)。这在图像处理中最常见。# 模拟一个3x3的灰度图像 img torch.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) # 四周各填充1个像素 padded F.pad(img, (1,1,1,1), modereflect) print(padded) 输出 tensor([[5, 4, 5, 6, 5], [2, 1, 2, 3, 2], [5, 4, 5, 6, 5], [8, 7, 8, 9, 8], [5, 4, 5, 6, 5]]) 4.3 3D张量填充3D张量填充需要指定6个值(左,右,上,下,前,后)。这在处理视频或体积数据时会用到。# 模拟一个2x2x2的体积数据 volume torch.tensor([[[1, 2], [3, 4]], [[5, 6], [7, 8]]]) # 在各个方向填充1个值 padded F.pad(volume, (1,1,1,1,1,1), modeconstant, value0) print(padded.shape) # 输出torch.Size([4, 4, 4])5. 实际应用场景分析5.1 图像处理中的边缘效应在做图像卷积时边缘像素的卷积结果会丢失信息。使用适当的填充模式可以缓解这个问题。我做过一个对比实验不使用填充图像每次卷积后尺寸都会缩小使用zero-padding会在边缘引入明显的边界使用reflect-padding能最好地保持图像内容连续性# 图像卷积示例 image torch.randn(1, 3, 256, 256) # 模拟RGB图像 conv nn.Conv2d(3, 16, kernel_size3, padding1, padding_modereflect) output conv(image)5.2 序列数据处理在处理不等长文本序列时我们经常需要填充到相同长度。但要注意对于RNN模型constant填充0可能影响模型性能对于某些任务reflect或replicate模式可能更合理# 文本序列填充示例 sequences [torch.tensor([1, 2, 3]), torch.tensor([4, 5])] max_len 4 padded_seqs [] for seq in sequences: pad_size max_len - len(seq) padded F.pad(seq, (0, pad_size), modeconstant) padded_seqs.append(padded)5.3 医学图像处理在处理CT或MRI等医学图像时circular模式可能不适合因为人体结构不具有周期性。这时reflect或replicate模式更合适。我在一个肝脏分割项目中发现使用reflect填充可以在保持器官边界连续性的同时避免引入伪影。6. 性能考量与常见问题6.1 不同模式的限制需要注意的是非constant模式reflect, replicate, circular只支持3D、4D、5D张量。这是PyTorch的当前限制。# 这会报错 x torch.tensor([1, 2, 3]) padded F.pad(x, (1,1), modereflect) # 错误6.2 内存消耗填充操作会增加内存使用量特别是对高维数据。我曾经在处理3D医学图像时因为过度填充导致GPU内存不足。解决方案是尽量只填充必要的量考虑使用in-place操作及时释放不再需要的中间张量6.3 反向传播的影响填充操作在反向传播时会有特殊处理constant填充的部分梯度为0其他模式的填充会参与梯度计算这在设计自定义层时要特别注意。我曾在实现一个特殊卷积层时因为不理解这点导致梯度计算错误。7. 高级技巧与最佳实践7.1 动态填充策略有时我们需要根据输入尺寸动态计算填充量。比如实现same卷积时def pad_for_same_conv(input, kernel_size): pad_total kernel_size - 1 pad_left pad_total // 2 pad_right pad_total - pad_left return F.pad(input, (pad_left, pad_right), modereflect)7.2 组合使用不同模式在某些场景下我们可能需要对不同维度使用不同填充模式。虽然F.pad不支持直接这样做但可以通过多次填充实现x torch.randn(3, 256, 256) # 模拟图像 # 对高度维度使用reflect x F.pad(x, (0,0,1,1), modereflect) # 对宽度维度使用replicate x F.pad(x, (1,1,0,0), modereplicate)7.3 自定义填充值对于constant模式我们可以使用非零填充值。这在某些特殊场景下很有用# 用-1填充序列 seq torch.tensor([1, 2, 3]) padded F.pad(seq, (1,1), modeconstant, value-1) # 输出tensor([-1, 1, 2, 3, -1])在实际项目中我发现合理选择填充值可以显著影响模型性能。比如在自然语言处理中用-100填充的标签可以在计算损失时被自动忽略。

更多文章