nn.Conv2d 是 torch.nn 中 2D 卷积的落地入口:吃进 (N, C_in, H, W) 的图像张量,用一组可学习的滑动滤波器产出特征图。本篇只讲基础运算的 API 面——参数语义、输出尺寸、权重布局与参数量,卷积变体的概念原理由库内其他笔记承接。
一层在算什么:shape 的进与出
构造签名 nn.Conv2d(in_channels, out_channels, kernel_size, ...) 里,out_channels 决定有几个独立滤波器,也就直接决定输出通道数;每个滤波器在输入上滑动做加权求和加 bias,产出一张特征图。shape 变化用手跑一遍最直观:
import torch
import torch.nn as nn
conv = nn.Conv2d(3, 16, kernel_size=3, stride=1, padding=1) # padding=1 抵消核覆盖的尺寸损失
x = torch.randn(2, 3, 224, 224) # (N, C_in, H, W)
print(conv(x).shape) # (2, 16, 224, 224)
print(conv.weight.shape) # (C_out, C_in/groups, kH, kW) = (16, 3, 3, 3)
print(conv.bias.shape) # (16,)权重是 4D 张量 (C_out, C_in/groups, kH, kW),bias 每个输出通道一个。注意 PyTorch 全线采用 Channels First(NCHW)约定,batch 维之后紧跟通道维——从 TensorFlow 等 NHWC 框架迁移权重时必须先 tensor.permute(0, 3, 1, 2) 换位,并核对 C_out/C_in 的排布顺序。
几何参数与输出尺寸
shape 之外,构造函数其余参数都在控制同一件事:滤波器在输入网格上的滑动几何。stride 是每次滑动的步长,padding 是四周补的圈数,dilation 在核内元素间挖洞,padding_mode 可把补零换成 'reflect'、'replicate' 或 'circular'。输出尺寸由一条公式统一:
其中 是输入高, 为 padding, 为 kernel_size, 为 dilation, 为 stride;被减掉的 正是挖洞后拉长的有效核尺寸, 方向同式。最常用组合是 k=3, p=1, s=1——尺寸不变;s=2 输出减半,是主流下采样写法。
参数量:为这一层付的账单
几何参数改变输出 shape,权重布局才决定训练开销。参数量是一条乘法:
即每个输出通道持有一份 的核外加一个 bias,上面例子为 。单层感受野只有核大小,但随层数堆叠逐层增长——这是”深”网络积累空间上下文的来源。
groups 与 dilation:公式里的两个杠杆
两条公式各留了一个可动的变量。参数量公式里的 就是 groups:输入输出通道分组、各组独立卷积,权重第二维从 缩到 ,参数量近似除以 ; 的极限即 depthwise 卷积,MobileNet 的深度可分离结构(depthwise + 1×1 pointwise)靠它把参数压掉一个量级。
几何公式里的 则是 dilation:核内挖洞使有效核尺寸变为 ,感受野扩大而参数分文未增,语义分割靠它不降分辨率地覆盖大视野,原理见 空洞卷积 Atrous Convolution。
变体与坑
不同维度的信号各有对应入口:nn.Conv1d 处理序列与音频,nn.Conv3d 处理视频与体数据(见 3D 卷积(3D Convolution, 3D-CNN)详解),采样位置本身可学的版本是 可变卷积 Deformable Convolution——它们共享同一套 shape 与参数量公式,只是维度不同。高频坑有二:padding='same' 只允许 stride=1,动态补齐与跨步采样语义冲突,组合即报错;跨框架迁移权重时 NCHW/NHWC 的换位最易漏查。卷积层与 nn 归一化层 的 conv+BN 组合及各层横向对比,见 常见网络层总结。