PyTorch DAY2: 搭建神经网络

如今,我们已经了解了 PyTorch 中张量及其运算,但这远远不够。本次实验将学会如何使用 PyTorch 方便地构建神经网络模型,以及 PyTorch 训练神经网络的步骤及方法。

知识点
  • PyTorch 构建神经网络
  • Sequential 容器结构
  • 使用 GPU 加速训练
  • 模型保存与推理

PyTorch 构建神经网络 

方便定义不同类型的 Tensor 及利于反向传播的 Autograd 机制是深度学习框架的重要特点,但真正带来极大便利的,莫过于已经封装好的不同神经网络结构组件,包括不同类型的层以及各式各样的损失函数、激活函数、优化器等。 

PyTorch 搭建神经网络结构的组件在 torch.nn 中 ,这些神经网络层大多以类出现,例如全连接层:torch.nn.Linear() ,MSE 损失函数类:torch.nn.MSELoss()  等。

除此之外,torch.nn.functional  下面同样也有神经网络层,激活函数,损失函数等,但均以函数出现,例如全连接层函数:torch.nn.functional.linear() ,MSE 损失函数:torch.nn.functionalmse_loss()  等。 

总之,torch.nn 下面包含了神经网络组件类(大写字母),而 torch.nn.functional 包含了神经网络组件函数(小写字母)。 

本次实验使用的数据集为 MNIST,你可以把它看成是 DIGITS 数据集的增强版,都是手写字符任务。前面我们使用过 Fashion MNIST 数据集,MNIST 数据集和其样本特征是一致的,只是样本类别不一样。MNIST 中每个样本是 28×28 的矩阵,目标是字符 0-9。 

               

我们可以直接使用 PyTorch 提供的计算机视觉增强模块 torchvision 加载 MNIST 数据集。由于数据集托管在外网服务器上,国内的下载速度较慢,实验从国内服务器下载该数据集。

# 从国内服务器下载数据集
!wget -nc "http://labfile.oss.aliyuncs.com/courses/1081/MNIST.zip"
!unzip -o "MNIST.zip"
import torchvision# 加载训练数据,参数 train=True,供 60000 条
train = torchvision.datasets.MNIST(root='.', train=True, transform=torchvision.transforms.ToTensor(), download=True)
# 加载测试数据,参数 train=False,供 10000 条
test = torchvision.datasets.MNIST(root='.', train=False, transform=torchvision.transforms.ToTensor(), download=True)

上面的代码中,transform=torchvision.transforms.ToTensor()  是利用了 torchvision 提供的 transforms 直接将原 NumPy 数组转换为 PyTorch 张量。现在,你可以尝试输出训练和测试数据的特征和目标查看。

train.data.shape, train.targets.shape, test.data.shape, test.targets.shape

接下来,我们还需要使用 PyTorch 提供的一个组件对数据进行封装。torch.utils.data.DataLoader  是 PyTorch 提供的及其常用的数据加载器,它可以将数据集封装成迭代器以方便我们后续进行小批量加载,数据打乱等操作。数据加载器准备好之后,后续只需要通过 for 循环来使用即可。

import torch# 训练数据打乱,使用 64 小批量
train_loader = torch.utils.data.DataLoader(dataset=train,batch_size=64, shuffle=True)
# 测试数据无需打乱,使用 64 小批量
test_loader = torch.utils.data.DataLoader(dataset=test,batch_size=64, shuffle=False)
train_loader, test_loader

接下来,我们学习 PyTorch 构建神经网络的经典方法,也是官方推荐使用的一种方法。 

首先,torch.nn 中的一个基础类 torch.nn.Module 。该类是 PyTorch 中所有神经网络的基类,它既可以表示神经网络中的某层,也可以表示若干层的神经网络。torch.nn 中的各个类实际上就是由 torch.nn.Modules 继承而拓展。所以,在实际使用中,我们可以继承nn.Module,撰写自定义网络层。

所以,当我们搭建神经网络时,也需要继承 torch.nn.Module。我们准备搭建一个包含两个隐含层的全连接网络。

输入(784) → 全连接层 1 (784, 512)→ 全连接层 2 (512, 128)→ 输出(10)
import torch.nn as nn
import torch.nn.functional as Fclass Net(nn.Module):def __init__(self):super(Net, self).__init__()self.fc1 = nn.Linear(784, 512)  # 784 是因为训练是我们会把 28*28 展平self.fc2 = nn.Linear(512, 128)  # 使用 nn 类初始化线性层(全连接层)self.fc3 = nn.Linear(128, 10)def forward(self, x):x = F.relu(self.fc1(x))  # 直接使用 relu 函数,也可以自己初始化一个 nn 下面的 Relu 类使用x = F.relu(self.fc2(x))x = self.fc3(x)  # 输出层一般不激活return x

我们定义了新的神经网络结构类 Net(),并使用 nn.Linear 组合了 3 个线性层(全连接层)。前向传播过程中,代码使用了 PyTorch 中常用的函数模块 torch.nn.functional 提供的 RELU 激活函数,实际上你也可以通过实例化 nn.Relu 来达到同样的效果。

下面,我们实例化自定义神经网络类:

model = Net()
model

PyTorch 的好处在于你可以初始化一个 784 长度的随机值样本传入网络,测试一下输出:

model(torch.randn(1, 784))

目前,我们已经搭好了前向传播网络。下面的步骤和 TensorFlow 非常相似:定义损失函数,优化器以及开始训练。

loss_fn = nn.CrossEntropyLoss()  # 交叉熵损失函数
opt = torch.optim.Adam(model.parameters(), lr=0.002)  # Adam 优化器

这里,我们选择了十分常用的交叉熵损失函数 nn.CrossEntropyLoss ,以及 Adam 优化器 torch.optim.Adam 。值得注意的是,PyTorch 中优化器需传入模型的参数 model.parameters(),这是 PyTorch 的一个使用特性。 

接下来,我们就可以开始训练了,这部分代码非常重要。

def fit(epochs, model, opt):print("Start training, please be patient.")# 全数据集迭代 epochs 次for epoch in range(epochs):# 从数据加载器中读取 Batch 数据开始训练for i, (images, labels) in enumerate(train_loader):images = images.reshape(-1, 28*28)  # 对特征数据展平,变成 784labels = labels  # 真实标签outputs = model(images)  # 前向传播loss = loss_fn(outputs, labels)  # 传入模型输出和真实标签opt.zero_grad()  # 优化器梯度清零,否则会累计loss.backward()  # 从最后 loss 开始反向传播opt.step()  # 优化器迭代# 自定义训练输出样式if (i+1) % 100 == 0:print('Epoch [{}/{}], Batch [{}/{}], Train loss: {:.3f}'.format(epoch+1, epochs, i+1, len(train_loader), loss.item()))# 每个 Epoch 执行一次测试correct = 0total = 0for images, labels in test_loader:images = images.reshape(-1, 28*28)labels = labelsoutputs = model(images)# 得到输出最大值 _ 及其索引 predicted_, predicted = torch.max(outputs.data, 1)correct += (predicted == labels).sum().item()  # 如果预测结果和真实值相等则计数 +1total += labels.size(0)  # 总测试样本数据计数print('============ Test accuracy: {:.3f} ============='.format(correct / total))
fit(epochs=1, model=model, opt=opt)  # 训练 1 个 Epoch,预计持续 10 分钟

上方的代码中有详细的注释,但依旧有几点值得注意的地方。

首先,由于 PyTorch 没有提供类似于 Flatten 这样的展平类,所以我们通过 reshape 操作将输入 28×28 展平为 784,使其和网络结构参数符合。你也可以使用 view,但官方更推荐使用 reshape 。

其次,opt.zero_grad() 这步非常关键。由于 PyTorch 设计时梯度会累计,所以我们需要手动清零以实现传入一个 Batch,计算梯度,然后更新参数,从而不会因为前面的梯度累计影响后面的参数更新。但 PyTorch 这样设计也是有原因的,比如当我们想提升 Batch 的大小而硬件又无法处理较多数据时,就可以通过梯度累积机制,等待传入多个 Batch 后再更新参数并执行清零,这就给了开发更多的灵活性。同时,后续循环神经网络中也可能利用到这个特性。

Sequential 容器结构

上面,我们学习了使用 PyTorch 构建神经网络模型的经典方法步骤。你会发现 PyTorch 使用起来比 TensorFlow 要简单一些,主要体现在 DataLoader 数据加载器和前向传播过程调试较为方便,以及无需管理会话等。但是,PyTorch 又似乎比 Keras 要复杂一些,尤其是需要手动构建训练过程,还需要注意执行 opt.zero_grad() 等额外步骤。

实际上,由于 PyTorch 未提供像 tf.keras 这种更高阶的 API,所以无法达到与 Keras 相似的便捷程度。不过,我们可以使用 PyTorch 提供的 Sequential 网络结构来优化上面的经典过程,使得神经网络结构定义的部分更精简一些。

上面,我们通过继承 nn.Module 来定义了网络结构 Net() 类。实际上,利用 nn.Sequential  可以让这个过程更加直观简便。你可以直接按顺序将网络需要的组件类添加到 Sequential 容器结构中。

model_s = nn.Sequential(nn.Linear(784, 512),  # 线性类nn.ReLU(),  # 激活函数类nn.Linear(512, 128),nn.ReLU(),nn.Linear(128, 10),
)

model_s  # 查看网络结构

接下来,我们直接利用上面定义好的损失函数和训练函数完成模型优化迭代过程。由于优化器中需要传入模型的参数,所以这里需要修改为后续定义的 Sequential 模型。

opt_s = torch.optim.Adam(model_s.parameters(), lr=0.002)  # Adam 优化器
fit(epochs=1, model=model_s, opt=opt_s)  # 训练 1 个 Epoch

使用 GPU 加速训练

图形处理器 GPU 是深度学习加速训练的重要硬件。当我们使用 TensorFlow 构建神经网络时,一般会自动调用 GPU 而无需修改代码 。不过,PyTorch 使用 GPU 加速会麻烦一些,我们需要将数据张量和模型都转化为 CUDA 类型 。为了方便大家在使用 PyTorch 时调用 GPU,下面给出一般流程用于参考。

首先,我们需要验证 PyTorch 是否可以使用当前 GPU 用于加速计算。torch.cuda.is_available()  如果返回 True 即代表 GPU 可用,False 则代表只能使用 CPU。

torch.cuda.is_available()

由于当前使用只配备了 CPU 环境,所以上面返回 False,不过不影响本小节内容学习。

一般,我们会提前写好一个判断语句,以保证代码能够在 CPU 或者 GPU 环境中均能正常执行。

# 如果 GPU 可用则使用 CUDA 加速,否则使用 CPU 设备计算
dev = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu")
dev

然后修改代码,数据和模型后面添加 .to(dev),这样 PyTorch 就可以自动判断是否使用 GPU 加速了。首先是对从 DataLoader 中加载出来的每一批次数据后添加 .to(dev)。我们沿用 fit(epochs, model, opt) 中的代码。

def fit(epochs, model, opt):print("Start training, please be patient.")for epoch in range(epochs):for i, (images, labels) in enumerate(train_loader):images = images.reshape(-1, 28*28).to(dev)  # 添加 .to(dev)labels = labels.to(dev)  # 添加 .to(dev)outputs = model(images)loss = loss_fn(outputs, labels)opt.zero_grad()loss.backward()opt.step()if (i+1) % 100 == 0:print('Epoch [{}/{}], Batch [{}/{}], Train loss: {:.3f}'.format(epoch+1, epochs, i+1, len(train_loader), loss.item()))correct = 0total = 0for images, labels in test_loader:images = images.reshape(-1, 28*28).to(dev)  # 添加 .to(dev)labels = labels.to(dev)  # 添加 .to(dev)outputs = model(images)_, predicted = torch.max(outputs.data, 1)correct += (predicted == labels).sum().item()total += labels.size(0)print('============ Test accuracy: {:.3f} ============='.format(correct / total))

接下来,给模型添加 .to(dev),使得模型可以自动判断是否使用 CUDA 加速。请注意,由于优化器中传入了模型的参数,而该参数可能会因为 GPU 变更为 CUDA 类型,所以我们需要重新执行优化器代码防止数据类型不一致而报错。

model_s.to(dev)
opt_s = torch.optim.Adam(model_s.parameters(), lr=0.002)

最终完成训练即可,如果有 GPU 则速度会明显优于 CPU。

fit(epochs=1, model=model_s, opt=opt_s)  # 训练 1 个 Epoch

模型保存与推理

我们同样可以保存 PyTorch 模型以用于推理。直接使用 torch.save  将模型存在 .pt 文件即可。

torch.save(model_s, './model_s.pt')

接下来,使用 torch.load  加载模型即可使用模型进行推理。

model_s = torch.load('./model_s.pt')
model_s

我们使用测试数据中的第一个样本作为示例进行推理。

# 对测试数据第一个样本进行推理,注意将张量类型转换为 FloatTensor
result = model_s(test.data[0].reshape(-1, 28*28).type(torch.FloatTensor).to(dev))
torch.argmax(result)  # 找到输出最大值索引即为预测标签

打印第一个测试样本的真实标签。

test.targets[0]  # 第一个测试数据真实标签

实际上,关于 PyTorch 模型的保存还有其他方法和适用情况,例如 CPU 训练的模型放置到 GPU 环境中进行推理等。更多内容,希望大家后续抽时间详细学习官方文档相应章节内容 。

实验总结

本次实验中,我们学习了如何继承 PyTorch 中神经网络基类 torch.nn.Module 搭建网络结构,并通过 MNIST 演示了 PyTorch 用于模型训练的完整过程。这是使用 PyTorch 构建人工神经网络最常用的方法,大家一定要牢牢掌握。当然,实验最后,我们还了解了如何使用 nn.Sequential 构建模型容器,以及 PyTorch 模型保存与 GPU 加速计算等内容。后续,推荐大家结合 PyTorch 官方文档示例来深入了解并掌握该框架的运用。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025 年 Java 最新学习资料与学习路线——从零基础到高手的成长之路

2025 年 Java 最新学习资料与学习路线——从零基础到高手的成长之路 大家好,欢迎来到我的频道!今天我们要聊聊 Java ——这门陪伴了很多程序员成长的编程语言。无论你是编程新手,还是已经走了一段编程路,但还不确定如何深入学习 …

riscv架构下linux4.15实现early打印

在高版本linux6.12.7源码中,early console介绍,可参考《riscv架构下linux6.12.7实现early打印》文章。 1 什么是early打印 适配内核到新的平台,基本环境搭建好之后,首要的就是要调通串口,方便后面的信息打印。 正常流…

【论文阅读笔记】基于YOLO和ResNet深度卷积神经网络的结直肠息肉检测

作者:李素琴、吴练练、宫德馨、胡珊、陈奕云、朱晓云、李夏、于红刚 效果视频链接:https://www.xhnj.com/m/video/1008384.htm 小结 从算法的角度来说,作为2020发布的论文,使用的技术是比较落后的了。一个息肉检测项目&#xff0…

win32汇编环境,窗口程序中基础列表框的应用举例

;运行效果 ;win32汇编环境,窗口程序中基础列表框的应用举例 ;比如在窗口程序中生成列表框,增加子项,删除某项,取得指定项内容等 ;直接抄进RadAsm可编译运行。重点部分加备注。 ;以下是ASM文件 ;>>>>>>>>>>>…

Lora理解QLoRA

Parameter-Efficient Fine-Tuning (PEFT) :节约开销的做法,fine-tune少量参数,而不是整个模型; Low-Rank Adaptation (LoRA) :是PEFT的一种;冻结原参数矩阵,只更新2个小参数矩阵。 原文经过对比…

YOLOv5训练长方形图像详解

文章目录 YOLOv5训练长方形图像详解一、引言二、数据集准备1、创建文件夹结构2、标注图像3、生成标注文件 三、配置文件1、创建数据集配置文件2、选择模型配置文件 四、训练模型1、修改训练参数2、开始训练 五、使用示例1、测试模型2、评估模型 六、总结 YOLOv5训练长方形图像详…

基于微信小程序的电子点菜系统设计与实现(KLW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导,欢迎高校老师/同行前辈交流合作✌。 技术范围:SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:…

Titans 架构中的记忆整合:Memory as a Context;Gated Memory;Memory as a Layer

Titans 架构中的记忆整合 Titans 架构中的记忆整合 Memory as a Context(MAC)变体:在处理长序列数据时,将序列分段,对于当前段 S ( t ) S^{(t)}

洛谷P3916 图的遍历

题目描述 给出 N 个点,M 条边的有向图,对于每个点 v,求 A(v) 表示从点 v 出发,能到达的编号最大的点。 输入格式 第 1 行 2 个整数 N,M,表示点数和边数。 接下来 M 行,每行 2 个整数 Ui,Vi​,表示边 (U…

【python】实现图像中的阴影去除 | 方案和代码

去除图像中的阴影是一项复杂的图像处理任务,尤其是当阴影区域与图像的其他部分混合时。阴影的存在会影响图像的颜色平衡和亮度,导致图像分析和理解的困难。 目录 一 安装依赖 二 函数 ① rgb2hsv ② hsv2rgb 三 实现图像中的阴影去除的方法 四 实…

记录一次 centos 启动失败

文章目录 现场1分析1现场2分析2搜索实际解决过程 现场1 一次断电,导致 之前能正常启动的centos 7.7 起不来了有部分log , 关键信息如下 [1.332724] XFS(sda3): Internal error xfs ... at line xxx of fs/xfs/xfs_trans.c [1.332724] XFS(sda3): Corruption of in-memory data…

文件操作:系统IO

文件操作 目录 基本概念Linux文件特点操作方式1-系统IO操作方式2-标准IO两种操作模式的对比 基本概念 什么是文件 简单的说,文件就是存储在硬件磁盘上的数据集合 文件通过什么来标识? 系统中在处理的文件(读、写操作)的时候…

ComfyUI-PromptOptimizer:文生图提示优化节点

ComfyUI-PromptOptimizer 是 ComfyUI 的一个自定义节点,旨在优化文本转图像模型的提示。它将用户输入的提示转换为更详细、更多样化、更生动的描述,使其更适合生成高质量的图像。无需本地模型。 1、功能 提示优化:优化用户输入的提示以生成…

windows 搭建flutter环境,开发windows程序

环境安装配置: 下载flutter sdk https://docs.flutter.dev/get-started/install/windows 下载到本地后,随便找个地方解压,然后配置下系统环境变量 编译windows程序本地需要安装vs2019或更新的开发环境 主要就这2步安装后就可以了&#xff0…

从玩具到工业控制--51单片机的跨界传奇【3】

在科技的浩瀚宇宙中,51 单片机就像一颗独特的星辰,散发着神秘而迷人的光芒。对于无数电子爱好者而言,点亮 51 单片机上的第一颗 LED 灯,不仅仅是一次简单的操作,更像是开启了一扇通往新世界的大门。这小小的 LED 灯&am…

构建一个简单的深度学习模型

构建一个简单的深度学习模型通常包括以下几个步骤:定义模型架构、编译模型、训练模型和评估模型。下面是一个使用Keras(TensorFlow的高级API)构建和训练一个简单的全连接神经网络(也称为多层感知器,MLP)的示…

linux下的NFS和FTP部署

目录 NFS应用场景架构通信原理部署权限认证Kerberos5其他认证方式 命令serverclient查看测试系统重启后自动挂载 NFS 共享 高可用实现 FTP对比一些ftp服务器1. **vsftpd (Very Secure FTP Daemon)**2. **ProFTPD (Professional FTP Daemon)**3. **Pure-FTPd**4. **WU-FTPD (Was…

Python操作Excel——openpyxl使用笔记(3)

3 单元格基本操作 3.1 访问单元格和读写其内容 在前面的例子中,已经简单演示过了向单元格中写入和读取数据。这里进一步提供访问单元格的一些方法。和前面一样,使用工作表的索引方式,可以快速定位一个单元格: import openpyxl w…

【漏洞预警】FortiOS 和 FortiProxy 身份认证绕过漏洞(CVE-2024-55591)

文章目录 一、产品简介二、漏洞描述三、影响版本四、漏洞检测方法五、解决方案 一、产品简介 FortiOS是Fortinet公司核心的网络安全操作系统,广泛应用于FortiGate下一代防火墙,为用户提供防火墙、VPN、入侵防御、应用控制等多种安全功能。 FortiProxy则…

一、1-2 5G-A通感融合基站产品及开通

1、通感融合定义和场景(阅读) 1.1通感融合定义 1.2通感融合应用场景 2、通感融合架构和原理(较难,理解即可) 2.1 感知方式 2.2 通感融合架构 SF(Sensing Function):核心网感知控制…