《动手学深度学习 Pytorch版》 7.3 网络中的网络(NiN)

news2024/11/17 17:51:33

LeNet、AlexNet和VGG的设计模式都是先用卷积层与汇聚层提取特征,然后用全连接层对特征进行处理。

AlexNet和VGG对LeNet的改进主要在于扩大和加深这两个模块。网络中的网络(NiN)则是在每个像素的通道上分别使用多层感知机。

import torch
from torch import nn
from d2l import torch as d2l

7.3.1 NiN

NiN的想法是在每个像素位置应用一个全连接层。 如果我们将权重连接到每个空间位置,我们可以将其视为 1 × 1 1\times 1 1×1 卷积层,即是作为在每个像素位置上独立作用的全连接层。 从另一个角度看,是将空间维度中的每个像素视为单个样本,将通道维度视为不同特征(feature)。

NiN块以一个普通卷积层开始,后面是两个 1 × 1 1\times 1 1×1 的卷积层。这两个卷积层充当带有ReLU激活函数的逐像素全连接层。

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.ReLU(),
        nn.Conv2d(out_channels, out_channels, kernel_size=1), nn.ReLU(),
        nn.Conv2d(out_channels, out_channels, kernel_size=1), nn.ReLU())

7.3.2 NiN 模型

最初的 NiN 网络是在 AlexNet 后不久提出的,显然 NiN 网络是从 AlexNet 中得到了一些启示的。 NiN 使用窗口形状为 11 × 11 11\times 11 11×11 5 × 5 5\times 5 5×5 3 × 3 3\times 3 3×3 的卷积层,输出通道数量与 AlexNet 中的相同。每个NiN块后有一个最大汇聚层,汇聚窗口形状为 3 × 3 3\times 3 3×3 ,步幅为 2。

NiN 和 AlexNet 之间的显著区别是 NiN 使用一个 NiN 块取代了全连接层。其输出通道数等于标签类别的数量。最后放一个全局平均汇聚层,生成一个对数几率。

NiN 设计的一个优点是显著减少了模型所需参数的数量。然而,在实践中,这种设计有时会增加训练模型的时间。

在这里插入图片描述

net = nn.Sequential(
    nin_block(1, 96, kernel_size=11, strides=4, padding=0),
    nn.MaxPool2d(3, stride=2),
    nin_block(96, 256, kernel_size=5, strides=1, padding=2),
    nn.MaxPool2d(3, stride=2),
    nin_block(256, 384, kernel_size=3, strides=1, padding=1),
    nn.MaxPool2d(3, stride=2),
    nn.Dropout(0.5),
    # 标签类别数是10
    nin_block(384, 10, kernel_size=3, strides=1, padding=1),
    nn.AdaptiveAvgPool2d((1, 1)),
    # 将四维的输出转成二维的输出,其形状为(批量大小,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)
Sequential output shape:	 torch.Size([1, 96, 54, 54])
MaxPool2d output shape:	 torch.Size([1, 96, 26, 26])
Sequential output shape:	 torch.Size([1, 256, 26, 26])
MaxPool2d output shape:	 torch.Size([1, 256, 12, 12])
Sequential output shape:	 torch.Size([1, 384, 12, 12])
MaxPool2d output shape:	 torch.Size([1, 384, 5, 5])
Dropout output shape:	 torch.Size([1, 384, 5, 5])
Sequential output shape:	 torch.Size([1, 10, 5, 5])
AdaptiveAvgPool2d output shape:	 torch.Size([1, 10, 1, 1])
Flatten output shape:	 torch.Size([1, 10])

7.3.3 训练模型

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())  # 大约需要二十五分钟,慎跑
loss 0.600, train acc 0.769, test acc 0.775
447.9 examples/sec on cuda:0

在这里插入图片描述

练习

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

net2 = nn.Sequential(
    nin_block(1, 96, kernel_size=11, strides=4, padding=0),
    nn.MaxPool2d(3, stride=2),
    nin_block(96, 256, kernel_size=5, strides=1, padding=2),
    nn.MaxPool2d(3, stride=2),
    nin_block(256, 384, kernel_size=3, strides=1, padding=1),
    nn.MaxPool2d(3, stride=2),
    nn.Dropout(0.5),
    nin_block(384, 10, kernel_size=3, strides=1, padding=1),
    nn.AdaptiveAvgPool2d((1, 1)),
    nn.Flatten())

lr, num_epochs, batch_size = 0.15, 12, 128
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size, resize=224)
d2l.train_ch6(net2, train_iter, test_iter, num_epochs, lr, d2l.try_gpu())  # 大约需要三十分钟,慎跑
loss 0.353, train acc 0.871, test acc 0.884
449.5 examples/sec on cuda:0

在这里插入图片描述

学习率调大一点点之后精度更高了,但是波动变的分外严重。


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

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

net3 = nn.Sequential(
    nin_block2(1, 96, kernel_size=11, strides=4, padding=0),
    nn.MaxPool2d(3, stride=2),
    nin_block2(96, 256, kernel_size=5, strides=1, padding=2),
    nn.MaxPool2d(3, stride=2),
    nin_block2(256, 384, kernel_size=3, strides=1, padding=1),
    nn.MaxPool2d(3, stride=2),
    nn.Dropout(0.5),
    # 标签类别数是10
    nin_block2(384, 10, kernel_size=3, strides=1, padding=1),
    nn.AdaptiveAvgPool2d((1, 1)),
    # 将四维的输出转成二维的输出,其形状为(批量大小,10)
    nn.Flatten())

lr, num_epochs, batch_size = 0.15, 10, 128
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size, resize=224)
d2l.train_ch6(net3, train_iter, test_iter, num_epochs, lr, d2l.try_gpu())  # 大约需要二十分钟,慎跑
loss 0.309, train acc 0.884, test acc 0.890
607.5 examples/sec on cuda:0

在这里插入图片描述

有时候会更好,有时候会不收敛。


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

a. 参数的数量是多少?

b. 计算量是多少?

c. 训练期间需要多少显存?

d. 预测期间需要多少显存?

a. 参数数量:

[ 11 × 11 + 2 ] + [ 5 × 5 + 2 ] + [ 3 × 3 + 2 ] + [ 3 × 3 + 2 ] = 123 + 27 + 11 + 11 = 172 \begin{align} &[11\times 11 + 2] + [5\times 5 + 2] + [3\times 3 + 2] + [3\times 3 + 2]\\ =& 123+27+11+11\\ =& 172 \end{align} ==[11×11+2]+[5×5+2]+[3×3+2]+[3×3+2]123+27+11+11172

b. 计算量:

{ [ ( 224 − 11 + 4 ) / 4 ] 2 × 1 1 2 × 96 + 22 4 2 × 2 } + [ ( 26 − 5 + 2 + 1 ) 2 × 5 2 × 96 × 256 + 2 6 2 × 2 ] + [ ( 12 − 3 + 1 + 1 ) 2 × 3 2 × 256 × 384 + 1 2 2 × 2 ] + [ ( 5 − 3 + 1 + 1 ) 2 × 3 2 × 384 × 10 + 5 2 × 2 ] = 34286966 + 353895752 + 107053344 + 553010 = 495789072 \begin{align} &\{[(224-11+4)/4]^2\times 11^2\times 96 + 224^2\times 2\} + [(26-5+2+1)^2\times 5^2\times 96\times 256 + 26^2\times 2] + \\ &[(12-3+1+1)^2\times 3^2\times 256\times 384 + 12^2\times 2]+[(5-3+1+1)^2\times 3^2\times 384\times 10 + 5^2\times 2]\\ =&34286966+353895752+107053344+553010\\ =&495789072 \end{align} =={[(22411+4)/4]2×112×96+2242×2}+[(265+2+1)2×52×96×256+262×2]+[(123+1+1)2×32×256×384+122×2]+[(53+1+1)2×32×384×10+52×2]34286966+353895752+107053344+553010495789072


(4)一次性直接将 384 × 5 × 5 384\times 5\times 5 384×5×5 的表示压缩为 10 × 5 × 5 10\times 5\times 5 10×5×5 的表示,会存在哪些问题?

压缩太快可能导致特征损失过多。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1025524.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JumpServer开源堡垒机与爱可生云树数据库完成兼容性认证

近日,中国领先的开源软件提供商FIT2CLOUD飞致云宣布,JumpServer开源堡垒机已经完成与爱可生云树数据库软件的兼容性认证。经过双方联合测试,云树数据库软件(简称:ActionDB)V1.0与杭州飞致云信息科技有限公司…

前端提高代码质量-提升代码的可维护性

代码质量是一个非常重要的概念,它决定了代码的可读性、可维护性、可扩展性和稳定性。在前端开发中,提升代码质量可以帮助我们减少错误、提高开发效率、降低维护成本,甚至可以提高用户体验。 在必要的地方加注释 良好的注释可以帮助开发人员理…

使用RKDevTool将update.img完整镜像进行解包,得到单独分区的镜像

(1)使用开发工具高级功能的解包 导入xx.img,然后点击解包(2)在Output/Android/Image得到想要的image

zotero通过DOI快速导入文献

之前我经常采用两种方式导入文献: (1)下载PDF,然后拖入zotero 这种方法比较费时间,有些文献无法下载pdf (2)通过google scholar检索文献,然后点击引用——EndNote,chorme…

HCQ1-1300-D故障笔记

常用查错网址: SMC_ERROR (ENUM) 删除 Web

socket套接字——TCP协议

目录 一、TCP协议相关函数 1.socket、bind函数 2.listen函数 3.accept函数 4.connect函数 二、实现TCP通信 1.服务端实现 (1)服务端类 (2)日志小组件 (3)初始化服务端 (4&#xff09…

etcd的安装和使用

安装及启动 在Mac上,推荐使用brew安装 brew install etcd 可以使用etcd启动服务,但更推荐使用 brew services 来管理使用brew安装的应用~ # 启动某个应用,这里用 etcd 做演示brew services start etcd# 停止某个应用brew services stop etcd#…

Hive的分区和分桶

目录 ​编辑 一、Hive分区 1.1 分区产生的背景 1.2 动态分区 1.2.1 hive的动态分区介绍 1.2.2 动态分区配置 1.2.2.1 动态分区开启 1.2.2.2 动态分区模式 1.2.2.3 一个mr节点上,设置动态分区的最大数量 1.2.2.4 所有mr节点上,设置所有动态分区…

linux安装redis超级详细教程

redis源码安装 安装gcc redis是C语言编写的,所以我们需要先在Linux上安装和升级,C语言的编译环境。 #安装gcc yum install -y gcc-c autoconf automake#centos7 默认的 gcc 默认是4.8.5,版本小于 5.3 无法编译,需要先安装gcc新版才能编译 gcc -v#升级…

rv1126-rv1109-环境搭建-全部编译的方法

主要参考:Rockchip_Developer_Guide_Linux_Software_CN.pdf / SDK-Rockchip_RV1126_RV1109_Quick_Start_Linux_CN.pdf 找对文档事半功倍!为什么这么说,因为没找对绕了路!别笑! //解压源码,基础略过 tar xvf rv1126_rv1109_linux_v3.0.2_20230724.tgz -C rv1126_rv1109 cd rv1…

【Axure高保真原型】动态控制不透明度

今天和大家分享动态控制不透明度的原型模板,我们可以滑块左右拖动或者点击滑条的某个位置,从而控制图片上方遮罩的不透明度……具体效果可以打开下方原型地址体验或者点击下方视频观看 【原型效果】 【Axure高保真原型】动态控制不透明度 【原型预览及下…

No thread-bound request found 错误以及解决方案

异常信息: cause: java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually o…

一起学数据结构(7)——树及二叉树的基本概念及存储

前面的关于数据结构的文章中,介绍了顺序表,链表,栈,队列等数据结构。对于以上数据结构,均是一对一的关系。本篇文章将对于一对多的数据结构——树进行解析。 目录 1. 树的定义及基本概念: 1.1 树的定义&a…

结合el-tooltip,实现内容过长省略,移上显示全部

在系统中,内容过长需要省略,鼠标移上显示全部,这个是常用的功能,也有很多方案解决这种。 单行内容超出处理 常用的css方案: .ellipsis {overflow: hidden;white-space: nowrap;text-overflow: ellipsis; } 该样式在…

基于Android系统英语学习助手APP设计开发

一、 设计思路 1.1设计目标 1.2设计思路 1.3设计内容 1.3.1界面设计 1.3.2功能模块设计 1.3.3功能流程图 1.3.4数据库设计(如果没有数据库这部分删除) 1.4工具设备要求 1.5技术方案 二、设计过程与说明 2.1技术路线 2.2实现方案 2.3实现原理…

C#复习:面向对象基本概念

C#复习:面向对象基本概念 前言什么是面向对象类,名称空间的介绍 如何导入类库DLL引用(黑盒引用)项目引用(白盒引用)NuGet介绍 依赖关系C#的分装(个人理解) 前言 关于我C#的博客是根据刘铁猛老师的C#入门课程为基础写的,可以配合刘铁猛老师的…

.bat批处理命令处理文件

批处理命令处理文件找到上级目录,并删除文件与文件夹 参考资料: [BAT] 如何获取bat的上一级目录、上两级目录..._bat 上层目录_Risun_Lee的博客-CSDN博客echo offset currPath%~dp0set parentPathset parentparentPath:beginfor /f "tokens1,* de…

solidworks导出文本能打开的stl文件

几种以文本格式(ASCII)导出stl的设置 1.solidworks导出时需要在选项里设置导出格式为ASCII,当选择以二进制格式导出时,打开会乱码; 2.CAD直接导出的是以二进制形式导出的,导出后也无法使用文本打开&#xf…

NVIDIA DALI学习:数据加载

DALI的工作流, 如下图: 读取数据图像解码和变换,可以放到GPU上进行,也是加速的关键生成处理好的数据, 导出给计算引擎 测试用例 import ctypesimport numpy as np import nvidia.dali.fn as fn import nvidia.dali…

关于Godot动态生成节点的细节

var dy_btn Button.new()add_child(dy_btn)print(get_child(0).name) 此时获取的名词会带有动态类型,如果这个时候想通过特定的节点名词来获取节点是不行的 此时需要补充类似 dy_btn.name "a" 的代码,然后就能按照节点名词获取节点了