想象你加入了一个学习小组。传统做法是:每个同学把笔记记在自己的本子上,上课时只看同桌(上一层)的笔记。而DenseNet的学习小组换了一种玩法——准备一本公共笔记本,每位同学学完新知识后,把自己的笔记贴进去,同时可以翻阅前面所有同学的笔记。这样一来,每个人都站在所有人肩膀上思考。 这个“公共笔记本”就是DenseNet的密集连接设计:网络中的每一层都能读取之前所有层的输出,把大家的知识拼在一起再继续学习。因为信息被反复共享和重用,网络不需要每层都从头学习一遍已有特征,参数自然更少;也因为每一层都和前面的层直接相连,训练时“传话”的路径大大缩短,梯度不容易消失。今天,我们就跟着这本公共笔记本,走进DenseNet的世界。
掌握DenseNet之后,你能在设计CNN架构时理解“特征重用”与“紧凑连接”的设计哲学,为图像分类、分割、超分等任务搭建参数更少、梯度更稳的高效模型——这是计算机视觉工程师的核心竞争力之一。
目录
可视化演示
展示除留余数法哈希构建与线性探测解决冲突的完整过程,支持插入与查找模式切换,逐步观察探测路径。
本节配有交互动效(进入视口后自动加载,约 3KB)。
除留余数法哈希构建 哈希函数 h(key)=key mod 8 将键映射到0-7号槽位 冲突时采用线性探测,依次检查下一个槽位 h(key) = key mod m 负载因子 α=n/m 衡量表填充程度
密集连接:公共笔记本的诞生
学习小组决定改革:不再各记各的,而是放一本公共笔记本在桌上。每位同学学完新内容后,先把前面所有同学的笔记从头到尾看一遍,再把自己的心得贴上去。这样一来,每个人动笔前都站在全组的肩膀上。DenseNet的设计者黄高博士正是这样想的:传统网络中,信息像流水线一样逐层传递,每一层只能看到前一层的输出,就像流水线上每个工人只瞧得见上一个工位传来的零件。
DenseNet打破了这条“单人传递链”。它的第 $l$ 层不再只接收上一层的结果,而是把第 $0$ 层到第 $l-1$ 层的所有输出全部收集起来,在通道维度上拼接成一份“完整笔记”,再统一交给一个复合函数处理。这个拼接动作,英文叫 concatenation,是 DenseNet 与 ResNet 最根本的分水岭——ResNet 把旧笔记和新笔记“叠在一起”(相加),DenseNet 则是“活页装订”(拼接),一页都不丢。
用公式表示,第 $l$ 层的输出为:
公共笔记本的规则一旦定下,整个小组的学习方式就彻底改变了——每一页笔记都不会被遗忘,每一层都拥有全组的知识积累,这正是 DenseNet 强大表达力的源头。
- 前面所有层的输出$x_0$ 到 $x_{l-1}$ 是第 0 层到第 l-1 层各自产出的特征图。它们就像公共笔记本上每一位同学留下的笔记页,谁也不许被撕掉。
- 拼接操作方括号把所有特征图在通道维度上首尾相连,形成一份更厚的“合订本”。注意这里是拼接,不是相加——每一页都完整保留。
- 复合函数$H_l(\cdot)$ 代表第 l 层的“加工流水线”,通常由批归一化(BatchNorm)、ReLU 激活函数和卷积层串联而成。它负责从合订本中提炼出新知识。
- 第 l 层的产出$x_l$ 就是第 l 层读完合订本后写下的新笔记,它也会被贴回公共笔记本,供后面所有层阅读。
特征重用:一页笔记多人受益
公共笔记本带来一个神奇的效果:特征重用。以前每个同学都要自己从头总结“什么是边缘”“什么是纹理”,现在小明的笔记里已经写清楚了,后面的同学直接翻看引用就行,不必重复劳动。在 DenseNet 中,第 $j$ 层输出的特征图会被第 $j+1$ 层、第 $j+2$ 层……一直到最后一层反复阅读和利用。
这种设计让网络的信息流变得极其“节俭”。传统 CNN 中,每一层都试图重新学习一整套完整特征,很多特征是重复的,白白浪费参数。而 DenseNet 中,某个中间层提取到“眼角轮廓”这种特征后,它会被保留在合订本中,后续所有层都能直接看到它,不需要再学一遍。用数学语言说,对于任意 $k > j$,特征 $x_j$ 都直接出现在第 $k$ 层的输入中:
因为特征被反复重用,网络的信息传递几乎没有损耗。浅层学到的基础特征(边缘、颜色块)能一路“活到”深层;深层也能随时回头调用浅层的细节,这让最终的特征表达既丰富又细腻。从数学角度看,DenseNet 天然实现了特征零丢失:任何一层的信息都可以直接跳转到任意后续层,不存在“中间层没学好就全盘皆输”的窘境。
回到学习小组:一个同学总结的公式,全班都能受益;一个人踩过的坑,后面的人翻开笔记就知道绕开。这份共享带来的效率提升,正是 DenseNet 用更少参数达到更高精度的秘密。
- 任意后续层$\forall k > j$ 表示“所有排在第 j 层后面的层”。在公共笔记本规则下,只要你在后面写笔记,就必然读过前面的内容。
- 集合关系$\in$ 表示“属于”。$x_j$ 作为合订本中的一页,被包含在第 k 层的输入集合里,而不是像传统网络那样被“消化吸收”后消失。
梯度流动:传话游戏不再失真
你有没有玩过“传话游戏”?十个人排成一排,第一个人说一句悄悄话,挨个往后传,传到队尾时往往面目全非。传统深层网络训练时也面临同样的困境:损失函数算出的梯度(可以理解为“修改意见”)要从最后一层一层传回第一层,每传一层就打个折扣,传到浅层时信号已经微弱到几乎消失——这就是著名的梯度消失问题。
DenseNet 的公共笔记本规则意外地解决了这个难题。因为每一层都直接连接到后面的所有层,反向传播时,梯度不需要沿着“层间传递链”一路走完全程。它有点像传话游戏里,每个人可以直接对队伍最前面的同学喊话,而不是只告诉身后那一个。第 $l$ 层的输出 $x_l$ 直接参与了所有后续层的计算,因此损失对 $x_l$ 的梯度来自所有后续层的直接贡献之和:
这种多路径梯度流动带来一个额外的好处:隐式深监督(implicit deep supervision)。传统网络只有最后一层输出会计算损失,中间层“看不太到”监督信号;而 DenseNet 的中间层通过密集连接,间接接收到了来自损失函数的丰富梯度——仿佛每一层都被老师单独点评过一样,训练自然更加稳定。
可以说,DenseNet 用“全员直连”的方式,把传话游戏中的长链条切成了无数条短线。每一条短线都清晰响亮,浅层不再聋,深层不再盲,整个网络在训练中配合得天衣无缝。
- 损失对第 l 层的梯度$\frac{\partial \mathcal{L}}{\partial x_l}$ 表示损失函数 $\mathcal{L}$ 对第 l 层输出求偏导,也就是“第 l 层该往哪个方向改进”。
- 所有后续层求和$\sum_{k > l}$ 把第 l 层之后所有层回传的梯度累加在一起。每多一条路径,信号就增强一分。
- 每一层的贡献$\frac{\partial \mathcal{L}}{\partial x_k} \cdot \frac{\partial x_k}{\partial x_l}$ 表示第 k 层回传的梯度里,属于“对 x_l 的依赖”的那一部分。因为拼接让 x_k 直接依赖 x_l,这个偏导不为零,梯度就能直达。
参数效率:一本笔记走天下
你可能以为:连接这么多、信息这么全,DenseNet 的参数一定爆炸了吧?恰恰相反,DenseNet 是一台省纸机器。学习小组里,虽然公共笔记本人人可读,但每个人只需要写下自己真正的新发现,而不是把前面所有人的笔记都重抄一遍。DenseNet 中每一层只新增很少的“笔记页”——这个新增的厚度叫增长速率(growth rate),记作 $k$,通常只有 12 或 24,远小于传统网络每层动辄几百个特征图。
为什么能这么省?关键在于瓶颈层(Bottleneck)的设计。假设某层输入有 $c_{in}$ 个通道(合订本已经很厚了),如果直接用一个 3×3 卷积去处理,参数量是 $9 \times k \times c_{in}$,计算量巨大。DenseNet 的做法是:先用一个 1×1 卷积把 $c_{in}$ 压缩到 $4k$(相当于“先写摘要”),再用 3×3 卷积提炼出 $k$ 个新特征。这样参数为:
正因为每层只写“新笔记”、先摘要再提炼,DenseNet 的参数量通常只有同精度 ResNet 的一半左右,而计算量也大幅下降。在 ImageNet 这种千万级数据集上,DenseNet-201 用约 20M 参数达到了超越 ResNet-101 的精度——实践再次证明:决定模型能力的不是参数数量,而是信息的使用效率。
- 1×1 卷积的降维$4k \times c_{in}$ 是 1×1 卷积的参数量:每个输出通道(共 4k 个)都要对输入全部 c_in 个通道做加权组合。
- 3×3 卷积的提炼$36k^2$ 是 3×3 卷积的参数量:4k 个输入通道、k 个输出通道、每个卷积核 3×3=9 个权重,即 $k \times 4k \times 9 = 36k^2$。
- 无瓶颈的代价$9k \times c_{in}$ 是直接用一个 3×3 卷积把 c_in 通道变成 k 通道的参数量。对比可见,当 c_in 远大于 k 时,瓶颈结构省下了约一半参数。
瓶颈与过渡:精炼与瘦身
公共笔记本用久了会越来越厚,几千页的笔记谁也翻不动。DenseNet 的应对之策是设置两个“管理员”:瓶颈层负责精炼,过渡层负责瘦身。
前面已经见识了瓶颈层的精炼术:先用 1×1 卷积把输入通道从 $c_{in}$ 压缩到 $4k$,再经过 3×3 卷积产出 $k$ 个新特征。这样既保留了合订本中的关键信息,又没让计算量失控。
密集块(Dense Block)之后,特征图的通道数已经累积得相当可观,这时过渡层(Transition Layer)登场。它做两件事:先用 1×1 卷积把通道数乘以一个压缩因子 $\theta$(通常取 0.5,即砍掉一半冗余页),再用 2×2 平均池化把特征图的空间尺寸缩小一半。通道和空间双双瘦身,网络这才有精力继续读下一本新笔记。过渡层的输出通道数为:
如果把整个 DenseNet 比作一套丛书,密集块是“阅读+记笔记”的单元,瓶颈层是“摘抄要点”,过渡层则是“定期清理旧笔记,只留精华”。这种张弛有度的节奏让网络既博学又轻快,深而不重。
- 输入通道数$c_{in}$ 是过渡层进来时合订本的“总页数”,也就是当前所有拼接特征图的通道总和。
- 压缩因子$\theta$ 是保留比例,取值在 0 到 1 之间。$\theta = 0.5$ 表示只保留一半通道,冗余信息被丢弃。
- 向下取整$\lfloor \cdot \rfloor$ 把计算结果取为整数,因为通道数必须是整数,不能出现“半个通道”。
对比ResNet:分享vs结对
同样是解决深层网络难训练的问题,ResNet 和 DenseNet 走出了两条风格迥异的路线。用学习小组来类比:ResNet 是“结对学习”——每个同学主要参考上一个同学的笔记,把上一个同学的输出和自己的想法相加,得到一个“残差”式的进步;而 DenseNet 是“全员共享”——每个人的笔记都被完整保留,新来者拼接阅读所有人的内容。
两者的核心差异就在合并方式上。ResNet 的残差块计算 $y = \mathcal{F}(x) + x$,新特征和旧的恒等映射(identity mapping)逐元素相加,通道数必须保持一致;DenseNet 则用拼接,通道数可以自由增长,信息完全不重叠。用公式对比:
这带来两个直接后果:一是 DenseNet 无需像 ResNet 那样精心设计“恒等映射”分支(因为拼接本身就是完美的恒等传递);二是 DenseNet 的特征冗余度更低,参数效率更高。ResNet 开辟了“跳跃连接”的思路,DenseNet 则把它做到极致——度不同,但哲学一脉相承:让信息在网络中自由流动,而不是被层层加工损耗。从 ResNet 到 DenseNet,我们看到了一条清晰的技术演进路径:从“少丢信息”到“一字不丢”。
- ResNet 的求和$y = \mathcal{F}(x) + x$ 中,$\mathcal{F}(x)$ 是学习到的残差增量,$x$ 是原始输入。二者逐元素相加,信息以“叠加”方式传递。这样做的好处是梯度有一条恒等捷径,但缺点是如果 x 和 F(x) 都包含有用信息,相加可能会互相干扰。
- DenseNet 的拼接$x_l = H_l([x_0, \ldots, x_{l-1}])$ 中,所有历史特征在通道维度排列起来,互不干扰,每个后续层都能直接访问任意深度的特征。
- 信息量的差异ResNet 的容量受限于固定的通道数,DenseNet 的通道数随层数线性增长,表达空间更充裕。
AI 应用场景
医学图像分割
阶段:模型架构设计 / 特征提取
解决的问题:医学影像(如 CT、MRI)中病灶区域通常边界模糊、对比度低,传统 CNN 在层层下采样后容易丢失细小病灶的细节特征,导致分割不准。DenseNet 的特征重用机制让浅层的纹理细节一路保留到深层,分割网络能同时参考全局结构与局部细节。
具体案例:U-Net++ 等知名医学分割网络借鉴了 DenseNet 的密集连接思想——在 U 形解码器的每一层之间加入密集跳连,使梯度能直达浅层。某三甲医院用这类模型做肺结节分割,在保持精度的同时把参数从 30M 降到 15M,推理速度提升近一倍,可以在 3 秒内完成一张 CT 切片的结节筛选。
图像超分辨率与去噪
阶段:模型训练与调优
解决的问题:超分任务要求网络同时保留高频边缘和低频纹理,传统网络为了学习这些特征需要堆叠大量参数,训练时还容易梯度消失。DenseNet 的密集连接让低频信息可以“抄近路”直达输出端,高频细节则通过特征重用逐层增强。
具体案例:SRDenseNet 将 DenseNet 应用于图像超分辨率,把低分辨率图像先经卷积提取浅层特征,再送入多个密集块逐步丰富细节。在 Set5 基准上,SRDenseNet 以 2M 参数达到了比 5M 参数的 VDSR 更高的 PSNR(峰值信噪比),且训练收敛速度快了约 30%。
端侧轻量级图像分类
阶段:模型压缩与部署
解决的问题:手机、摄像头等边缘设备算力和内存有限,传统大模型无法落地。DenseNet 的参数效率让它成为“小模型高精度”的代表,特别适合不需要蒸馏就能直接部署的场景。
具体案例:某安防公司要在低成本芯片上做实时动物识别,选用 DenseNet-121 做骨干网络,配合瓶颈层和过渡层压缩,最终模型仅 7M 参数、30MB 内存占用,在 2W 功耗的边缘盒子上实现了 28fps 的推理速度,精度比同体积 MobileNet 高出 2.3 个百分点。
Python 演示
import torchimport torch.nn as nnimport torch.nn.functional as F class Bottleneck(nn.Module): def __init__(self, in_channels, growth_rate): super().__init__() self.bn1 = nn.BatchNorm2d(in_channels) self.conv1 = nn.Conv2d(in_channels, 4 * growth_rate, 1, bias=False) self.bn2 = nn.BatchNorm2d(4 * growth_rate) self.conv2 = nn.Conv2d(4 * growth_rate, growth_rate, 3, padding=1, bias=False) def forward(self, x): out = self.conv1(F.relu(self.bn1(x))) out = self.conv2(F.relu(self.bn2(out))) return torch.cat([x, out], dim=1) class Transition(nn.Module): def __init__(self, in_channels, out_channels): super().__init__() self.bn = nn.BatchNorm2d(in_channels) self.conv = nn.Conv2d(in_channels, out_channels, 1, bias=False) self.pool = nn.AvgPool2d(2) def forward(self, x): return self.pool(self.conv(F.relu(self.bn(x)))) class SimpleDenseNet(nn.Module): def __init__(self, growth_rate=12, num_classes=10): super().__init__() self.features = nn.Sequential( nn.Conv2d(1, 24, 3, padding=1, bias=False), self._make_block(24, 4, growth_rate), Transition(24 + 4 * growth_rate, 32), self._make_block(32, 4, growth_rate), Transition(32 + 4 * growth_rate, 48), nn.BatchNorm2d(48) ) self.classifier = nn.Linear(48, num_classes) def _make_block(self, in_ch, layers, growth_rate): block = [] for _ in range(layers): block.append(Bottleneck(in_ch, growth_rate)) in_ch += growth_rate return nn.Sequential(*block) def forward(self, x): out = self.features(x) out = F.adaptive_avg_pool2d(F.relu(out), 1) return self.classifier(out.view(out.size(0), -1)) def main(): model = SimpleDenseNet(growth_rate=12) x = torch.randn(8, 1, 28, 28) y = torch.randint(0, 10, (8,)) loss = F.cross_entropy(model(x), y) loss.backward() first_grad = list(model.parameters())[0].grad total = sum(p.numel() for p in model.parameters()) print(f"输出形状: {tuple(y.shape)}") print(f"参数量: {total / 1e3:.1f}K") print(f"第一层梯度已回传: {first_grad is not None}") if __name__ == "__main__": main()
out = self.conv1(F.relu(self.bn1(x)))瓶颈层第一步:先对输入做归一化和激活,再用 1×1 卷积把通道压缩到 4 倍增长速率,相当于“写摘要”。return torch.cat([x, out], dim=1)密集连接的核心:把原始输入 x 和新特征 out 在通道维度拼接,输出的通道数比输入多了 growth_rate 个。self.pool(self.conv(F.relu(self.bn(x))))过渡层:归一化、激活后先用 1×1 卷积压缩通道,再用 2×2 平均池化缩小空间尺寸。self._make_block(24, 4, growth_rate)构建含 4 个瓶颈层的密集块,每个瓶颈层都会让通道数增长 growth_rate,块结束时总通道数为 24 + 4×k。first_grad = list(model.parameters())[0].grad检查第一层卷积的梯度是否存在。DenseNet 的短路径让梯度成功回传到网络最前端。
常见误区
误区DenseNet 名字带"Dense",我以为就是把网络加宽、每层多放几个卷积核,连接方式还是像普通 CNN 一样一层接一层。
正解恰恰相反,DenseNet 的“密集”指的是连接关系的密集:第 l 层的输入是前面所有层输出的拼接,而不仅仅是上一层的输出。它不靠加宽,而靠“信息共享”取胜。用公共笔记本的比喻说,每个同学都要翻看全组所有历史笔记,而不是只看同桌的。
为何常见:“Dense“在英文里既可以形容”稠密“也可以让人联想到”厚重“,初学者很容易从字面理解成”又宽又厚的网络”。
误区公共笔记本被所有层翻阅,每层都要处理这么多输入,参数肯定比普通 CNN 多好几倍吧?GPU 跑得动吗?
正解实际上 DenseNet 的参数量远小于同等深度的传统 CNN 和 ResNet。因为每层只新增 k 个特征图(k 通常为 12 或 24),加上瓶颈层先用 1×1 卷积降维,计算量被压得很低。参数少的原因是特征重用——不需要每层都重新学习一遍已有特征。
为何常见:人们习惯用“连接数”粗略估计参数量,直觉上连接越多参数越多。但 DenseNet 的连接是“读取”而非“复制”,读取共享内容不需要额外参数。
误区反正都是把之前的特征带到后面,一个用加号一个用拼接,本质应该没区别吧?选哪个都行。
正解相加和拼接有本质区别。ResNet 的相加要求新旧特征逐元素对应,通道数必须一致,相当于“两杯水倒在一起”;DenseNet 的拼接是“活页装订”,所有历史特征页完整保留,通道数线性增长。拼接让第 l 层可以自由选择读哪些特征、忽略哪些特征,而相加则强制所有通道一起参与融合。这导致 DenseNet 的特征冗余度更低、信息丢失更少。
为何常见:从公式上看两者都包含“恒等传递”的思想,初学者容易忽略操作符(+ 与 cat)对信息流结构的根本性影响。
误区既然 k 是每层新增的特征图数量,那我把 k 从 12 调到 48,网络每层写更多笔记,参数量多一点但精度一定更高吧?
正解k 不是越大越好。k 增大会让每层输入通道数累加得更快,瓶颈层的 1×1 卷积参数和计算量线性上升,而且过大的 k 会导致特征冗余度回升,边际收益递减。实验表明 k=12 时 DenseNet 已经能达到很好的精度-参数平衡,继续增大 k 只换来微小的精度提升,却付出数倍的参数代价,还更容易过拟合。
为何常见:人们天然认为“容量越大越好”,忽视了网络设计的本质是在容量与效率之间找平衡点。DenseNet 的设计哲学就是“小步快跑,充分共享”。
面试题
Q1. DenseNet 中第 l 层的输入是什么?
- A.仅第 l-1 层的输出
- B.前面所有层输出的拼接← 正确答案
- C.第一层与第 l-1 层输出
- D.全部层输出的加权求和
答案:B。DenseNet 的核心是密集连接,第 l 层接收第 0 层到第 l-1 层全部输出的拼接。A 是普通 CNN 的做法,C 是部分连接,D 是注意力机制式的加权,都与 DenseNet 的“全员直连”不符。
Q2. DenseNet 中特征合并的具体操作是什么?
- A.按位置逐元素相加
- B.沿通道维度拼接← 正确答案
- C.取最大值合并
- D.按空间位置做平均
答案:B。DenseNet 用 torch.cat 在通道维度拼接特征。逐元素相加是 ResNet 的做法;最大值合并是 MaxOut 的思想;平均合并则类似全局平均池化,都不会保留全部特征页。
Q3. DenseNet 缓解梯度消失的主要原因是什么?
- A.梯度通过多条短路径直达浅层← 正确答案
- B.使用了更大的学习率
- C.加宽了网络每一层的通道
- D.取消了所有激活函数
答案:A。密集连接让每一层都直接参与后续所有层的计算,反向传播时梯度沿多条短路径同时回传,信号衰减被极大缓解。学习率和层宽不是架构级的解决方案,取消激活函数会损害表达能力。
Q4. 瓶颈层中 1×1 卷积的主要作用是什么?
- A.将通道降维以节约计算量← 正确答案
- B.增大特征图的空间尺寸
- C.把不同层特征做对齐
- D.直接减少网络的总层数
答案:A。瓶颈层先用 1×1 卷积把输入通道从较大的 c_in 压缩到 4k,再做 3×3 卷积,参数从 9k×c_in 降到 4k×c_in+36k²。1×1 卷积在 DenseNet 里是“摘要”工具,不改变空间尺寸,也不改变层数。
Q5. 关于 DenseNet 特征重用,下列正确的有?
- A.每层特征被后续所有层复用← 正确答案
- B.避免各层重复学习相同特征← 正确答案
- C.减少了网络对数据的依赖
- D.让每层参数数量必然相等
答案:AB。A 和 B 正是特征重用的核心含义:公共笔记本让一页笔记被多人阅读,避免重复劳动。C 属于过度延伸,特征重用并不改变数据需求;D 明显错误,不同层输入通道数不同,参数数量也不同。
Q6. 与 ResNet 相比,DenseNet 参数量更少的关键原因是什么?
- A.每层只需学习少量新增特征,无需重复学习冗余信息← 正确答案
- B.所有层共享同一套卷积核参数
- C.卷积核的尺寸被强制缩小了一半
- D.网络跳过了所有批归一化层
答案:A。ResNet 的每层都要学习成百上千个通道的残差,很多特征与浅层重复;DenseNet 每层只新增 k 个特征,且通过拼接让全部历史特征直接可见,无需重新学习。B 是权重共享(如 RNN)的思路,C 和 D 与事实不符。
Q7. DenseNet 的过渡层包含哪些操作?
- A.一个 1×1 卷积压缩通道← 正确答案
- B.一个 2×2 的平均池化层← 正确答案
- C.一个 3×3 的普通卷积层
- D.一个全连接分类器头
答案:AB。过渡层 = 1×1 卷积(压缩通道数,乘以压缩因子 θ)+ 2×2 平均池化(缩小空间尺寸)。3×3 卷积是瓶颈层内的操作,全连接分类器在网络的最后,与过渡层无关。
Q8. DenseNet 的增长速率 k 表示什么意思?
- A.每层新增的特征图数量← 正确答案
- B.网络总层数的上限
- C.输入图像的通道数量
- D.全连接层的隐藏单元数
答案:A。增长速率 k 指每个密集块内,每经过一个瓶颈层,输出特征图的通道数比输入增加 k。它决定了公共笔记本“每页写多厚”,是控制网络容量的关键超参数。
Q9. DenseNet 相比传统 CNN 的优势有哪些?
- A.梯度可以更顺畅地回传到浅层← 正确答案
- B.参数利用率显著提升← 正确答案
- C.特征被后续层反复使用← 正确答案
- D.完全不需要激活函数
答案:ABC。密集连接带来三个直接优势:短路径改善梯度流动、特征重用提升参数效率、每层特征都被后续层反复读取。D 错误,ReLU 等激活函数仍是网络表达能力的基石。
Q10. 某 DenseNet 的密集块中,当前输入通道数为 c,增长速率为 k,经过一个瓶颈层后输出通道数是多少?
- A.输出通道数变为 c 加 k← 正确答案
- B.输出通道数变为 c 减 k
- C.输出通道数保持 c 不变
- D.输出通道数变为 c 乘 k
答案:A。瓶颈层通过 torch.cat([x, out], dim=1) 将输入 x 与新生成的 k 个特征图拼接,因此输出通道数 = c + k。这正是 DenseNet“只增笔记不丢笔记”的设计——每经过一层,通道数线性增长 k。