一、前言
本文对比 手动卷积演示代码 和 标准模型卷积实战代码 ,区分 torch.nn.functional.conv2d(函数式卷积)与 torch.nn.Conv2d(类形式卷积层)的用法、场景、底层逻辑,同时梳理张量维度、网络执行流程、数据集调用等全套知识点,适合深度学习入门复习。
二、代码 1:函数式卷积 F.conv2d 手动卷积演示
完整代码
python
运行
import torch
import torch.nn.functional as F
# 1. 定义原始二维输入矩阵(模拟单通道图像)
input = torch.tensor([[1,2,0,3,1],
[0,1,2,3,1],
[1,2,1,0,0],
[5,2,3,1,1],
[2,1,0,1,1]])
# 2. 手动定义卷积核
kernel = torch.tensor([[1,2,1],
[0,1,0],
[2,1,0]])
# 3. 维度变换:转为卷积要求的 4 维格式 [N, C, H, W]
# N=1(批次), C=1(通道), H=5(高), W=5(宽)
input = torch.reshape(input,(1,1,5,5))
# 卷积核也转为4维:[out_C, in_C, kH, kW]
kernel = torch.reshape(kernel,(1,1,3,3))
# 4. 调用函数式卷积完成计算
output = F.conv2d(input, kernel, stride=1)
# 5. 打印卷积结果
print(output)
逐行详细解析
1. 库导入
python
运行
import torch
import torch.nn.functional as F
torch:基础张量运算库,用来创建矩阵、变形、计算;torch.nn.functional:简写为F,函数式神经网络算子库 ,内部包含卷积、激活、池化等纯计算函数,无内置可训练参数。
2. 定义输入与卷积核
python
运行
# 原始输入:二维张量 [H, W] 5行5列
input = torch.tensor([[1,2,0,3,1],...])
# 手动自定义 3×3 卷积核
kernel = torch.tensor([[1,2,1],...])
- 此处是纯数学矩阵,模拟一张 5×5 单通道灰度图;
- 卷积核由用户手动指定固定数值,不是模型自动训练出来的参数。
3. reshape 维度扩充(核心重点)
python
运行
input = torch.reshape(input,(1,1,5,5))
PyTorch 二维卷积 conv2d 强制要求输入为 4 维张量 ,格式规定: [batch_size, channels, height, width] → 简写 [N, C, H, W]
参数解释:
- 第一个
1:batch_size批次大小,代表一批只有 1 张图; - 第二个
1:channels通道数,代表单通道灰度图; 5, 5:图像原始高度、宽度。
python
运行
kernel = torch.reshape(kernel,(1,1,3,3))
卷积核标准 4 维格式:[out_channels, in_channels, kH, kW]
- 第 1 个
1:输出通道数; - 第 2 个
1:输入通道数(和输入图像通道一致); 3,3:卷积核尺寸。
核心规则:只要使用卷积算子,必须补全 4 个维度,哪怕只有 1 张图、1 个通道。
4. F.conv2d 函数调用
python
运行
output = F.conv2d(input, kernel, stride=1)
- 函数特点:纯计算函数,不持有参数;
- 必须手动传入:输入张量、卷积核、步长;
stride=1:卷积核每次滑动 1 个像素;- 默认
padding=0:图像外围不补 0。
5. 输出形状计算

三、代码 2:类形式卷积 nn.Conv2d + 数据集实战
完整代码
python
运行
import torch.nn
import torchvision
from torch import nn
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
# 1. 加载CIFAR10测试集
torch_dataset = torchvision.datasets.CIFAR10(
root="../dataset",
train=False,
transform=torchvision.transforms.ToTensor(),
download=True
)
# 2. 批量数据加载器
dataloader = DataLoader(dataset=torch_dataset, batch_size=64)
# 3. 自定义卷积网络(继承nn.Module)
class f1(nn.Module):
def __init__(self):
super().__init__()
# 定义卷积层(类形式卷积)
self.conv2d=torch.nn.Conv2d(in_channels=3,out_channels=6,kernel_size=3,stride=1)
# 前向传播:数据运算逻辑
def forward(self, x):
x=self.conv2d(x)
return x
# 4. TensorBoard日志器
writer = SummaryWriter("logs3")
# 5. 实例化网络
f=f1()
step=0
# 6. 循环遍历批次数据
for data in dataloader:
imgs,target=data
# 传入图像,执行卷积运算
output =f(imgs)
# 可视化原始图片
writer.add_images("input",imgs,step)
# 重塑维度,适配TensorBoard显示
output = torch.reshape(output,(-1,3,30,30))
writer.add_images("output",output,step)
step+=1
# 关闭日志
writer.close()
逐行详细解析
1. 库导入
python
运行
import torchvision # 视觉库:数据集、图像预处理
from torch import nn # 神经网络模块:网络层、模型基类
from torch.utils.data import DataLoader # 批量加载数据
from torch.utils.tensorboard import SummaryWriter # 可视化
2. 加载 CIFAR10 数据集
python
运行
torch_dataset = torchvision.datasets.CIFAR10(
root="../dataset", # 数据集存放路径,../ 代表上一级目录
train=False, # False = 加载测试集(10000张)
transform=ToTensor(), # 预处理:PIL图 → 张量 + 归一化 + 维度转换
download=True # 本地无文件则自动下载
)
- 单张图像形状:
[3, 32, 32],3 通道 RGB 彩色图; - 像素范围:
[0, 1]。
3. DataLoader 批量打包
python
运行
dataloader = DataLoader(dataset=torch_dataset, batch_size=64)
batch_size=64:每一批取出 64 张图片;- 输出数据形状:
[64, 3, 32, 32],标准 4 维卷积输入格式。
4. 自定义网络类(PyTorch 标准模型写法)
python
运行
class f1(nn.Module):
def __init__(self):
super().__init__()
# 定义卷积层:类形式 Conv2d
self.conv2d=torch.nn.Conv2d(in_channels=3,out_channels=6,kernel_size=3,stride=1)
nn.Module:所有自定义网络必须继承的基类,负责参数管理、反向传播、模型保存;__init__初始化函数:- 仅在模型创建时执行 1 次;
- 作用:定义网络层、自动创建可训练参数(卷积核 + 偏置);
- 此阶段不做任何图像运算。
nn.Conv2d 核心参数详解
表格
| 参数 | 取值 | 含义 |
|---|---|---|
in_channels=3 |
3 | 输入通道数,对应 RGB 三通道图像 |
out_channels=6 |
6 | 输出通道数,代表使用 6 个卷积核,输出 6 组特征图 |
kernel_size=3 |
3 | 卷积核大小 3×3 |
stride=1 |
1 | 卷积核滑动步长为 1 |
默认参数:padding=0,不补 0。
5. forward 前向传播函数
python
运行
def forward(self, x):
x=self.conv2d(x)
return x
- 网络真正执行运算的地方;
- 规则:外部调用
模型实例(输入)时,PyTorch 会自动执行 forward; - 每一批数据都会走一遍该函数,完成卷积计算。
6. 模型实例化 & 循环推理
python
运行
f=f1() # 创建模型,执行 __init__,初始化卷积核参数
for data in dataloader:
imgs,target=data # 解包:图像张量 + 标签
output =f(imgs) # 传入图像 → 自动调用forward → 执行卷积
f(imgs)是整套代码的运算入口;- 卷积输入:
[64, 3, 32, 32]; - 卷积输出尺寸计算: \((32-3)\div1 +1 = 30\) 输出形状:
[64, 6, 30, 30]
7. reshape 与 TensorBoard 可视化
python
运行
output = torch.reshape(output,(-1,3,30,30))
- 原始输出通道为 6,TensorBoard 仅支持 1/3 通道图片渲染,直接使用会报警告;
(-1, 3, 30, 30):-1:自动推导批次维度;3:强制改为 3 通道,适配 RGB 可视化;
- 注意:
reshape返回新张量,必须用变量接收,否则修改无效。
8. writer.close()
将内存中日志完整写入本地文件,防止日志丢失。
四、两段代码核心对比(重点总结)
1. 卷积 API 本质区别(最核心)
表格
| 对比项 | 代码 1:F.conv2d(函数式) |
代码 2:nn.Conv2d(类形式) |
|---|---|---|
| 所属模块 | torch.nn.functional |
torch.nn |
| 参数持有 | 无内置参数,卷积核手动传入、固定不变 | 自带 weight/bias 可训练参数,框架自动初始化 |
| 使用位置 | 任意位置,多用于临时计算、原理演示 | 写在 __init__ 中,标准网络层写法 |
| 训练属性 | 卷积核不参与反向传播、无法训练 | 参数被模型收集,可配合优化器训练更新 |
| 适用场景 | 学习卷积原理、手动验证计算、固定特征提取 | 搭建深度学习模型、模型训练、工程实战 |
2. 输入数据形式对比
-
代码 1
- 输入:手动定义 5×5 二维矩阵(模拟单张灰度图);
- 维度:手动
reshape为[1, 1, 5, 5](单批次、单通道); - 数据来源:手动构造张量。
-
代码 2
- 输入:CIFAR10 标准数据集,RGB 彩色图;
- 维度:
[64, 3, 32, 32](多批次、三通道); - 数据来源:
torchvision官方数据集 +DataLoader批量加载。
3. 代码结构与执行流程对比
代码 1 流程(简单流程)
- 创建矩阵 + 卷积核
- 统一转为 4 维张量
- 调用
F.conv2d直接计算 - 输出结果
特点:一步计算,无网络结构、无循环、无训练逻辑。
代码 2 流程(标准深度学习流程)
- 加载数据集 → DataLoader 分批
- 定义网络类(继承
nn.Module)__init__:搭建卷积层(仅执行 1 次)forward:定义运算逻辑(循环执行)
- 实例化模型
- 循环遍历每一批数据 → 送入模型推理
- TensorBoard 可视化
特点:工业级标准流程,可直接扩展为训练网络。
4. 通道数差异
- 代码 1:单通道图像(
C=1),输出单通道特征图; - 代码 2:RGB 三通道图像(
C=3),卷积输出 6 通道特征图。
5. reshape 作用差异
- 代码 1:补全卷积必需的 4 维格式,为了正常执行卷积;
- 代码 2:修改通道数,为了适配 TensorBoard 可视化。
五、通用知识点汇总(复习必背)
-
卷积统一要求 无论哪种卷积方式,输入必须是 4 维张量:
[N, C, H, W](批次、通道、高、宽)。 -
卷积尺寸通用公式 \(H_{out} = \frac{H_{in} - kH}{stride} + 1 \quad (padding=0)\)
-
使用选择建议
- 学习卷积原理、手写验证 → 用
F.conv2d; - 搭建模型、训练网络、项目开发 → 用
nn.Conv2d。
- 学习卷积原理、手写验证 → 用
-
PyTorch 网络固定分工
__init__:定义层、初始化参数(只执行一次);forward:数据前向运算(每一条数据都执行)。
-
TensorBoard 限制 图像可视化仅支持 1 通道(灰度)、3 通道(RGB),多通道特征图需要维度转换才能显示。
六、易错点整理
- 卷积算子必须 4 维输入,二维矩阵一定要用
reshape扩维; reshape不会原地修改张量,必须接收返回值;nn.Module不要拼写错误(禁止写成Moudle);F.conv2d卷积核固定,nn.Conv2d卷积核可训练;- 输入通道数必须和上一层输出通道数保持一致。