news 2026/9/18 6:48:04

卷积神经网络特征图尺寸计算:公式推导与 LeNet-5 实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
卷积神经网络特征图尺寸计算:公式推导与 LeNet-5 实战

把 LeNet-5 的结构图摊在桌上,一层一层往下推特征图尺寸:输入 32×32,第一层 5×5 卷积核、步长 1、不加填充,输出 28×28;接着 2×2 池化,输出 14×14……这种"手推"看着很基础,但卷积神经网络里绝大多数"张量维度对不上""skip connection 相加失败""全连接层输入特征数算错"的报错,根子都在这几步计算上。特征图大小计算这件事,说穿了只有一个公式,但它牵扯到卷积、池化、空洞卷积、转置卷积等一整套层的尺寸规则,还连锁影响感受野、参数量、显存占用和计算量。这篇内容就是把这套规则从头讲透:公式怎么来的、边界情况怎么处理、3D 卷积和图卷积为什么不能照搬、以及在真实项目里怎么用几行代码把自己的手算结果验证一遍。不管你是刚看完 CNN 基本结构图、准备复现 LeNet-5 的新手,还是已经在调 ResNet 变体、经常被尺寸问题绊住的老手,都能从里面找到能直接抄走的做法。

1. 别急着背公式,先搞清楚它是怎么数出来的

1.1 一次维度报错引出的核心问题

我印象最深的一次排查,是帮同事看一个残差网络训练不起来的报错。日志只给了一句张量尺寸不匹配,两个特征图的通道和空间尺寸都对不上,加法做不了。翻了半天代码,问题出在一个 3×3、步长 2 的卷积上——同事默认输出尺寸会整除到整数,但实际上输入是 27×27,除以 2 之后向下取整,输出变成了 13×13,和另一条分支的尺寸差了 1。改成步长 1 加池化,或者把输入补到偶数,问题立刻消失。

这类问题的本质是:卷积和池化的输出尺寸不是连续可分的,它必须取整。取整方向、取整后丢掉的那部分像素去了哪里、下一层还能不能对上,这些都得算清楚。所以特征图大小计算不是一个"考试知识点",而是排查网络结构问题的第一把螺丝刀。你只要能把每一层的输入输出尺寸写成一列,绝大多数结构 bug 在三分钟内就能定位。

1.2 用"能放几次"的思路把公式数出来

很多人记公式是靠背,但背下来的东西一旦遇到空洞卷积或者转置卷积就失效了。我更推荐从"滑窗能放几次"的角度去理解。

假设一维输入长度是 $L$,卷积核长度是 $k$,步长是 $s$,两侧各补 $p$ 个位置。补完之后总长度变成 $L + 2p$。卷积核第一次覆盖的位置起始于第 1 个点,之后每次向右移动 $s$ 个位置。那么卷积核的起始位置最多能取到哪里?最后一个合法的起始位置必须满足"核的右端不超过补零后的总长度",也就是起始位置 $i$ 要满足 $i + k - 1 \le L + 2p$。

把所有合法起始位置列出来,是 $1, 1+s, 1+2s, \dots$,这是一个等差数列。设共有 $n$ 个位置,则最后一个位置是 $1 + (n-1)s$,代入约束:

$$1 + (n-1)s + k - 1 \le L + 2p$$

整理得 $(n-1)s \le L + 2p - k$,于是

$$n = \left\lfloor \frac{L + 2p - k}{s} \right\rfloor + 1$$

这就是那个大家都见过的公式。我之所以要把它推一遍,是因为推导过程里藏着两个关键信息:第一,下取整是天然的,不是人为规定的,因为不完整的滑窗位置被丢弃了;第二,决定结果的不是单独的 $p$ 或 $k$,而是 $L + 2p - k$ 这个"有效可用长度",理解这一点之后,你就能凭直觉判断"这个配置会不会丢像素"。

1.3 二维卷积为什么宽高可以分开算

二维卷积看起来复杂,但它的滑窗在高度和宽度两个方向上是独立运动的。高度方向只和输入高度、核高度、高度方向步长、高度方向填充有关,宽度方向同理,两者互不干扰。所以二维卷积的输出可以直接写成两个一维公式的乘积:

$$H_{out} = \left\lfloor \frac{H_{in} + 2p_h - k_h}{s_h} \right\rfloor + 1, \quad W_{out} = \left\lfloor \frac{W_{in} + 2p_w - k_w}{s_w} \right\rfloor + 1$$

通道维度的规则更简单:输出的通道数等于这一层卷积核的个数,和输入的通道数无关。输入通道数只影响每个卷积核的深度——一个 $3 \times 3$ 的卷积核作用在 64 通道输入上时,它实际是一个 $3 \times 3 \times 64$ 的三维张量。这个区分很重要,新手最容易把"输入通道"和"输出通道"的角色搞混,然后在算参数量的时候出错。

理解了这一点,你就能明白为什么卷积层可以接受任意尺寸的输入:只要空间尺寸满足公式能算出至少 1 的输出,网络就能跑通,这也是全卷积网络能处理不同分辨率图像的原因。

2. 不同类型层的尺寸规则,逐个拆开看

2.1 标准卷积层:填充和步长的配合套路

标准卷积层直接用上面那个公式,没什么特殊之处,但实际写代码时有几个固定套路值得记住。

当步长 $s=1$ 时,如果想让输出尺寸和输入保持一致,需要 $L + 2p - k \ge L$,也就是 $p \ge (k-1)/2$。对于奇数核,最自然的取值是 $p = (k-1)/2$:3×3 配 1,5×5 配 2,7×7 配 3。这就是所谓的same padding,也是为什么主流网络的卷积核几乎清一色用奇数尺寸——偶数核没法在两侧对称填充后保持尺寸不变,只能一边多补一个位置,平白引入不对称性。我用过的所有稳定训练的图像模型里,空间卷积核全是 3×3 或 5×5,没有例外。

当步长 $s=2$ 时,情况就不那么干净了。代入 $k=3, p=1, s=2$:

$$out = \left\lfloor \frac{L + 2 - 3}{2} \right\rfloor + 1 = \left\lfloor \frac{L-1}{2} \right\rfloor + 1 = \left\lceil \frac{L}{2} \right\rceil$$

也就是说,偶数输入会被精确减半,奇数输入会向上取整。这个特性在实现下采样时非常常用,但代价是输入尺寸的奇偶性会影响输出,网络前后两段的尺寸可能对不齐。我的做法是:只要用了 stride=2 的卷积做下采样,就保证输入特征图的高宽是偶数,从数据预处理阶段就把输入裁剪到 2 的幂次附近,能省掉后面一大堆麻烦。

提示:PyTorch 官方文档给出的卷积输出公式是 $\lfloor (H_{in} + 2p - d(k-1) - 1)/s + 1 \rfloor$,比我上面写的多了一个 dilation 项。当 $d=1$ 时两者完全等价,可以放心使用同一个记忆版本。

2.2 池化层:公式相同,但取整策略可以调

池化层的尺寸公式和卷积完全一样,因为它在数学上就是一个固定权重的滑窗操作。常用的池化配置是核 2、步长 2、不填充,代入公式:

$$out = \left\lfloor \frac{L - 2}{2} \right\rfloor + 1 = \left\lfloor \frac{L}{2} \right\rfloor$$

所以 32 变 16、28 变 14、14 变 7、7 变 3。注意最后一步,7 会变成 3 而不是 3.5,被丢掉的那一行一列像素就永久消失了。这在浅层网络里没什么感觉,但在做逐像素分割或者需要恢复分辨率的任务里,丢掉的位置信息会让上采样后的边缘对不上。我见过不少分割模型在验证集上边缘一直糊,最后查出来是下采样路径用奇数尺寸输入,四次池化之后尺寸和上采样路径错开了一个像素,靠插值硬凑回去的。

PyTorch 的池化层提供了一个ceil_mode参数,设为 True 时会向上取整,公式变成 $\lceil (L-k)/s \rceil + 1$。什么时候该用它?当你希望输出尺寸尽量大、不想丢边界像素的时候。什么时候不该用?当你的下采样路径和上采样路径必须严格对称的时候,向上取整会让尺寸变化不再单调可预测,反而更难对齐。我的经验是:默认用向下取整,把输入尺寸调成能被整除的数值,是最省心的方案。

2.3 空洞卷积和转置卷积:公式要改两个地方

空洞卷积的引入是为了在不增加参数量的前提下扩大感受野。它的做法是在卷积核的相邻元素之间插入空洞,等效核尺寸变成:

$$k_{eff} = d \times (k - 1) + 1$$

其中 $d$ 是膨胀率。3×3 的核,膨胀率为 2 时,等效核是 5×5;膨胀率为 4 时,等效核是 9×9。但参数量始终是 3×3=9 个权重,这就是它的价值所在。把等效核代回原公式:

$$out = \left\lfloor \frac{L + 2p - d(k-1) - 1}{s} \right\rfloor + 1$$

实战里踩过的坑是:为了让空洞卷积保持尺寸不变,填充量也要跟着放大。3×3、膨胀率 2 的卷积,如果还按 $p=1$ 去配,输出尺寸会缩水 2。正确的填充量是 $p = d(k-1)/2$。我在做语义分割的多尺度上下文模块时,几条并行的空洞卷积分支如果填充量不按这个规则配,输出的特征图尺寸就各不相同,最后根本没法拼接或者相加。记住一句话:膨胀率变了,填充量必须同步变化。

转置卷积(也叫反卷积,但这个名字不够准确)走的是反方向。它的作用是让输出比输入大,常见于上采样路径。公式是:

$$out = (L - 1) \times s - 2p + k + output_padding$$

这个公式之所以长得不一样,是因为它把前向卷积中"哪个位置被覆盖了几次"的过程反转了:输入中的每个点会按步长散布到输出上,散布区域重叠的部分累加。用 $L=4, s=2, p=1, k=3$ 试一下,输出是 $(4-1)\times 2 - 2 + 3 = 7$,正好是输入的两倍少 1。如果你想让输出精确等于输入的 2 倍,就需要把 $output_padding$ 设为 1,输出变成 8。

注意:转置卷积非常容易出现"棋盘格"artifacts,原因是不同输出位置的覆盖次数不均匀。规避方法一是保证 $k$ 能被 $s$ 整除(比如 4×4 核配步长 2),二是干脆用"最近邻插值 + 3×3 卷积"替代。我在最近两年的项目里几乎不再直接用转置卷积,换成插值加卷积之后,输出图像的网格感基本消失了。

2.4 3D 卷积和图卷积:不能照搬二维的思路

3D 卷积在二维公式的基础上多了一个时间或者深度维度。设三维核为 $k_t \times k_h \times k_w$,步长为 $s_t \times s_h \times s_w$,填充为 $p_t \times p_h \times p_w$,那么三个方向各自套用一维公式即可:

$$T_{out} = \left\lfloor \frac{T_{in} + 2p_t - k_t}{s_t} \right\rfloor + 1$$

以此类推。处理视频或者医学体数据时,我通常把时间维的步长单独设成 2 或者 3,空间维保持 1,这样能在保留空间分辨率的同时压缩时间维度。这里要注意的是,3D 卷积的参数量和显存占用是二维的三次方级别增长,一个 3×3×3、64 通道的 3D 卷积,参数量接近 11 万,和二维的 3×3 卷积完全不是一个量级。所以做体数据处理时,第一层往往用较大的空间核配小时间核,比如 $3\times7\times7$,控制住显存。

图卷积神经网络的"尺寸"概念和上面这些完全不是一回事,它是理解难点。图卷积里的节点数量由图的邻接结构决定,卷积操作实际上是在邻接矩阵和特征矩阵之间做乘法,节点数在传播过程中保持不变,所以不存在"滑窗滑几次"的问题。真正变化的是每个节点的特征维度,那才对应着常规卷积里的"通道数"。如果拿二维卷积的公式去套图卷积,会用错方向。图卷积里需要关心的是聚合范围——几阶邻居参与计算,以及是否引入池化来减少节点数(这需要图池化或者图粗化操作,不是简单滑窗)。

3. 手算加代码验证,把 LeNet-5 逐层走一遍

3.1 手推 LeNet-5 的每一层

理论说得再多,不如完整走一遍。LeNet-5 是结构图里出现频率最高的小网络,参数少、层数浅,非常适合练手。

原始结构约定输入是 32×32 的单通道图像,后面接 C1 卷积、S2 池化、C3 卷积、S4 池化、C5 卷积,再接两个全连接层。逐层算下来:

输入尺寸步长填充输出尺寸计算过程
输入----1×32×32-
C11×32×325×5106×28×28(32-5)/1+1=28
S26×28×282×2206×14×14(28-2)/2+1=14
C36×14×145×51016×10×10(14-5)/1+1=10
S416×10×102×22016×5×5(10-2)/2+1=5
C516×5×55×510120×1×1(5-5)/1+1=1
F6120---84全连接
输出84---10全连接

关键在于 C5 这一层:5×5 的卷积核正好和 5×5 的输入等大,输出塌缩成 1×1。这在结构上等效于全连接层,但权重共享方式不同。我第一次看论文时没意识到这一点,以为 C5 后面还有空间维度,结果算全连接层的输入特征数时多乘了一个 5×5,直接导致参数量对不上。

顺便算一下参数量,这是检验你是否真的理解通道维度的好办法。C1 的每个卷积核是 $5\times5\times1$,共 6 个,加偏置:$5\times5\times1\times6+6=156$。C3 的核是 $5\times5\times6$,共 16 个:$5\times5\times6\times16+16=2416$。C5 是 $5\times5\times16$,共 120 个:$5\times5\times16\times120+120=48120$。全连接 120 到 84 是 $120\times84+84=10164$,84 到 10 是 $84\times10+10=850$。全部加起来 61706 个参数,和公开资料里 LeNet-5 约 6 万参数的说法完全吻合。能把这串数字算到和公开值一致,说明你的尺寸和通道逻辑已经通了。

3.2 用几行代码把自己的手算结果验一遍

手算容易错,最好的习惯是写完就验证。下面这几行代码可以直接拿去用,把每一层的实际输出形状打出来:

import torch import torch.nn as nn def conv_out(size, k, s=1, p=0, d=1): """一维卷积/空洞卷积输出尺寸""" return (size + 2 * p - d * (k - 1) - 1) // s + 1 def pool_out(size, k, s, p=0, ceil_mode=False): """池化输出尺寸""" if ceil_mode: return -(-(size + 2 * p - k) // s) + 1 return (size + 2 * p - k) // s + 1 class LeNet5(nn.Module): def __init__(self): super().__init__() self.features = nn.Sequential( nn.Conv2d(1, 6, 5), # C1 nn.Tanh(), nn.AvgPool2d(2, 2), # S2 nn.Conv2d(6, 16, 5), # C3 nn.Tanh(), nn.AvgPool2d(2, 2), # S4 nn.Conv2d(16, 120, 5), # C5 nn.Tanh(), ) self.classifier = nn.Sequential( nn.Linear(120, 84), nn.Tanh(), nn.Linear(84, 10), ) def forward(self, x): for i, layer in enumerate(self.features): x = layer(x) print(f"layer {i:02d} {layer.__class__.__name__:12s} -> {tuple(x.shape)}") return self.classifier(x.flatten(1)) model = LeNet5() _ = model(torch.randn(1, 1, 32, 32)) # 顺便验证手算公式 assert conv_out(32, 5) == 28 assert conv_out(14, 5) == 10 assert pool_out(28, 2, 2) == 14 assert pool_out(10, 2, 2) == 5 print("手算与代码一致")

跑一遍就能看到输出依次是 6×28×28、6×14×14、16×10×10、16×5×5、120×1×1,和自己手推的表格一模一样。我更推荐用torchinfo这类工具直接总结整个模型的逐层形状、参数量和计算量,输入尺寸设成你要用的实际尺寸,一次就能看到全貌:

# pip install torchinfo from torchinfo import summary summary(LeNet5(), input_size=(1, 1, 32, 32))

实操心得:验证时输入的 batch size 一定要用真实的数值,不要用 1 蒙混过关。因为有些自定义层里写死了 batch 维度的操作(比如某些实现不规范的全连接或者自注意力的 reshape),batch=1 时恰好不报错,换到 32 就炸。我在项目里养成了一开始就用真实 batch 跑一次 shape 检查的习惯。

3.3 从目标尺寸反推填充量

实际工作中更常见的场景是反过来:我已经知道输入尺寸,也定好了输出尺寸,需要求填充量该设多少。把公式变形一下就得到:

$$p = \frac{s \times (out - 1) - L + k}{2}$$

如果算出来不是整数,说明这组配置达不到你要的输出尺寸,需要调整核、步长或者输出尺寸。举个真实例子:输入 224×224,我要用步长 2、核 3 的卷积把它降到 112×112,代入:

$$p = \frac{2 \times 111 - 224 + 3}{2} = \frac{1}{2}$$

不是整数,差一点点。这就是为什么很多网络在 stride=2 的卷积前后都会检查一下输入尺寸——224 这种"标准尺寸"看起来是 2 的倍数,但除以 2 之后变成 112,再除以 2 是 56,一路除到 7 就变成奇数了,再往下就需要配合池化或者AdaptiveAvgPool。我的处理方式是:深层特征图不要依赖逐层手算,直接在最末层用自适应平均池化指定输出尺寸,让框架自己处理剩下的取整问题。这比纠结每一层的填充量靠谱得多。代码上就是一句nn.AdaptiveAvgPool2d((1, 1)),无论输入是 7×7 还是 8×8,输出都是 1×1。

4. 尺寸算完之后,感受野和计算量怎么接着算

4.1 感受野的递推关系

特征图尺寸算清楚了,感受野就能顺着往下推。感受野的含义是输出特征图上的一个点,对应回原始输入图像上的区域有多大。

递推规则是:设到第 $n$ 层为止的感受野为 $RF_n$,累乘步长为 $S_{cum}$,那么

$$RF_n = RF_{n-1} + (k_n - 1) \times S_{cum, n-1}, \quad S_{cum, n} = S_{cum, n-1} \times s_n$$

初始时 $RF_0 = 1$,$S_{cum,0} = 1$。注意这里用的是核尺寸,如果有膨胀,要换成等效核尺寸 $d(k-1)+1$。

拿 LeNet-5 走一遍会发现一个很漂亮的结论。C1 后 $RF=5$,累乘步长 1;S2 后 $RF = 5 + 1\times1 = 6$,累乘步长变 2;C3 后 $RF = 6 + 4\times2 = 14$,累乘步长仍是 2;S4 后 $RF = 14 + 1\times2 = 16$,累乘步长变 4;C5 后 $RF = 16 + 4\times4 = 32$。最后一层输出 1×1 时感受野恰好是 32,正好等于整个输入图像的大小。这不是巧合,是网络设计者刻意安排的结果——输出层的每一个神经元都应该"看到"完整图像。这个自洽性检验非常好用:如果你设计完一个分类网络,算出来最后一层的感受野明显小于输入尺寸,说明网络根本没看全图像,性能上限就被锁死了。

相反的情况也值得警惕。我做过一个医学图像分类的任务,输入 512×512,但网络只有五层下采样,算下来感受野不到 300。模型在训练集上表现不错,验证集一直上不去,换成更深的骨干网络之后才正常。后来复盘,根本原因就是有效感受野覆盖不了病灶的完整范围。

4.2 参数量和计算量的估算方法

卷积层的参数量公式很直接:

$$Params = k_h \times k_w \times C_{in} \times C_{out} + C_{out}$$

最后那一项是偏置,如果bias=False就去掉。计算量(以乘加次数计)则是:

$$FLOPs = H_{out} \times W_{out} \times C_{out} \times k_h \times k_w \times C_{in}$$

把 LeNet-5 的三层卷积代进去看看:C1 是 $28\times28\times6\times25\times1 \approx 11.8$ 万次,C3 是 $10\times10\times16\times25\times6 = 24$ 万次,C5 是 $1\times1\times120\times25\times16 = 4.8$ 万次。总共约 40 万次乘加,放到今天连手机的零头都算不上。可就是这个小网络,在当年把手写数字识别的错误率压到了很低。

对比一下现代网络就能感受到量级差异。一个 3×3 卷积,输入输出都是 256 通道,特征图 56×56,计算量是 $56\times56\times256\times9\times256 \approx 1.85$ 亿次乘加,比整个 LeNet-5 大了四百多倍。所以当你发现显存不够的时候,优先砍的应该是特征图空间尺寸和通道数同时较大的那些层,而不是无脑减层数。

4.3 为什么 3×3 堆叠比大核更划算

这个结论值得单独说,因为它直接决定了现代网络的形态。

一个 5×5 卷积,输入输出通道都是 $C$,参数量是 $25C^2$。换成两个 3×3 卷积串联,参数量是 $2 \times 9C^2 = 18C^2$,少了将近三成;感受野是 $3 + 2 = 5$,和单个 5×5 完全一样。再往上,三个 3×3 堆叠感受野是 7,参数量 $27C^2$,而单个 7×7 要 $49C^2$,省了将近一半。

除了参数更省,堆叠还有一个更重要的好处:每两个卷积之间都夹着一层非线性激活。单个 5×5 卷积只做了一次线性变换加一次激活,而两个 3×3 做了两次,表达能力更强。这就是 VGG 之后几乎所有主流骨干网络都采用 3×3 小核堆叠的原因。

不过也有例外。在网络的浅层,尤其是第一层,输入通道数很小(1 或者 3),参数量本来就不大,这时候用 7×7 或者 5×5 的大核配上较大步长,能更快地压缩空间尺寸、扩大感受野,性价比反而更高。我自己的经验是:第一层用大核大步长做快速下采样,中间主体用 3×3 堆叠,最后一层用全局池化收尾,这个组合在大多数视觉任务上都很稳。

5. 尺寸对不上怎么办:常见问题速查

5.1 六种典型的尺寸错位原因

现象常见原因排查方法处理建议
两条分支相加报错stride=2 的卷积遇到奇数输入,取整后差 1打印两条分支的输出形状保证输入为偶数,或改用池化下采样
拼接时通道对不上把输入通道当成了输出通道检查卷积层的 out_channels记住输出通道等于卷积核个数
全连接层输入维度算错漏乘了空间尺寸,或误算 C5 为 5×5把卷积输出 shape 打印出来flatten(1)让框架自己算
空洞卷积后尺寸缩小填充量没随膨胀率同步调整检查 p 是否等于 d(k-1)/2膨胀率变了,填充必须跟着变
上采样后尺寸差 1转置卷积的 output_padding 没设反推公式验证补齐 output_padding 或用插值替代
池化后奇数尺寸丢像素默认向下取整看输入尺寸奇偶性输入调成偶数,或开 ceil_mode
推理时尺寸和训练不符用了固定尺寸的全连接层对比两个阶段的输入尺寸换自适应池化,支持动态输入

5.2 几条踩坑换来的实操经验

第一条,先写尺寸表,再写代码。我在设计任何新网络时,第一件事是在纸上(或者表格里)把每一层的输入尺寸、核、步长、输出尺寸列出来,确认最后能收敛到期望的大小,然后才开始写代码。这个习惯让我省下的调试时间,比写这张表花的时间多十倍都不止。

第二条,把形状检查当断言用。关键分支合并的地方,加一行形状断言,一旦尺寸不匹配立刻报错,而不是等到训练几个小时后才发现 loss 异常。位置成本几乎为零,收益极高。

第三条,动态尺寸输入要谨慎。如果你的部署场景需要处理不同分辨率的输入,网络里所有依赖固定尺寸的操作(固定输入的全连接层、某些自定义 reshape、位置编码)都得改。最稳妥的做法是全卷积化加全局池化,让网络对输入尺寸天然免疫。但要注意,全卷积化之后,浅层 padding 较多的卷积在边界处的计算会引入一些误差,尺寸越小这个影响越明显,所以也别把输入缩得太小。

第四条,注意框架之间的差异。同样的配置,不同框架的默认行为可能不一样。有的框架是"通道在前",有的是"通道在后",打印形状时一定要看清楚维度的顺序,否则你会把 batch 维度当成通道维度,然后困惑为什么通道数对不上。我自己就因为这个在跨框架迁移权重时白白折腾了半个下午。

第五条,不要迷信工具输出的计算量数字。不同工具对 FLOPs 的定义不一样,有的算一次乘加为 1 次,有的算 2 次;有的把激活层的开销也算进去,有的不算。做模型对比的时候,一定用同一个工具、同一个设置去测,否则数字之间没有可比性。

5.3 常用配置速查

需要保持尺寸不变时,直接查这张表:

核尺寸步长填充输出相对输入典型用途
110不变通道变换、瓶颈结构
311不变主力卷积层
512不变浅层大核
713不变网络第一层
321约减半(向上取整)下采样
220减半(向下取整)池化下采样
421精确减半转置卷积上采样

需要扩大到指定倍数时,转置卷积的配置反推一下:想让输出精确等于输入的 2 倍,$k=4, s=2, p=1$ 是最干净的组合,因为 $k$ 能被 $s$ 整除,不会产生棋盘格。3 倍上采样同理用 $k=6, s=3, p=2$。

最后分享一个我平时用得最多的检查套路:不管多复杂的网络,先在纸上把尺寸链算一遍,然后用真实 batch size 跑一次前向,把每层形状打出来逐行核对,最后再算一遍感受野确认覆盖范围。这三步做完,网络结构层面的问题基本就清零了,剩下的才轮到数据和优化器的问题。我前后带过几个新人,让他们养成这个习惯之后,卡在形状报错上的时间明显少了很多,能把精力放到真正重要的地方去。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/18 6:47:43

Vue插槽机制解析与高级应用实践

1. 理解Vue插槽的核心价值在Vue组件化开发中,插槽(Slot)机制就像是给组件预留的"接口插座"。想象你买了一个多功能台灯,灯座是固定的,但你可以根据需要更换不同的灯罩——这就是插槽的直观体现。它完美实现了组件"容器"与…

作者头像 李华
网站建设 2026/9/18 6:46:29

MiroFish:根因清单自动生成Miro鱼骨图

做质量和故障复盘的人对这一幕应该都不陌生:会议室订好了,Miro 画板开好了,六个人围着一块屏幕,主持人先在白板上画一条横线,再斜着拉出六根大骨,写上"人、机、料、法、环、测",然后大…

作者头像 李华
网站建设 2026/9/18 6:46:03

上传文件夹到GitHub:网页端与命令行实操指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/18 6:46:02

看 Claude Cowork 和聊天合并,TaoToken Key 落到调用层

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/18 6:45:29

TinyML赋能MCU:传感器从数据搬运工到边缘决策者

1. 这不是“把AI塞进MCU”的噱头,而是传感器角色的根本性重定义“当 AI 走进传感器”——这个标题乍看像一句科技媒体常用的修辞,但在我过去十年跑遍上百个工业现场、医疗设备产线和农业物联网项目的实操经验里,它指向的是一场静默却彻底的范…

作者头像 李华
网站建设 2026/9/18 6:45:14

专业专利代理的价值与八类必须委托的专利详解

1. 为什么有些专利必须找专业代理机构?作为一名在知识产权领域摸爬滚打多年的从业者,我见过太多因为专利撰写不当而导致的惨痛教训。很多企业和技术人员往往低估了专业专利代理的价值,直到在关键时刻发现专利无法发挥应有作用时才追悔莫及。专…

作者头像 李华