2025-08-24
数据处理
00

目录

1.torch.nn.Flatten
2.torch.nn.Conv2d
3. torch.nn.BatchNorm2d

在编写深度学习模型的时候,有时候难免需要一些底层的函数,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。

image.png

代码实例:

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(或其他值)。

卷积算子公式

  1. 核心数学运算:互相关(Cross-correlation) 严格来说,深度学习中的“卷积”操作在数学上是互相关(Cross-correlation)。真正的卷积需要将卷积核翻转180度。但由于卷积核的参数是学习得到的,翻转与否并不影响模型的学习能力,因此库都采用计算更简单的互相关。

假设:

  • 输入特征图为 II (尺寸 HH x WW)
  • 卷积核为 KK (尺寸 khk_h x kwk_w)
  • 输出特征图为 OO (尺寸 HoutH_{out} x WoutW_{out})

输出特征图上 (i,j)(i, j) 位置的值 O[i,j]O[i, j] 的计算公式为:

O[i,j]=(m=0kh1n=0kw1I[i+m,j+n]K[m,n])+b\begin{aligned} {O [ i , j ]} & {{}=\left( \sum_{m=0}^{k_{h}-1} \sum_{n=0}^{k_{w}-1} I [ i+m , j+n ] \cdot K [ m , n ] \right)+b} \\ \end{aligned}
  1. 考虑多通道(Multi-channel)

这是实际情况。假设:

  • 输入 IICinC_{in} 个通道,表示为 I[c,h,w]I[c, h, w]
  • 卷积核 KK 也有 CinC_{in} 个通道,其尺寸为 (Cin,kh,kw)(C_{in}, k_h, k_w)
  • 输出 OO 的一个通道由一个完整的 CinC_{in} 通道的卷积核生成。

为了生成输出特征图的一个通道,我们需要一个 (Cin,kh,kw)(C_{in}, k_h, k_w) 的卷积核。计算过程是:将卷积核的每个通道与输入的对应通道进行二维互相关,然后将 CinC_{in} 个结果逐点相加,最后加上一个偏置项 bb

假设我们有 CoutC_{out} 个这样的卷积核K0,K1,...,KCout1(K_0, K_1, ..., K_{C_{out}-1}),就能得到 CoutC_{out} 个输出通道。

kk 个输出通道 OkO_k(i,j)(i, j) 位置的值为:

Ok[i,j]=(c=0Cm1m=0kh1n=0kw1I[c,i+m,j+n]Kk[c,m,n])+bk\begin{aligned} {O_{k} [ i , j ]=\left( \sum_{c=0}^{C_{m}-1} \sum_{m=0}^{k_{h}-1} \sum_{n=0}^{k_{w}-1} I [ c , i+m , j+n ] \cdot K_{k} [ c , m , n ] \right)+b_{k}} \\ \end{aligned}
  • kk 是输出通道的索引 (0 到 Cout1C_{out}-1)。
  • cc 是输入通道的索引 (0 到 Cin1C_{in}-1)。
  • KkK_k 是第 k 个卷积核(一个 3D 张量)。
  • bkb_k 是对应第 k 个输出通道的偏置项。

至于输入和输出的尺寸计算方式如下:

Hout=Hin+2×padding[0]dilation[0]×(kernel_size[0]1)1stride[0]+1H_{o u t}=\lfloor\frac{H_{i n}+2 \times\mathrm{p a d d i n g} [ 0 ]-\mathrm{d i l a t i o n} [ 0 ] \times( \mathrm{k e r n e l \_s i z e} [ 0 ]-1 )-1} {\mathrm{s t r i d e} [ 0 ]}+1 \rfloor
Wout=Win+2×padding[1]dilation[1]×(kernel_size[1]1)1stride[1]+1W_{o u t}=\lfloor\frac{W_{i n}+2 \times\mathrm{p a d d i n g} [ 1 ]-\mathrm{d i l a t i o n} [ 1 ] \times( \mathrm{k e r n e l \_s i z e} [ 1 ]-1 )-1} {\mathrm{s t r i d e} [ 1 ]}+1 \rfloor
  • ⌊ ... ⌋ 表示向下取整。
  • 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=1N×H×Wn=1Nh=1Hw=1Wxn,c,h,w\begin{aligned} {\mu_{c}} & {{}=\frac{1} {N \times H \times W} \sum_{n=1}^{N} \sum_{h=1}^{H} \sum_{w=1}^{W} x_{n , c , h , w}} \\ \end{aligned}
σc2=1N×H×Wn=1Nh=1Hw=1W(xn,c,h,wμc)2\sigma_{c}^{2}=\frac{1} {N \times H \times W} \sum_{n=1}^{N} \sum_{h=1}^{H} \sum_{w=1}^{W} ( x_{n , c , h , w}-\mu_{c} )^{2}

第二步:归一化

使用第一步计算出的均值和方差,对该通道 c 上的所有值进行归一化,使其近似服从均值为 0、方差为 1 的标准正态分布。

x^n,c,h,w=xn,c,h,wμcσc2+ϵ\hat{x}_{n , c , h , w}=\cfrac{x_{n , c , h , w}-\mu_{c}} {\sqrt{\sigma_{c}^{2}+\epsilon}}

其中ϵ\epsilon 是一个极小的常数(例如 1e-5),目的是防止分母为零,增加数值稳定性。

第三步:缩放和偏移(仿射变换)

仅仅进行标准化会改变层的表示能力。例如,对于 Sigmoid 激活函数,我们希望其输入不仅集中在 0 附近。因此,BN 引入了两个可学习的参数 γc\gamma_c(gamma,缩放)和 βc\beta_c(beta,偏移),对标准化后的值进行线性变换。

yn,c,h,w=γcx^n,c,h,w+βc\boldsymbol{y}_{n , c , h , w}=\gamma_{c} \cdot\hat{\boldsymbol{x}}_{n , c , h , w}+\beta_{c}

γc\gamma_cβc\beta_c 是长度为 C(通道数)的向量,每个通道一对。 在训练开始时,γ\gamma 通常初始化为 1,β\beta 初始化为 0。 通过训练,网络可以学习到最适合数据的分布均值和方差。例如,如果网络认为原始分布更好,它可以通过学习将 γ\gamma 设置为原始的标准差,将 β\beta 设置为原始的均值,从而“抵消”归一化的效果。

本文作者:James

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!