CNN 张量形状与参数量
系统计算 NCHW、卷积/池化输出、Flatten 和 Linear 参数量。
学习目标
- 同一卷积处理两种图像大小
- 为什么 Flatten 后容易出现 Linear 维度错误?
- 说明:参数统计不能替代速度、显存或泛化能力评估。
为什么需要这个概念
CNN 形状分析逐层计算 batch、通道、空间尺寸的变化;参数统计只计算可学习张量元素数,两者相关但不是同一件事。
学习前需要掌握
背景与问题
卷积网络改一个步长,后面所有展平维度都可能变化。先画出形状链和参数账本,可以在训练前发现不匹配,并判断模型主要把容量花在哪里。
概念定义
CNN 形状分析逐层计算 batch、通道、空间尺寸的变化;参数统计只计算可学习张量元素数,两者相关但不是同一件事。
直观理解
激活大小像流水线当前占用的工作台,参数量像固定安装的工具数量。换大图会占更多工作台,却不一定增加工具。
核心原理
普通卷积输出空间长度按输入、padding、dilation、核、stride 计算并向下取整。batch 通常保持,通道变为 out_channels;池化一般保留通道,只改变空间。Flatten(start_dim=1) 合并非 batch 维,避免误把样本拼在一起。
带偏置普通卷积参数为 C_out×(C_in×K_h×K_w+1),groups 不为 1 时需把每核输入通道除以 groups。线性层参数为 out_features×(in_features+1)。BatchNorm 另有缩放和偏移参数,running stats 是 buffer。
参数少不代表运行快:高分辨率卷积会在很多位置重复计算。训练显存还包括激活、梯度和优化器状态,因此应分别记录参数、输出形状和实际内存测量。
数学表达
核心公式
CNN 形状分析逐层计算 batch、通道、空间尺寸的变化;参数统计只计算可学习张量元素数,两者相关但不是同一件事。
变量含义
NbatchC通道H,W空间尺寸
计算步骤
- 132 的输出为 floor((32+2−3)/2)+1=16。
- 264 的输出为 32。
- 3参数始终为 8×(3×9+1)=224。
代码对应位置
示例 1同一卷积处理两种图像大小的最小验证:使用完整构造输入核对同一卷积处理两种图像大小,输出只表示本例计算。
变量解释
| 变量 | 含义 |
|---|---|
N | batch |
C | 通道 |
H,W | 空间尺寸 |
完整数值示例
同一卷积处理两种图像大小
已知条件
- 卷积从 3 通道变为 8 通道,3×3 核,有偏置
- stride=2,padding=1
- 输入高宽分别为 32 与 64
计算步骤
- 32 的输出为 floor((32+2−3)/2)+1=16。
- 64 的输出为 32。
- 参数始终为 8×(3×9+1)=224。
计算结果
输出分别是 (2,8,16,16) 和 (2,8,32,32),参数均为 224。
处理前后对比
- 参数统计不能替代速度、显存或泛化能力评估。
同一卷积处理两种图像大小
空间边长翻倍,输出元素数变为四倍,但核仍是同一组 224 个参数。若之后接展平全连接,输入特征数也变为四倍,分类头参数才会跟着增加。
这解释了为什么一张高分辨率图片可能耗尽显存,即使模型文件没有变大。估算资源时,只报模型参数数量会遗漏主要的激活成本。
计算与实现步骤
- 32 的输出为 floor((32+2−3)/2)+1=16。
- 64 的输出为 32。
- 参数始终为 8×(3×9+1)=224。
代码实现
示例 1
同一卷积处理两种图像大小的最小验证
example_01.py用途:使用完整构造输入核对同一卷积处理两种图像大小,输出只表示本例计算。
import torch
from torch import nn
conv = nn.Conv2d(3, 8, 3, stride=2, padding=1)
for size in [32, 64]:
y = conv(torch.zeros(2, 3, size, size))
print(f"input={size} output={tuple(y.shape)}")
print("parameters:", sum(p.numel() for p in conv.parameters()))代码解析
解析始终位于完整代码下方,并按实际代码段逐项对应。
输入数据与任务
使用完整构造输入核对同一卷积处理两种图像大小,输出只表示本例计算。
y- 目标标签或连续目标值。
Step 1 · 1–7 行
导入当前步骤需要的数值计算、预处理、模型或评价工具。依赖集中写在代码开头,便于复现。
import torch
from torch import nn
conv = nn.Conv2d(3, 8, 3, stride=2, padding=1)
for size in [32, 64]:
y = conv(torch.zeros(2, 3, size, size))
print(f"input={size} output={tuple(y.shape)}")
print("parameters:", sum(p.numel() for p in conv.parameters()))预期输出或运行结果
input=32 output=(2, 8, 16, 16) input=64 output=(2, 8, 32, 32) parameters: 224
常见错误 · 5 条
- 通道不衔接
- stride 只凭直觉
- Flatten 算错
- 忽略尾部池化
- 确认样本轴、特征轴以及 X 与 y 的第一维完全对应。
实际应用
- 训练前验证网络结构
- 比较分辨率变化的资源成本
常见错误
- 通道不衔接
- stride 只凭直觉
- Flatten 算错
- 忽略尾部池化
常见问题
为什么 Flatten 后容易出现 Linear 维度错误?
in_features 必须等于实际通道×高×宽。任何池化、步长或输入分辨率变化都会改变这个乘积,需重新核对或使用自适应池化。
这个示例能说明什么边界?
参数统计不能替代速度、显存或泛化能力评估。
推荐学习资料
参考库不会生成虚假资源或无效外部链接。