网络中的网络(NiN)|现代卷积神经网络|动手学深度学习

22 阅读7分钟

1. 调整 NiN 的超参数,以提高分类准确性。

为了提高Network-in-Network(NiN)模型的分类准确率,可以调整以下超参数和模型组件:

  1. 增加卷积层的滤波器数量:增加每层卷积层的滤波器数量,以提高模型的容量,学习更复杂的特征。

  2. 调整卷积核大小:微调不同层的卷积核大小,以捕捉不同尺度的特征。你也可以尝试非对称的卷积核。

  3. 添加批量归一化:在每个卷积层后添加Batch Normalization层,以稳定和加速训练过程。

  4. 调整Dropout率:尝试不同的Dropout率,找到能够减少过拟合的最佳值。

  5. 学习率和优化方法:调整学习率,并考虑使用高级优化方法如Adam或学习率调度器。

  6. 数据增强:实施数据增强技术,例如随机裁剪、旋转和翻转,以提高模型的泛化能力。

  7. 增加模型深度:通过增加层数或每层的滤波器数量,尝试更深或更宽的模型。

以下是根据这些建议调整后的模型:

def nin_block(in_channels, out_channels, kernel_size, strides, padding):
    return nn.Sequential(
        nn.Conv2d(in_channels, out_channels, kernel_size, strides, padding),
        nn.BatchNorm2d(out_channels),
        nn.ReLU(),
        nn.Conv2d(out_channels, out_channels, kernel_size=1),
        nn.BatchNorm2d(out_channels),
        nn.ReLU(),
        nn.Conv2d(out_channels, out_channels, kernel_size=1),
        nn.BatchNorm2d(out_channels),
        nn.ReLU()
    )

net = nn.Sequential(
    nin_block(1, 192, kernel_size=11, strides=4, padding=0),  # 增加滤波器数量
    nn.MaxPool2d(3, stride=2),
    nin_block(192, 512, kernel_size=5, strides=1, padding=2), # 增加滤波器数量
    nn.MaxPool2d(3, stride=2),
    nin_block(512, 768, kernel_size=3, strides=1, padding=1), # 增加滤波器数量
    nn.MaxPool2d(3, stride=2),
    nn.Dropout(0.5),
    nin_block(768, 10, kernel_size=3, strides=1, padding=1),
    nn.AdaptiveAvgPool2d((1, 1)),
    nn.Flatten()
)

lr, num_epochs, batch_size = 0.1, 10, 128
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size, resize=224)
d2l.train_ch6(net, train_iter, test_iter, num_epochs, lr, d2l.try_gpu())

执行时间:10m 27.0s

loss 0.132, train acc 0.956, test acc 0.906
1046.0 examples/sec on cuda:0

image.png

额外建议:

  1. 超参数调优:使用网格搜索或随机搜索工具,系统地找到最佳超参数。
  2. 正则化:探索其他正则化技术,如L2正则化。
  3. 预训练:如果可能,在与目标数据集类似的大型数据集上预训练模型,然后进行微调。
  4. 实验不同架构:有时候,像添加残差连接(ResNet风格)的架构改进可以提高性能。

通过仔细调整这些方面,可以显著提高NiN模型在特定分类任务中的性能。

2. 为什么 NiN 块中有两个 1×11\times 1 卷积层?删除其中一个,然后观察和分析实验现象。

看结果一个卷积层效果更好,训练速度提升,准确度提升,过拟合减弱

两个 1×11 \times 1 卷积层

loss 0.339, train acc 0.875, test acc 0.854
4322.1 examples/sec on cuda:0

image.png

执行时间:5m 55.7s

loss 0.253, train acc 0.907, test acc 0.897
4299.0 examples/sec on cuda:0

image.png

一个 1×11 \times 1 卷积层

loss 0.317, train acc 0.881, test acc 0.856
5553.1 examples/sec on cuda:0

image.png

执行时间:4m 50.7s

loss 0.233, train acc 0.915, test acc 0.911
5535.0 examples/sec on cuda:0

image.png

3. 计算NiN的资源使用情况。

  1. 参数的数量是多少?
  2. 计算量是多少?
  3. 训练期间需要多少显存?
  4. 预测期间需要多少显存?

要分析你提供的Network-in-Network (NiN)模型的资源使用情况,我们需要计算参数数量、计算量以及训练和预测期间的显存需求。

参数数量计算

对于每个卷积层,参数数量的计算公式为: 参数数量=(K×K×输入通道×输出通道)+输出通道\text{参数数量} = (K \times K \times \text{输入通道} \times \text{输出通道}) + \text{输出通道} 其中 KK 是卷积核大小。

  1. 第一个nin_block (1, 96, 11, 4, 0):

    • Conv2d: (11×11×1×96)+96=11×11×1×96+96=11616(11 \times 11 \times 1 \times 96) + 96 = 11 \times 11 \times 1 \times 96 + 96 = 11616
    • Conv2d (1x1): (1×1×96×96)+96=96×96+96=9312(1 \times 1 \times 96 \times 96) + 96 = 96 \times 96 + 96 = 9312
    • Conv2d (1x1): (1×1×96×96)+96=9312(1 \times 1 \times 96 \times 96) + 96 = 9312
    • 总计: 11616+9312+9312=3024011616 + 9312 + 9312 = 30240
  2. 第二个nin_block (96, 256, 5, 1, 2):

    • Conv2d: (5×5×96×256)+256=5×5×96×256+256=614656(5 \times 5 \times 96 \times 256) + 256 = 5 \times 5 \times 96 \times 256 + 256 = 614656
    • Conv2d (1x1): (1×1×256×256)+256=256×256+256=65792(1 \times 1 \times 256 \times 256) + 256 = 256 \times 256 + 256 = 65792
    • Conv2d (1x1): (1×1×256×256)+256=65792(1 \times 1 \times 256 \times 256) + 256 = 65792
    • 总计: 614656+65792+65792=746240614656 + 65792 + 65792 = 746240
  3. 第三个nin_block (256, 384, 3, 1, 1):

    • Conv2d: (3×3×256×384)+384=3×3×256×384+384=884736(3 \times 3 \times 256 \times 384) + 384 = 3 \times 3 \times 256 \times 384 + 384 = 884736
    • Conv2d (1x1): (1×1×384×384)+384=384×384+384=147840(1 \times 1 \times 384 \times 384) + 384 = 384 \times 384 + 384 = 147840
    • Conv2d (1x1): (1×1×384×384)+384=147840(1 \times 1 \times 384 \times 384) + 384 = 147840
    • 总计: 884736+147840+147840=1180416884736 + 147840 + 147840 = 1180416
  4. 第四个nin_block (384, 10, 3, 1, 1):

    • Conv2d: (3×3×384×10)+10=3×3×384×10+10=34570(3 \times 3 \times 384 \times 10) + 10 = 3 \times 3 \times 384 \times 10 + 10 = 34570
    • Conv2d (1x1): (1×1×10×10)+10=10×10+10=110(1 \times 1 \times 10 \times 10) + 10 = 10 \times 10 + 10 = 110
    • Conv2d (1x1): (1×1×10×10)+10=110(1 \times 1 \times 10 \times 10) + 10 = 110
    • 总计: 34570+110+110=3479034570 + 110 + 110 = 34790

总参数数量: 30240+746240+1180416+34790=199068630240 + 746240 + 1180416 + 34790 = 1990686

计算量(FLOPs)

每个卷积层的FLOPs计算公式为: FLOPs=2×K×K×输入通道×输出通道×输出宽度×输出高度\text{FLOPs} = 2 \times K \times K \times \text{输入通道} \times \text{输出通道} \times \text{输出宽度} \times \text{输出高度}

假设输入图像大小为224x224。

  1. 第一个nin_block (1, 96, 11, 4, 0):

    • Conv2d (11x11): 输出大小 = 54x54,FLOPs = 2×11×11×1×96×54×542 \times 11 \times 11 \times 1 \times 96 \times 54 \times 54
    • Conv2d (1x1): 输出大小 = 54x54,FLOPs = 2×1×1×96×96×54×542 \times 1 \times 1 \times 96 \times 96 \times 54 \times 54
    • Conv2d (1x1): 输出大小 = 54x54,FLOPs = 2×1×1×96×96×54×542 \times 1 \times 1 \times 96 \times 96 \times 54 \times 54
  2. 第二个nin_block (96, 256, 5, 1, 2):

    • Conv2d (5x5): 输出大小 = 27x27,FLOPs = 2×5×5×96×256×27×272 \times 5 \times 5 \times 96 \times 256 \times 27 \times 27
    • Conv2d (1x1): 输出大小 = 27x27,FLOPs = 2×1×1×256×256×27×272 \times 1 \times 1 \times 256 \times 256 \times 27 \times 27
    • Conv2d (1x1): 输出大小 = 27x27,FLOPs = 2×1×1×256×256×27×272 \times 1 \times 1 \times 256 \times 256 \times 27 \times 27
  3. 第三个nin_block (256, 384, 3, 1, 1):

    • Conv2d (3x3): 输出大小 = 13x13,FLOPs = 2×3×3×256×384×13×132 \times 3 \times 3 \times 256 \times 384 \times 13 \times 13
    • Conv2d (1x1): 输出大小 = 13x13,FLOPs = 2×1×1×384×384×13×132 \times 1 \times 1 \times 384 \times 384 \times 13 \times 13
    • Conv2d (1x1): 输出大小 = 13x13,FLOPs = 2×1×1×384×384×13×132 \times 1 \times 1 \times 384 \times 384 \times 13 \times 13
  4. 第四个nin_block (384, 10, 3, 1, 1):

    • Conv2d (3x3): 输出大小 = 6x6,FLOPs = 2×3×3×384×10×6×62 \times 3 \times 3 \times 384 \times 10 \times 6 \times 6
    • Conv2d (1x1): 输出大小 = 6x6,FLOPs = 2×1×1×10×10×6×62 \times 1 \times 1 \times 10 \times 10 \times 6 \times 6
    • Conv2d (1x1): 输出大小 = 6x6,FLOPs = 2×1×1×10×10×6×62 \times 1 \times 1 \times 10 \times 10 \times 6 \times 6

总FLOPs需要将这些值相加。由于计算过程复杂,这里只列出计算公式,详细的FLOPs计算需要具体工具。

显存需求

训练期间

  1. 前向和后向传播:

    • 需要存储激活值、梯度和参数。
  2. 批量大小:

    • 假设批量大小为 BB

显存使用包括: 显存=激活值显存+参数显存+梯度显存\text{显存} = \text{激活值显存} + \text{参数显存} + \text{梯度显存}

预测期间

  1. 仅前向传播:
    • 主要需要存储激活值和参数。

使用典型大小:

  • 激活值: 根据每层输出大小计算。
  • 参数: 每个参数4字节(32位浮点数)。
  • 梯度(仅在训练时): 类似于激活值。

总体上,训练期间的显存需求大约是预测期间的两倍,因为需要存储梯度。

总结

  • 总参数数量: 约1,990,686。
  • FLOPs: 需要详细计算。
  • 显存使用:
    • 训练期间: 通常是预测期间的两倍。
    • 预测期间: 包括激活值和参数,需要根据具体层的输出大小和参数大小计算。

具体的显存和FLOPs计算需要更详细的尺寸和工具,这里提供了一个计算框架。

4. 一次性直接将 384×5×5384 \times 5 \times 5 的表示缩减为 10×5×510 \times 5 \times 5 的表示,会存在哪些问题?

一次性将表示从 384×5×5384 \times 5 \times 5 缩减到 10×5×510 \times 5 \times 5 存在以下几个问题:

1. 信息丢失

大的通道数(如 384)可以捕捉到丰富的特征信息。直接将其缩减到较小的通道数(如 10),会导致大量信息丢失,模型可能无法有效学习和提取有用的特征。

2. 特征表达能力下降

通道数的减少意味着模型的表达能力下降。高维的特征空间可以表示更多的细节和复杂的模式,而低维的特征空间则可能无法捕捉到这些细节和复杂性。

3. 梯度消失和梯度爆炸

如果缩减过程涉及大的参数变化,可能会导致梯度消失或梯度爆炸问题。这会影响模型的训练稳定性和收敛速度。

4. 卷积计算效率

卷积操作的计算效率也会受到影响。高维度到低维度的转换可能需要更多复杂的计算步骤,并且不一定能充分利用并行计算的优势。

5. 模型复杂度和可解释性

大幅度缩减通道数会使得模型复杂度增加,难以解释每个通道的特定功能和特征。模型的透明度和可解释性可能会下降。

6. 潜在的过拟合

过多的参数缩减可能导致模型过度拟合训练数据而在验证数据上表现较差。这是因为模型可能会缺乏足够的表达能力来泛化到新的数据。

7. 模型层次结构

通常,网络的层次结构设计是经过细致考量的,以确保每一层都能够逐步提取和组合特征。一次性大幅度缩减通道数会破坏这种层次结构,使得模型的特征提取过程不连续,影响最终的性能。

总结

一次性将 384×5×5384 \times 5 \times 5 缩减到 10×5×510 \times 5 \times 5 会导致信息丢失、特征表达能力下降、梯度问题、卷积计算效率降低、模型复杂度增加、潜在过拟合和层次结构破坏等问题。为了避免这些问题,通常采用逐步缩减通道数的方式,通过多个卷积层和非线性激活函数逐渐减少通道数,从而保留更多的特征信息和模型的表达能力。