当前位置: 首页 > news >正文

动手学深度学习—网络中的网络NiN(代码详解)

目录

      • 1. NiN块
      • 2. NiN模型
      • 3. 训练模型

LeNet、AlexNet和VGG都有一个共同的设计模式:
通过一系列的卷积层与汇聚层来提取空间结构特征;然后通过全连接层对特征的表征进行处理。

如果在过程的早期使用全连接层,可能会完全放弃表征的空间结构。

而NiN(网络中的网络)提供了一个非常简单的解决方案:在每个像素的通道上分别使用多层感知机。

1. NiN块

卷积层的输入和输出由四维张量组成(样本,通道,高度,宽度)
全连接层的输入和输出通常是二维张量(样本,特征)

NiN在每个像素位置(针对每个高度和宽度)应用一个全连接层,可以将其视为1x1卷积层。将间维度中的每个像素视为单个样本,将通道维度视为不同特征。在这里插入图片描述
第一层为普通卷积层,之后的两个卷积层充当带有ReLU函数的逐像素全连接层。
NiN块

import torch
from torch import nn
from d2l import torch as d2l# 定义NiN块,(输入通道,输出通道,核大小,步幅,填充)
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())

2. NiN模型

1、NiN使用窗口形状为11×11、5×5和3×3的卷积层,输出通道数量与AlexNet中的相同
2、每个NiN块后有一个最大汇聚层,汇聚窗口形状为3×3,步幅为2
3、取消了全连接层,使用一个NiN块,其输出通道数等于标签类别的数量
4、最后放一个全局平均汇聚层,生成一个对数几率

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),# 标签类别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)

在这里插入图片描述

3. 训练模型

定义精度评估函数

"""定义精度评估函数:1、将数据集复制到显存中2、通过调用accuracy计算数据集的精度
"""
def evaluate_accuracy_gpu(net, data_iter, device=None): #@save# 判断net是否属于torch.nn.Module类if isinstance(net, nn.Module):net.eval()# 如果不在参数选定的设备,将其传输到设备中if not device:device = next(iter(net.parameters())).device# Accumulator是累加器,定义两个变量:正确预测的数量,总预测的数量。metric = d2l.Accumulator(2)with torch.no_grad():for X, y in data_iter:# 将X, y复制到设备中if isinstance(X, list):# BERT微调所需的(之后将介绍)X = [x.to(device) for x in X]else:X = X.to(device)y = y.to(device)# 计算正确预测的数量,总预测的数量,并存储到metric中metric.add(d2l.accuracy(net(X), y), y.numel())return metric[0] / metric[1]

定义GPU训练函数

"""定义GPU训练函数:1、为了使用gpu,首先需要将每一小批量数据移动到指定的设备(例如GPU)上;2、使用Xavier随机初始化模型参数;3、使用交叉熵损失函数和小批量随机梯度下降。
"""
#@save
def train_ch6(net, train_iter, test_iter, num_epochs, lr, device):"""用GPU训练模型(在第六章定义)"""# 定义初始化参数,对线性层和卷积层生效def init_weights(m):if type(m) == nn.Linear or type(m) == nn.Conv2d:nn.init.xavier_uniform_(m.weight)net.apply(init_weights)# 在设备device上进行训练print('training on', device)net.to(device)# 优化器:随机梯度下降optimizer = torch.optim.SGD(net.parameters(), lr=lr)# 损失函数:交叉熵损失函数loss = nn.CrossEntropyLoss()# Animator为绘图函数animator = d2l.Animator(xlabel='epoch', xlim=[1, num_epochs],legend=['train loss', 'train acc', 'test acc'])# 调用Timer函数统计时间timer, num_batches = d2l.Timer(), len(train_iter)for epoch in range(num_epochs):# Accumulator(3)定义3个变量:损失值,正确预测的数量,总预测的数量metric = d2l.Accumulator(3)net.train()# enumerate() 函数用于将一个可遍历的数据对象for i, (X, y) in enumerate(train_iter):timer.start() # 进行计时optimizer.zero_grad() # 梯度清零X, y = X.to(device), y.to(device) # 将特征和标签转移到devicey_hat = net(X)l = loss(y_hat, y) # 交叉熵损失l.backward() # 进行梯度传递返回optimizer.step()with torch.no_grad():# 统计损失、预测正确数和样本数metric.add(l * X.shape[0], d2l.accuracy(y_hat, y), X.shape[0])timer.stop() # 计时结束train_l = metric[0] / metric[2] # 计算损失train_acc = metric[1] / metric[2] # 计算精度# 进行绘图if (i + 1) % (num_batches // 5) == 0 or i == num_batches - 1:animator.add(epoch + (i + 1) / num_batches,(train_l, train_acc, None))# 测试精度test_acc = evaluate_accuracy_gpu(net, test_iter) animator.add(epoch + 1, (None, None, test_acc))# 输出损失值、训练精度、测试精度print(f'loss {train_l:.3f}, train acc {train_acc:.3f},'f'test acc {test_acc:.3f}')# 设备的计算能力print(f'{metric[2] * num_epochs / timer.sum():.1f} examples/sec'f'on {str(device)}')

在这里插入图片描述

训练模型

# 训练模型
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())

在这里插入图片描述

相关文章:

  • 功能测试想进阶,可以提供一点点思路和方向吗?
  • 深度学习——图像分类(CIFAR-10)
  • vue项目package.json与package-lock.json作用及区别
  • 10款轻量型的嵌入式GUI库分享
  • ajax请求的时候get 和post方式的区别?
  • 【Java】PAT Basic Level 1023 组个最小数
  • 怎么降低Linux内核驱动开发的风险?
  • C# 图解教程 第5版 —— 第10章 语句
  • appium操控微信小程序的坑
  • Centos 7 安装 Docker Enginee
  • rabbitmq-3.8.15集群、集群镜像模式安装部署
  • 【Python3】【力扣题】202. 快乐数
  • 使用Golang与Web3.js进行区块链开发
  • 体育竞技分析
  • 前端Vue页面中如何展示本地图片
  • C语言笔记(第一章:C语言编程)
  • el-input获取焦点 input输入框为空时高亮 el-input值非法时
  • exif信息对照
  • js中的正则表达式入门
  • mongo索引构建
  • Redux系列x:源码分析
  • Sass Day-01
  • text-decoration与color属性
  • Vim 折腾记
  • 阿里云前端周刊 - 第 26 期
  • 动态魔术使用DBMS_SQL
  • 基于Javascript, Springboot的管理系统报表查询页面代码设计
  • 聚簇索引和非聚簇索引
  • 前端相关框架总和
  • 使用 5W1H 写出高可读的 Git Commit Message
  • 腾讯大梁:DevOps最后一棒,有效构建海量运营的持续反馈能力
  • 怎么将电脑中的声音录制成WAV格式
  • 摩拜创始人胡玮炜也彻底离开了,共享单车行业还有未来吗? ...
  • ​DB-Engines 12月数据库排名: PostgreSQL有望获得「2020年度数据库」荣誉?
  • #pragma once
  • #我与Java虚拟机的故事#连载05:Java虚拟机的修炼之道
  • (13)[Xamarin.Android] 不同分辨率下的图片使用概论
  • (26)4.7 字符函数和字符串函数
  • (Java岗)秋招打卡!一本学历拿下美团、阿里、快手、米哈游offer
  • (Spark3.2.0)Spark SQL 初探: 使用大数据分析2000万KF数据
  • (七)c52学习之旅-中断
  • (一)Spring Cloud 直击微服务作用、架构应用、hystrix降级
  • ***检测工具之RKHunter AIDE
  • .equal()和==的区别 怎样判断字符串为空问题: Illegal invoke-super to void nio.file.AccessDeniedException
  • .net core 6 使用注解自动注入实例,无需构造注入 autowrite4net
  • .Net 转战 Android 4.4 日常笔记(4)--按钮事件和国际化
  • .NET中使用Redis (二)
  • [<MySQL优化总结>]
  • [ACL2022] Text Smoothing: 一种在文本分类任务上的数据增强方法
  • [acwing周赛复盘] 第 69 场周赛20220917
  • [AutoSar]BSW_OS 02 Autosar OS_STACK
  • [codeforces]Recover the String
  • [hdu2196]Computer树的直径
  • [IE编程] IE 是如何决定Accept-Language 属性的
  • [Java]深入剖析常见排序