当前位置: 首页 > news >正文

PyTorch Conv2d 参数详解:padding=1 与 kernel_size=3 如何保持特征图尺寸不变

PyTorch Conv2d 参数详解:padding=1 与 kernel_size=3 如何保持特征图尺寸不变

当我们在构建卷积神经网络时,经常会遇到一个关键问题:如何在卷积操作后保持特征图的尺寸不变?这看似简单的需求背后,其实隐藏着卷积运算的数学原理和工程实践的巧妙平衡。本文将深入探讨PyTorch中Conv2d层的这一特性,通过公式推导、可视化解释和代码验证,带你彻底理解padding与kernel_size的配合机制。

1. 卷积操作中的尺寸变化原理

卷积神经网络(CNN)的核心操作是卷积运算,但初学者常常会对卷积后特征图尺寸的变化感到困惑。让我们从一个简单的例子开始:假设我们有一个5×5的输入特征图,使用3×3的卷积核进行卷积,步长(stride)为1,不进行填充(padding=0)。这时输出特征图的尺寸是多少?

根据卷积运算的基本公式:

H_out = (H_in - kernel_size + 2 * padding) / stride + 1 W_out = (W_in - kernel_size + 2 * padding) / stride + 1

代入数值计算:

H_out = (5 - 3 + 0) / 1 + 1 = 3 W_out = (5 - 3 + 0) / 1 + 1 = 3

可以看到,输出特征图的尺寸从5×5缩小到了3×3。这是因为卷积核在移动时,中心点只能覆盖输入特征图的中间区域,边缘的像素无法作为中心点被处理。

为什么这会造成问题?在深层网络中,连续的卷积操作会使特征图尺寸迅速缩小:

  • 第一层卷积:5×5 → 3×3
  • 第二层卷积:3×3 → 1×1
  • 第三层卷积:无法进行

这种尺寸的快速缩减会限制网络的深度,同时边缘信息的丢失也可能影响模型性能。

2. 填充(padding)的解决方案

为了保持特征图尺寸不变,我们需要引入填充(padding)的概念。填充是指在输入特征图的周围添加额外的像素值(通常是0),以扩展输入的尺寸。对于3×3的卷积核,如果我们希望在卷积后尺寸不变,应该设置多少padding?

让我们推导一般情况下的公式。要使H_out = H_in,根据公式:

H_in = (H_in - kernel_size + 2 * padding) / stride + 1

解这个方程:

H_in * stride = H_in - kernel_size + 2 * padding + stride 2 * padding = H_in * (stride - 1) + kernel_size - stride

当stride=1时,公式简化为:

2 * padding = kernel_size - 1 padding = (kernel_size - 1) / 2

因此,对于kernel_size=3:

padding = (3 - 1) / 2 = 1

这就是为什么在使用3×3卷积核时,设置padding=1可以保持特征图尺寸不变。同理:

  • 对于5×5卷积核:padding=(5-1)/2=2
  • 对于7×7卷积核:padding=(7-1)/2=3

为什么卷积核大小通常为奇数?从上面的计算可以看出,当kernel_size为奇数时,padding会是整数,这在实际操作中更方便实现。如果使用偶数尺寸的卷积核,padding将出现小数,导致不对称的填充,这在工程实现上更为复杂。

3. 不同参数组合的对比分析

为了更直观地理解padding和kernel_size的关系,我们来看几种常见配置下的输出尺寸变化:

输入尺寸kernel_sizepaddingstride输出尺寸尺寸是否不变
5×53×3013×3
5×53×3115×5
5×55×5011×1
5×55×5215×5
7×73×3124×4
7×73×3117×7

从表格中可以得出几个重要结论:

  1. 当stride=1时,padding=(kernel_size-1)/2能保持尺寸不变
  2. 增大stride会导致输出尺寸减小,这是下采样的一种方式
  3. 更大的kernel_size需要更多的padding来维持尺寸

4. PyTorch实现与验证

理论需要通过实践来验证。下面我们通过PyTorch代码来实际验证padding=1和kernel_size=3的组合是否能保持特征图尺寸不变。

import torch import torch.nn as nn # 创建一个5×5的随机输入特征图 (batch_size=1, channels=1, height=5, width=5) input_tensor = torch.randn(1, 1, 5, 5) # 创建3×3卷积层,padding=1 conv_layer = nn.Conv2d(in_channels=1, out_channels=1, kernel_size=3, padding=1) # 进行卷积操作 output_tensor = conv_layer(input_tensor) print("输入尺寸:", input_tensor.shape) print("输出尺寸:", output_tensor.shape)

运行结果:

输入尺寸: torch.Size([1, 1, 5, 5]) 输出尺寸: torch.Size([1, 1, 5, 5])

确实,输出尺寸与输入尺寸保持一致。为了更全面地验证,我们可以创建一个测试函数:

def test_conv_params(input_size, kernel_size, padding, stride): input_tensor = torch.randn(1, 1, input_size, input_size) conv_layer = nn.Conv2d(1, 1, kernel_size=kernel_size, padding=padding, stride=stride) output = conv_layer(input_tensor) print(f"输入:{input_size}×{input_size}, 核:{kernel_size}, " f"填充:{padding}, 步长:{stride} => 输出:{output.shape[2]}×{output.shape[3]}") # 测试不同配置 test_conv_params(5, 3, 1, 1) # 尺寸不变 test_conv_params(7, 3, 1, 2) # 使用步长2下采样 test_conv_params(5, 5, 2, 1) # 5×5核需要padding=2保持尺寸

输出:

输入:5×5, 核:3, 填充:1, 步长:1 => 输出:5×5 输入:7×7, 核:3, 填充:1, 步长:2 => 输出:4×4 输入:5×5, 核:5, 填充:2, 步长:1 => 输出:5×5

5. 实际应用中的考量

理解了padding和kernel_size的关系后,在实际网络设计中我们还需要考虑以下因素:

  1. 计算开销:更大的kernel_size和padding会增加计算量。3×3卷积因其良好的平衡性成为最常用的选择。

  2. 感受野:虽然padding=1和kernel_size=3保持了尺寸,但感受野(每个输出像素能看到输入图像的区域)仍然只有3×3。为了增加感受野,可以采用:

    • 堆叠多个3×3卷积(两个3×3卷积的感受野相当于一个5×5)
    • 使用空洞卷积(dilated convolution)
  3. 边界效应:填充的像素(通常是0)可能影响边界特征的学习。在某些情况下,可以使用反射填充(reflection padding)或复制填充(replication padding)作为替代。

  4. 步长选择:当需要下采样时,可以使用stride=2的卷积,但要注意输出尺寸的计算。另一种常见做法是保持stride=1,使用最大池化进行下采样。

# 两种下采样方式的对比 def compare_downsample(): input_tensor = torch.randn(1, 1, 7, 7) # 方式1:使用stride=2的卷积 conv_stride2 = nn.Conv2d(1, 1, kernel_size=3, padding=1, stride=2) out1 = conv_stride2(input_tensor) # 方式2:stride=1卷积+最大池化 conv_stride1 = nn.Conv2d(1, 1, kernel_size=3, padding=1, stride=1) pool = nn.MaxPool2d(kernel_size=2, stride=2) out2 = pool(conv_stride1(input_tensor)) print(f"stride=2卷积输出尺寸: {out1.shape}") print(f"卷积+池化输出尺寸: {out2.shape}") compare_downsample()

输出:

stride=2卷积输出尺寸: torch.Size([1, 1, 4, 4]) 卷积+池化输出尺寸: torch.Size([1, 1, 3, 3])

可以看到,两种方式的输出尺寸略有不同,这是因为池化操作的计算方式与步长卷积有所不同。在实际网络中,这两种方式各有优劣,需要根据具体任务进行选择。

http://www.jsqmd.com/news/1139837/

相关文章:

  • Java毕设选题推荐:基于 SpringBoot 的校园运动会赛程编排管理系统的设计与实现 基于 SpringBoot+Vue 的大学生运动会成【附源码、mysql、文档、调试+代码讲解+全bao等】
  • [GESP202606 八级] 线网建设题解
  • YOLOv10模型改进-损失函数改进-第89篇:YOLOv10改进策略【损失函数】| Huber Loss损失函数
  • Qt信号槽在使用中避免循环绑定
  • PyTorch 2.0 CIFAR-10 模型优化:3种学习率策略对比,测试集准确率提升至69.78%
  • Python爬虫经典案例第83篇:在线博客平台爬取:掘金数据采集实战
  • CIC研判:数字化越转越重,病根还是在低代码工作流
  • BLIP BLIP-2 超详细入门解析
  • 电商罗盘视频怎么下载?罗盘视频跳转、无水印下载和内容库教程
  • PyTorch nn.LSTM 参数详解与避坑指南:batch_first 等5个关键参数实战解析
  • 如何3秒完成网页图片格式转换:Save Image as Type浏览器扩展完整指南
  • Opus 4.8、GPT-5.5、Gemini 3.1 Pro 测了同一套任务,输赢比你想的复杂
  • 非遗网站平台的设计与实现毕业设计任务书
  • 谷歌 Find Hub 双版本迭代优化软硬件生态
  • TensorFlow 2.10 GPU Windows 终极配置:CUDA 11.2 + cuDNN 8.1 避坑 3 要点
  • 支撑 2500 亿行对话数据:某头部大模型公司如何用 TiDB 托住高频 AI 交互场景
  • 3个关键步骤彻底解决Intel Mac过热问题:Turbo Boost Switcher终极指南
  • MDX-M3-Viewer:游戏模型格式的WebGL解析与可视化引擎
  • 重构石化智能底座——乾元通多链路技术赋能石化生产与数据融合
  • 旧地面翻新
  • Transformer 架构 2023:从 GPT-3 到 Stable Diffusion 的 5 大 AIGC 基石模型对比
  • 运算放大器 PCB 布局 5 大误区解析:从原理图正确到板级失效的根因
  • SSD能效比如何决定大模型本地推理流畅度
  • IDM激活脚本终极指南:5种方法实现永久免费下载管理
  • 计算机毕业设计之基于YOLO11的图像识别的交通信号灯识别
  • 赛博朋克边缘行者2:AI图像生成与本地部署技术实践指南
  • 城市地铁屏蔽门专用安全光幕选型指南
  • 深度解析msvcp140.dll运行原理,配套msvcp140.dll丢失的解决方法分层修复方案
  • Windows下pyenv-win安全审计与防护实战指南
  • 影刀RPA新手教程:定时任务常见问题完全指南——为什么定时任务没有跑起来