目录

网络中的网络(NiN)

NiN的应用

1*1卷积层和全连接层的对比

为啥除了主卷积层 还要加入NIN卷积层

1. 增强非线性表达能力

2. 跨通道信息交互

3. 替代全连接层,减少参数

4. NiN 块的直观理解

5. 实验验证:1×1 卷积的效果

6. 与现代网络的联系

总结

为啥主卷积层第一层stride=4?其他的都为stride=1

1. 第一层:11×11 卷积 + stride=4—— 快速捕获全局特征并降维

2. 第二层:5×5 卷积 + stride=1—— 聚焦局部特征细化

3. 第三层:3×3 卷积 + stride=1—— 提取更精细的局部特征

4. 第四层:3×3 卷积 + stride=1—— 映射到类别空间

总结:参数设计的底层逻辑

完整代码

代码解析

主卷积层与 NiN 卷积层说明:

主卷积层:

NiN 卷积层:

 网络中的主卷积层具体参数:

实验结果


网络中的网络(NiN)

针对 “全连接层易丢失空间结构” 的问题,提出了全新的特征处理思路:用 “像素级多层感知机(1x1 卷积)” 替代全连接层在通道上的处理,保留空间特征的结构信息。

 
  • 核心创新:1x1 卷积与全局平均池化

    • 1x1 卷积(像素级 MLP)
      传统 CNN 中,卷积层提取空间特征后,需通过全连接层 “扁平化” 处理(丢失空间维度)。NiN 在每个卷积层后插入 1x1 卷积层(等价于在每个像素的通道维度上应用多层感知机):1x1 卷积核不改变空间尺寸(高、宽),仅对通道维度进行非线性变换(如输入通道数为 C,1x1 卷积可将其映射到新的通道数,实现通道级特征融合),既保留空间结构,又完成特征的非线性处理。
    • 全局平均池化(替代全连接层)
      传统全连接层参数多且易过拟合。NiN 在最后一层卷积后使用 “全局平均池化”:对每个通道的所有像素取平均值,直接得到与类别数相等的通道数(如 10 类分类任务,输出 10 个通道的平均值),既减少参数,又保持了通道与类别的对应关系。
  • 与前序模型的差异
    打破了 “卷积 + 汇聚→全连接” 的固定模式,通过 1x1 卷积在保持空间结构的前提下处理通道特征,避免了早期全连接层对空间信息的破坏,为后续 CNN(如 GoogLeNet)的 “多尺度特征融合” 提供了思路。

NiN的应用

1*1卷积层和全连接层的对比

特性1×1 卷积全连接层
参数共享是(同一卷积核应用于所有位置)否(每个神经元参数独立)
空间信息保留是(保持特征图尺寸)否(需展平为向量)
计算效率高(可并行计算)低(需逐像素计算)
应用场景特征融合、降维 / 升维分类任务的最后几层

为啥除了主卷积层 还要加入NIN卷积层

在 NiN 网络中,除了主卷积层(如 11×11、5×5 卷积)外,还添加两个 1×1 卷积层(NiN 卷积层)的主要目的是增强网络的非线性表达能力跨通道信息交互,同时减少参数数量。以下是详细解释:

1. 增强非线性表达能力

传统 CNN 中,卷积层后接 ReLU 激活函数引入非线性,但这种非线性仅在单个通道内生效。NiN 通过堆叠两个 1×1 卷积层 + ReLU,实现了跨通道的非线性变换

 
  • 单个卷积层:仅对空间局部区域进行线性变换,不同通道间缺乏交互。
  • 1×1 卷积层:将同一位置的不同通道值进行加权求和(线性组合),再通过 ReLU 引入非线性。多个 1×1 卷积层堆叠后,可学习更复杂的特征组合。
 

示例
假设主卷积层输出 96 个通道的特征图,第一个 1×1 卷积层可将这 96 个通道的信息整合为新的特征表示,第二个 1×1 卷积层进一步变换,形成更抽象的特征。

2. 跨通道信息交互

1×1 卷积的核心作用是在不改变空间尺寸的情况下,实现不同通道间的信息融合

  • 传统卷积(如 3×3、5×5):主要捕获空间局部信息,通道间交互依赖后续层。
  • 1×1 卷积:直接对同一位置的所有通道进行线性组合,相当于对每个像素点进行 “全连接” 操作。

数学表达
对于输入特征图 X[i,j,c](位置 (i,j) 的第 c 个通道),1×1 卷积的输出为:

Y[i,j,k] = ReLU(∑_{c=0}^{C_in-1} W[k,c] × X[i,j,c] + b[k])
 

其中,每个输出通道 k 是所有输入通道的加权和,再通过 ReLU 激活。

3. 替代全连接层,减少参数

传统 CNN 在特征提取后使用全连接层进行分类,存在两个问题:

  1. 空间信息丢失:需将特征图展平为向量。
  2. 参数过多:全连接层参数密集,易过拟合。

NiN 的改进:

  • 1×1 卷积 + 全局平均池化替代全连接层:
    • 1×1 卷积直接在特征图上操作,保持空间结构。
    • 全局平均池化将每个通道的特征图压缩为一个标量,大幅减少参数。

参数对比
假设输入为 5×5×384 的特征图,输出 10 个类别:

  • 全连接层:参数数量 = 5×5×384×10 + 10 = 96,010
  • NiN 方式
    1. 1×1 卷积(384→10):参数数量 = 1×1×384×10 + 10 = 3,850
    2. 全局平均池化:无参数
      总参数减少约 96%!

4. NiN 块的直观理解

NiN 块的结构可类比为 “微型多层感知机(MLP)” 作用于每个空间位置:

  • 主卷积层(如 11×11):捕获空间局部特征。
  • 第一个 1×1 卷积层:对每个像素点的通道进行第一次非线性变换(相当于 MLP 的隐藏层)。
  • 第二个 1×1 卷积层:进行第二次非线性变换(相当于 MLP 的输出层)。

这种结构使网络能够学习更复杂的特征交互,同时保持卷积的平移不变性。

5. 实验验证:1×1 卷积的效果

Hinton 在 NiN 论文中通过实验证明,添加 1×1 卷积层可显著提升模型性能:

  • 基准模型:仅使用主卷积层 + 池化层,Top-1 准确率为 69.8%。
  • 添加 1×1 卷积:准确率提升至 73.9%。
  • 进一步添加全局平均池化:准确率提升至 74.8%,同时参数减少 90% 以上。

6. 与现代网络的联系

NiN 的 1×1 卷积思想被后续网络广泛采用:

  • GoogLeNet(Inception 模块):使用 1×1 卷积进行降维,减少计算量。
  • ResNet(残差块):使用 1×1 卷积调整通道数,实现残差连接。
  • MobileNetShuffleNet:使用深度可分离卷积(包含 1×1 卷积)大幅减少参数。

总结

在主卷积层后添加 1×1 卷积层的核心目的是:

  1. 增强非线性:通过跨通道的非线性变换学习更复杂的特征。
  2. 减少参数:替代全连接层,降低模型复杂度。
  3. 提高泛化能力:通过全局平均池化和 1×1 卷积,减少过拟合风险。

为啥主卷积层第一层stride=4?其他的都为stride=1

NiN 网络中卷积层的kernel_sizestride参数设置(第一层 11×11+stride=4,后续层逐步减小卷积核并固定 stride=1),是为了适配特征提取的层级需求:从全局到局部、从粗糙到精细,同时平衡计算效率。以下是具体原因:

1. 第一层:11×11 卷积 + stride=4—— 快速捕获全局特征并降维

在网络最浅层,优先捕获图像的全局结构信息(如衣物的整体轮廓、大致形状),同时通过大步长快速降低特征图尺寸,减少后续计算量。

  • 大卷积核(11×11)的作用
    输入图像为 224×224(Fashion-MNIST resize 后),11×11 的大卷积核可以覆盖更大的空间范围,直接捕捉全局特征(例如 “裙子的整体轮廓”“外套的大致版型”)。如果用小卷积核(如 3×3),需要多层堆叠才能覆盖相同范围,会增加计算量。

  • 大步长(stride=4)的作用
    计算公式:输出尺寸 = (输入尺寸 - kernel_size) / stride + 1
    对于 224×224 输入:(224 - 11) / 4 + 1 ≈ 54,输出特征图尺寸从 224×224 压缩到 54×54,直接减少 76% 的空间尺寸
    这么做的原因是:

    • 浅层特征图的 “空间冗余度高”(相邻像素信息相似),大步长可以高效去除冗余,降低后续层的计算压力;
    • 全局特征不需要过高的空间分辨率(54×54 足够保留整体结构),过度保留反而会增加无效计算。

2. 第二层:5×5 卷积 + stride=1—— 聚焦局部特征细化

在第一层全局特征的基础上,进一步提取中等尺度的局部特征(如衣物的边缘、纹理走向),同时不再大幅降维,保留细节信息。

  • 中等卷积核(5×5)的作用
    经过第一层降维后,特征图尺寸为 54×54,此时需要关注比全局更精细的特征(例如 “衣领的形状”“袖口的边缘”)。5×5 卷积核的覆盖范围(比 11×11 小)更适合捕捉这类局部特征,同时避免因卷积核过大导致的特征模糊。

  • 固定步长(stride=1)的作用
    配合padding=2(54 - 5 + 2×2)/1 + 1 = 54),输出特征图尺寸保持 54×54 不变。
    原因是:此时特征图已经足够小(54×54),不需要再通过大步长降维;相反,需要保留足够的空间分辨率,让局部特征(如边缘、纹理)的位置信息不丢失,为后续更精细的提取做准备。

3. 第三层:3×3 卷积 + stride=1—— 提取更精细的局部特征

在全局和中等局部特征的基础上,进一步捕捉细微特征(如布料的纹理细节、图案花纹)。

  • 小卷积核(3×3)的作用
    经过第二层池化后,特征图尺寸降至 26×26(54→26),此时需要更精细的特征(例如 “毛衣的针织纹理”“裤子的缝线”)。3×3 是最小的有效卷积核(1×1 无法捕捉空间相关性),能够精准提取相邻像素的局部关联,是捕捉细微特征的最优选择。

  • stride=1 的必要性
    配合padding=1(26 - 3 + 2×1)/1 + 1 = 26),输出尺寸保持 26×26。此时特征图已经很小,且细微特征对空间位置敏感(例如纹理的走向),必须用 stride=1 避免位置信息丢失。

4. 第四层:3×3 卷积 + stride=1—— 映射到类别空间

将前面提取的所有特征(全局→局部→精细)映射到 10 个类别通道(对应 Fashion-MNIST 的 10 类衣物),为最终分类做准备。

  • 为什么仍用 3×3+stride=1
    经过第三层池化后,特征图尺寸为 12×12(26→12),此时的核心任务是将特征与类别关联(例如 “针织纹理→毛衣”“缝线细节→裤子”)。3×3 卷积可以在不破坏特征空间结构的前提下,将 384 个特征通道映射到 10 个类别通道;stride=1 配合padding=1保持尺寸不变(12×12),确保每个类别通道能完整保留前面的特征信息,最后通过自适应池化压缩为 1×1 即可得到类别得分。

总结:参数设计的底层逻辑

NiN 的卷积层参数设置遵循 特征提取的层级规律

  • 浅层(第一层):用大卷积核 + 大步长,优先捕获全局结构,快速降维以提高效率;
  • 深层(第二、三、四层):用小卷积核 + 小步长,逐步聚焦局部细节,保留空间信息以提高特征精度。

这种设计既符合人类视觉系统的感知逻辑(先整体后局部),又平衡了计算成本与特征表达能力,是现代 CNN(如 AlexNet、VGG)的通用设计原则。

完整代码

"""
文件名: 7.3
作者: 墨尘
日期: 2025/7/13
项目名: dl_env
备注: 实现NiN(Network in Network)网络架构并在Fashion-MNIST数据集上训练
"""
import torch
from torch import nn
from d2l import torch as d2l
# 手动显示图像相关库
import matplotlib.pyplot as plt  # 绘图库
import matplotlib.text as text  # 用于修改文本绘制(解决符号显示问题)


# -------------------------- 核心解决方案:解决文本显示问题 --------------------------
# 定义替换函数:将Unicode减号(U+2212,可能导致显示异常)替换为普通减号(-)
def replace_minus(s):
    if isinstance(s, str):  # 判断输入是否为字符串
        return s.replace('\u2212', '-')  # 替换特殊减号为普通减号
    return s  # 非字符串直接返回

# 重写matplotlib的Text类的set_text方法,解决减号显示异常
original_set_text = text.Text.set_text  # 保存原始的set_text方法
def new_set_text(self, s):
    s = replace_minus(s)  # 调用替换函数处理文本中的减号
    return original_set_text(self, s)  # 调用原始方法设置文本
text.Text.set_text = new_set_text  # 应用重写后的方法


# -------------------------- 字体配置(确保中文和数学符号正常显示)--------------------------
plt.rcParams["font.family"] = ["SimHei"]  # 设置中文字体(支持中文显示)
plt.rcParams["text.usetex"] = True  # 使用LaTeX渲染文本(提升数学符号显示效果)
plt.rcParams["axes.unicode_minus"] = True  # 确保负号正确显示(避免显示为方块)
plt.rcParams["mathtext.fontset"] = "cm"  # 设置数学符号字体为Computer Modern(更美观)
d2l.plt.rcParams.update(plt.rcParams)  # 让d2l库的绘图工具继承上述字体配置


# NiN块是NiN网络的基本构建单元,由一个普通卷积层(主卷积层)和两个1x1卷积层(NiN卷积层)组成
# 1x1卷积层可以看作是对每个像素点的全连接层,增加了模型的非线性表达能力
def nin_block(in_channels, out_channels, kernel_size, strides, padding):
    return nn.Sequential(
        # 主卷积层:使用指定的kernel_size进行特征提取
        nn.Conv2d(in_channels, out_channels, kernel_size, strides, padding),
        nn.ReLU(),  # ReLU激活函数引入非线性

        # NiN卷积层1:1x1卷积,增强跨通道信息交互和非线性
        nn.Conv2d(out_channels, out_channels, kernel_size=1), nn.ReLU(),

        # NiN卷积层2:进一步增强模型的非线性表达能力
        nn.Conv2d(out_channels, out_channels, kernel_size=1), nn.ReLU())

if __name__ == '__main__':
    # 构建完整的NiN网络
    net = nn.Sequential(
        # 第一个NiN块,使用较大的11x11主卷积核捕捉全局特征
        nin_block(1, 96, kernel_size=11, strides=4, padding=0),  # 主卷积层:11x11
        nn.MaxPool2d(3, stride=2),  # 最大池化层,降低特征图尺寸

        # 第二个NiN块,增加通道数到256
        nin_block(96, 256, kernel_size=5, strides=1, padding=2),  # 主卷积层:5x5
        nn.MaxPool2d(3, stride=2),  # 第二次降采样

        # 第三个NiN块,通道数增加到384
        nin_block(256, 384, kernel_size=3, strides=1, padding=1),  # 主卷积层:3x3
        nn.MaxPool2d(3, stride=2),  # 第三次降采样

        # 随机丢弃 50% 的神经元,防止过拟合
        nn.Dropout(0.5),  # Dropout层,防止过拟合

        # 最后一个NiN块,将通道数映射为类别数10
        nin_block(384, 10, kernel_size=3, strides=1, padding=1),  # 主卷积层:3x3

        # 自适应平均池化,将特征图大小调整为1x1
        nn.AdaptiveAvgPool2d((1, 1)),
        # 将四维的输出(B, C, 1, 1)转成二维的输出(B, 10)
        nn.Flatten())

    # 测试网络结构,打印每一层的输出形状
    X = torch.rand(size=(1, 1, 224, 224))
    for layer in net:
        X = layer(X)
        print(layer.__class__.__name__, 'output shape:\t', X.shape)

    # 设置训练超参数
    lr, num_epochs, batch_size = 0.1, 10, 128
    # 加载Fashion-MNIST数据集,调整图像大小为224x224以适应网络输入
    train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size, resize=224)
    # 使用GPU进行训练,如果可用的话
    d2l.train_ch6(net, train_iter, test_iter, num_epochs, lr, d2l.try_gpu())
    plt.show(block=True)  # block=True:保持图像窗口打开,直到手动关闭

代码解析

主卷积层与 NiN 卷积层说明:

  1. 主卷积层
    • 每个nin_block中的第一个卷积层(即nn.Conv2d
    • 使用指定的 kernel_size(11x11、5x5 或 3x3)
    • 负责提取空间特征并调整通道数
  2. NiN 卷积层
    • 每个nin_block中的后两个卷积层
    • 固定使用 1x1 卷积核
    • 负责跨通道信息融合和增强非线性表达能力
  3.  网络中的主卷积层具体参数:
    • 第一层:11x11,stride=4(捕获全局特征)
    • 第二层:5x5,stride=1(提取局部特征)
    • 第三层:3x3,stride=1(提取更精细特征)
    • 第四层:3x3,stride=1(映射到类别空间)
 

这种结构设计使得网络能够:

  • 通过主卷积层捕获空间特征
  • 通过 NiN 卷积层增强特征表达能力
  • 整体上比传统 CNN 使用更少的参数实现更好的性能

实验结果

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐