在编写深度学习模型的时候,有时候难免需要一些底层的函数,pytorch提供了大量的封装,本手册提供常用函数用法和参数解释。
1.torch.nn.Flatten
torch.nn.Flatten 的核心功能非常简单:将一个连续范围内的维度展平(flatten)成一个维度。
想象一下你有一张多层的、有高度和宽度的“数据饼”(比如一张彩色图片的数据),Flatten 的作用就是把它“压”成一条长长的“数据面条”。
Example
:Flatten 层的作用就是在这两者之间架起一座桥梁,它负责将 (N, C, H, W) 形状的张量转换为 (N, C * H * W) 的形状,这样就可以无缝地送入全连接层了。
parameters
:
- start_dim (int): 开始展平的维度(包含该维度)。默认值为 1。
- end_dim (int): 结束展平的维度(包含该维度)。默认值为 -1。

代码实例:
import torch
from torch import nn
x = torch.randint(low=0, high=10, size=(1, 3, 4, 4))
print(x)
flatten = nn.Flatten()
y = flatten(x)
print(y)
输出:
tensor([[[[0, 9, 3, 4],
[6, 4, 0, 7],
[9, 5, 6, 8],
[3, 7, 1, 9]],
[[7, 8, 0, 8],
[0, 0, 2, 5],
[2, 6, 3, 5],
[3, 3, 3, 8]],
[[1, 9, 8, 4],
[1, 1, 9, 4],
[7, 0, 0, 3],
[4, 2, 4, 7]]]])
tensor([[0, 9, 3, 4, 6, 4, 0, 7, 9, 5, 6, 8, 3, 7, 1, 9, 7, 8, 0, 8, 0, 0, 2, 5,
2, 6, 3, 5, 3, 3, 3, 8, 1, 9, 8, 4, 1, 1, 9, 4, 7, 0, 0, 3, 4, 2, 4, 7]])
从代码运行可以观察到展开的顺序是从start_dim开始,然后逐行追加,直到一个通道的展开完后,再沿着第二个通道展开。
2.torch.nn.Conv2d
其函数为:torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode='zeros', device=None, dtype=None)
可以通过以下网页测试输出:https://www.jamesblog.top/c/con
参数解释
in_channels (int)
: 输入数据的通道数。
对于第一层卷积,如果是 RGB 图像,in_channels 就是 3。
对于后续层,in_channels 是上一层输出的通道数(即 out_channels)。
out_channels (int)
: 输出数据的通道数。
这个值等于卷积核的数量。每个卷积核都会生成一个输出通道(特征图)。
out_channels 决定了卷积层提取特征的种类数量。
kernel_size (int or tuple)
: 卷积核的尺寸。
如果是一个整数 k,表示卷积核大小为 k x k。
如果是一个元组 (h, w),表示卷积核大小为 h x w。
常用的有 3x3 (kernel_size=3) 和 5x5 (kernel_size=5)。
stride (int or tuple, optional)
: 卷积核滑动的步幅。默认为 1。stride=1 表示每次向右或向下移动 1 个像素。stride=2 表示每次移动 2 个像素,这会使得输出特征图的尺寸减半(降采样)。
padding (int or tuple, optional)
: 在输入数据的边界进行填充。默认为 0。在输入图像的周围填充指定数量的 0(或其他值)。
卷积算子公式
- 核心数学运算:互相关(Cross-correlation)
严格来说,深度学习中的“卷积”操作在数学上是互相关(Cross-correlation)。真正的卷积需要将卷积核翻转180度。但由于卷积核的参数是学习得到的,翻转与否并不影响模型的学习能力,因此库都采用计算更简单的互相关。
假设:
- 输入特征图为 I (尺寸 H x W)
- 卷积核为 K (尺寸 kh x kw)
- 输出特征图为 O (尺寸 Hout x Wout)
输出特征图上 (i,j) 位置的值 O[i,j] 的计算公式为:
O[i,j]=(m=0∑kh−1n=0∑kw−1I[i+m,j+n]⋅K[m,n])+b
- 考虑多通道(Multi-channel)
这是实际情况。假设:
- 输入 I 有 Cin 个通道,表示为 I[c,h,w]
- 卷积核 K 也有 Cin 个通道,其尺寸为 (Cin,kh,kw)
- 输出 O 的一个通道由一个完整的 Cin 通道的卷积核生成。
为了生成输出特征图的一个通道,我们需要一个 (Cin,kh,kw) 的卷积核。计算过程是:将卷积核的每个通道与输入的对应通道进行二维互相关
,然后将 Cin 个结果逐点相加,最后加上一个偏置项 b
假设我们有 Cout 个这样的卷积核(K0,K1,...,KCout−1),就能得到 Cout 个输出通道。
第 k 个输出通道 Ok 上 (i,j) 位置的值为:
Ok[i,j]=(c=0∑Cm−1m=0∑kh−1n=0∑kw−1I[c,i+m,j+n]⋅Kk[c,m,n])+bk
- k 是输出通道的索引 (0 到 Cout−1)。
- c 是输入通道的索引 (0 到 Cin−1)。
- Kk 是第 k 个卷积核(一个 3D 张量)。
- bk 是对应第 k 个输出通道的偏置项。
至于输入和输出的尺寸计算方式如下:
Hout=⌊stride[0]Hin+2×padding[0]−dilation[0]×(kernel_size[0]−1)−1+1⌋
Wout=⌊stride[1]Win+2×padding[1]−dilation[1]×(kernel_size[1]−1)−1+1⌋
- ⌊ ... ⌋ 表示向下取整。
- padding[0], dilation[0], kernel_size[0], stride[0] 分别是高度维度的参数。
- padding[1], dilation[1], kernel_size[1], stride[1] 分别是宽度维度的参数。
3. torch.nn.BatchNorm2d
在训练深度网络时,每一层的输入分布会随着前一层参数的更新而不断变化,这种现象称为内部协变量偏移。这要求后续层需要不断地去适应新的分布,从而降低了训练速度,并使得训练深层次网络变得困难。
批量归一化通过对每个小批量(mini-batch)的数据进行归一化,将其强制转换为具有稳定均值和方差的分布,从而解决了这个问题。
nn.BatchNorm2d 的输入与输出
nn.BatchNorm2d 是专门为2D卷积层的4D输入输出数据设计的。
输入张量形状: (N, C, H, W)
- N: Batch Size(一个批次中的样本数量)
- C: Channels(通道数)
- H: Height(高度)
- W: Width(宽度)
输出张量形状: (N, C, H, W) (与输入形状相同)
它的核心操作是:沿着 N(batch),H(高度),W(宽度)维度计算统计量,而对每个通道 C 单独进行归一化。这意味着每个通道都有自己独立的均值和方差估计,以及自己独立的可学习参数。
对于给定的一个批次输入 x,BatchNorm2d 对每一个通道 c 执行以下计算步骤:
第一步:计算当前小批量的均值和方差
对于一个特定的通道 c,我们从整个批次的所有样本和该样本的所有空间位置(H x W)中提取值。
μc=N×H×W1n=1∑Nh=1∑Hw=1∑Wxn,c,h,w
σc2=N×H×W1n=1∑Nh=1∑Hw=1∑W(xn,c,h,w−μc)2
第二步:归一化
使用第一步计算出的均值和方差,对该通道 c 上的所有值进行归一化,使其近似服从均值为 0、方差为 1 的标准正态分布。
x^n,c,h,w=σc2+ϵxn,c,h,w−μc
其中ϵ 是一个极小的常数(例如 1e-5),目的是防止分母为零,增加数值稳定性。
第三步:缩放和偏移(仿射变换)
仅仅进行标准化会改变层的表示能力。例如,对于 Sigmoid 激活函数,我们希望其输入不仅集中在 0 附近。因此,BN 引入了两个可学习的参数 γc(gamma,缩放)和 βc(beta,偏移),对标准化后的值进行线性变换。
yn,c,h,w=γc⋅x^n,c,h,w+βc
γc 和 βc 是长度为 C(通道数)的向量,每个通道一对。
在训练开始时,γ 通常初始化为 1,β 初始化为 0。
通过训练,网络可以学习到最适合数据的分布均值和方差。例如,如果网络认为原始分布更好,它可以通过学习将 γ 设置为原始的标准差,将 β 设置为原始的均值,从而“抵消”归一化的效果。