【基于 PyTorch 的 Python 深度学习】5 机器学习基础(3)

前言

文章性质:学习笔记 📖

学习资料:吴茂贵《 Python 深度学习基于 PyTorch ( 第 2 版 ) 》【ISBN】978-7-111-71880-2

主要内容:根据学习资料撰写的学习笔记,该篇主要介绍了单 GPU 加速和多 GPU 加速,以及使用 GPU 的注意事项。

预:关于 GPU 加速

深度学习涉及很多向量或多矩阵运算,如矩阵相乘、矩阵相加、矩阵-向量乘法等。深层模型的算法,如 BP 、自编码器、CNN 等,都可以写成矩阵运算的形式,而无须写成循环运算。然而,在单核 CPU 上执行时,矩阵运算会被展开成循环的形式,本质上还是串行执行。GPU(Graphic Process Unit,图形处理器)的众核体系结构包含几千个流处理器,可将矩阵运算并行化执行,大幅缩短计算时间。随着 NVIDIA 、AMD 等公司不断推进其 GPU 的大规模并行架构,面向通用计算的 GPU 已成为加速可并行应用程序的重要手段。得益于 GPU 众核(Many-Core)体系结构,程序在 GPU 系统上的运行速度相较于单核 CPU 往往提升几十倍乃至上千倍。

目前,GPU 已经发展到了较为成熟的阶段。利用 GPU 来训练深度神经网络,可以充分发挥其计算核心的能力,使得在使用海量训练数据的场景下所耗费的时间大幅缩短,占用的服务器也更少。如果对深度神经网络进行合理优化,一块 GPU 卡相当于数十甚至上百台 CPU 服务器的计算能力,因此 GPU 已经成为业界在深度学习模型训练方面的首选解决方案。

如何使用 GPU ?现在很多深度学习工具都支持 GPU 运算,使用时只需要简单配置即可。PyTorch 支持 GPU,可以通过 to(device) 函数来将数据从内存中转移到 GPU 显存,如果有多个 GPU ,还可以定位到哪个或哪些 GPU ?PyTorch 一般把 GPU 作用于张量或模型(包括 torch.nn 下面的一些网络模型以及自己创建的模型)等数据结构上。

一、单 GPU 加速

使用 GPU 之前,需要确保 GPU 是可用的,可以通过 torch.cuda.is_available() 的返回值来进行判断。返回 True 则表示具有能够使用的 GPU 。 通过 torch.cuda.device_count() 可以获得可用的 GPU 的数量。

如何查看平台 GPU 的配置信息?在命令行输入命令 nvidia-smi 即可(适合于 Linux 或 Windows 环境),如图 5-28 所示。

把数据从内存转移到 GPU ,通常针对 张量(我们需要的数据)和 模型

1. 对于类型为 FloatTensor 或 LongTensor 等的张量,我们直接使用方法 .to(device).cuda() 即可。

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
# 或 device = torch.device("cuda:0")
device1 = torch.device("cuda:1")  
for batch_idx, (img, label) in enumerate(train_loader):
    img = img.to(device)
    label = label.to(device)

2. 对于模型来说,也使用 .to(device).cuda() 方法来将网络放到 GPU 显存中。

# 实例化网络
model = Net()
model.to(device)    # 使用序号为 0 的 GPU
# 或 model.to(device1)    # 使用序号为 1 的 GPU

二、多 GPU 加速

这里我们介绍单主机多 GPU 的情况,单主机多 GPU 主要采用的是 DataParallel 函数,而不是 DistributedParallel,后者一般用于多主机多 GPU ,当然也可用于单主机多 GPU 。使用多 GPU 训练的方式有很多,前提是我们的设备中存在两个及以上 GPU 。使用时直接用模型传入 torch.nn.DataParallel 函数即可,代码如下:

# 对于模型
net = torch.nn.DataParallel(model)

这时,默认所有存在的显卡都会被使用。如果你的电脑有很多显卡,但只想利用其中的部分,例如,只使用编号为 0 、1 、3 、4 的四个 GPU ,那么可以采用以下方式:

# 假设有 4 个 GPU ,其 id 设置如下
device_ids = [0, 1, 2, 3]
# 对于数据
input_data = input_data.to(device=device_ids[0])
# 对于模型
net = torch.nn.DataParallel(model)
net.to(device)

或者:

os.environ["CUDA_VISIBLE_DEVICES"] = ','.join(map(str, [0, 1, 2, 3]))
net = torch.nn.DataParallel(model)

说明:其中的 CUDA_VISIBLE_DEVICES 表示当前可以被 PyTorch 程序检测到的 GPU 。

下面为单机多 GPU 的实现代码:

1)背景说明。以波士顿房价数据为例,共 506 个样本,13 个特征。数据划分成训练集和测试集,然后用 data.DataLoader 将数据转换为可批加载的方式。采用 nn.DataParallel 并发机制,环境有 2 个 GPU 。当然,数据量很小,按理不宜用 nn.DataParallel 。

2)加载数据。

boston = load_boston()
X, y = (boston.data, boston.target)
dim = X.shape[1]

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
# 组合训练数据及标签
myset = list(zip(X_train, y_train))

3)把数据转换为批处理加载方式。批次大小为 128 ,打乱数据。

from torch.utils import data
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
dtype = torch.FloatTensor

train_loader = data.DataLoader(myset, batch_size=128, shuffle=True)

4)定义网络。

class Net1(nn.Module):
    """
    使用 Sequential() 函数构建网络,Sequential()函数的功能是将网络的层组合到一起
    """
    def __init__(self, in_dim, n_hidden_1, n_hidden_2, out_dim):
        super(Net1, self).__init__()
        self.layer1 = torch.nn.Sequential(nn.Linear(in_dim, n_hidden_1))
        self.layer2 = torch.nn.Sequential(nn.Linear(n_hidden_1, n_hidden_2))
        self.layer3 = torch.nn.Sequential(nn.Linear(n_hidden_2, out_dim))
        
 
    def forward(self, x):
        x1 = F.relu(self.layer1(x))
        x1 = F.relu(self.layer2(x1))
        x2 = self.layer3(x1)
        # 显示每个 GPU 分配的数据大小
        print("\tIn Model: input size", x.size(), "output size", x2.size())
        return x2

5)把模型转换为多 GPU 并发处理格式。

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
# 实例化网络
model = Net1(13, 16, 32, 1)
if torch.cuda.device_count() > 1:
    print("Let's use", torch.cuda.device_count(), "GPUs")
    # dim = 0 [64, xxx] -> [32, ...], [32, ...] on 2GPUs
    model = nn.DataParallel(model)

model.to(device)

运行的结果如下:

6)选择优化器及损失函数。

optimizer_orig = torch.optim.Adam(model.parameters(), lr=0.01)
loss_func = torch.nn.MSELoss()

7)模型训练,并可视化损失值。

from torch.utils.tensorboard import SummaryWriter
# from tensorboardX import SummaryWriter
writer = SummaryWriter(log_dir='logs')
for epoch in range(100):        
    model.train()
    for data, label in train_loader:
        input = data.type(dtype).to(device)
        label = label.type(dtype).to(device)
        output = model(input)       
        loss = loss_func(output, label)
        # 反向传播
        optimizer_orig.zero_grad()
        loss.backward()
        optimizer_orig.step()
        print("Outside: input size", input.size(), "output_size", output.size())
    writer.add_scalar('train_loss_paral', loss, epoch)

运行的部分结果如下:

从运行结果可以看出,一个批次数据( batch-size=128 )拆分成两份,每份大小为 64 ,分别放在不同的 GPU 上。此时用 GPU 监控也可以发现两个 GPU 同时在使用,如图 5-29 所示。

 8)通过 Web 页面查看损失值的变化情况,如图 5-30 所示。

图形中出现较大振幅是由于采用批次处理,而且数据没有做任何预处理,因此对数据进行规范化应该更平滑一些。

单主机多 GPU 也可使用 DistributedParallel 函数,虽然配置比使用 nn.DataParallel 函数稍微麻烦一点,但是训练速度和效果更好。

具体配置为:

# 初始化使用 nccl 后端
torch.distributed.init_process_group(backend="nccl")
# 模型并行化,使用多进程,可单机或分布式训练
model = torch.nn.parallel.DistributedDataParallel(model)

单主机运行时,使用下列方法启动:

python -m torch.distributed.launch main.py

参考代码:feiguyunai/Python-DL-PyTorch2/pytorch-05/pytorch-05-05.ipynb at main · Wumg3000/feiguyunai · GitHub

三、使用 GPU 的注意事项

使用 GPU 可以提升训练的速度,但如果使用不当,可能影响使用效率,具体注意事项如下:

• GPU 的数量尽量为偶数,奇数个 GPU 可能会出现异常中断的情况;

• GPU 训练速度很快,但数据量较小时,效果可能没有单 GPU 好,甚至还不如 CPU ;

• 如果内存不够大,使用多 GPU 训练的时候可通过设置 pin_memory 为 False,当然有时使用精度稍低的数据类型的效果也还行。

第五章の小结 

本章从机器学习的概念出发,首先说明其基本任务、一般流程等,然后说明在机器学习中解决过拟合、欠拟合的一些常用技巧或方法。同时介绍了各种激活函数、损失函数、优化器等机器学习、深度学习的核心内容。最后说明在程序中如何设置 GPU 设备、如何用 GPU 加速训练模型等内容。这章是深度学习的基础。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

今年做电商,视频号小店绝对是明智之举,未来风口就在这里

大家好,我是电商笨笨熊 电商一直是近几年的热门创业方向; 但是面对众多电商平台,对于普通玩家的我们来说,该怎么选择呢? 今年来说,我会更愿意选择视频号小店。 作为一个腾讯推出的电商项目,…

LeetCode例题讲解:移动044

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。 请注意 ,必须在不复制数组的情况下原地对数组进行操作。 示例 1: 输入: nums [0,1,0,3,12] 输出: [1,3,12,0,0] 示例 2: 输入: nums [0] 输出…

【STM32+HAL】DS18B20读取环境温度

一、准备工作 有关CUBEMX的初始化配置,参见我的另一篇blog:【STM32HAL】CUBEMX初始化配置 二、所用工具 1、芯片: STM32F407VET6 2、IDE: MDK-Keil软件 3、库文件:STM32F4xxHAL库 三、实现功能 串口打印当前温度值…

Day_3

1. HttpClient HttpClient是Apache的一个子项目&#xff0c;是高效的、功能丰富的支持HTTP协议的客户端编程工具包 作用&#xff1a;发送HTTP请求&#xff0c; 接受相应数据 <dependency><groupId>org.apache.httpcomponents</groupId><artifactId>…

Deep Learn Part Six Gated RNN-24.5.1

本章核心一句话&#xff1a; 卸下包袱&#xff0c;轻装上阵。--尼采 总述&#xff1a;本章所学内容 0.引子&#xff1a; 上一章介绍的 RNN 之所以不擅长学习时序数据的长期依赖关系&#xff0c;是因为 BPTT 会发生梯度消失和梯度爆炸的问题。本节我们将首先回顾一下上一章介…

21物联1班shift五次

1.选择推荐选项 2.等待 3.点击取消 4.选择查看问题详细信息 5.点击txt文件 6.找到system文件夹&#xff0c;将sethc改为qqq&#xff0c;将cmd文件改为sethc文件 7.单击完成。重新启动虚拟机。连续按五次shift出现cmd框&#xff0c;修改密码

MySql#MySql安装和配置

目录 一、卸载不需要的环境 二、安装mysql yum 源 三、开始安装 四、如果保证安装成功呢&#xff1f; 五、MySql 启动&#xff01; 六、登录mysql 七、配置文件说明 八、设置开机启动&#xff01; 本次安装是在Linux环境在centos7中完成 首先先将自己切换成root 一、…

彻底搞懂大小端存储and调试中内存窗口如何使用?

定义 首先我们有一个常识&#xff0c;Windows采用小端存储方式。 探究Windows下vs2019是什么存储&#xff1f; 在小端存储方式中&#xff0c;低字节存储在内存的低地址处&#xff0c;高字节存储在内存的高地址处。这与大端存储方式恰好相反&#xff0c;大端存储方式中高字节存…

[图解]DDD领域驱动设计浮夸,Eric Evans开了个坏头

0 00:00:00,630 --> 00:00:02,790 今天我们要讲的是 1 00:00:03,930 --> 00:00:07,420 DDD领域驱动设计浮夸 2 00:00:07,700 --> 00:00:10,590 Eric Evans开了个坏头 3 00:00:14,790 --> 00:00:17,380 在《领域驱动设计》的 4 00:00:18,650 --> 00:00:22,59…

QT:小项目:登录界面 (下一章连接数据库)

一、效果图 登录后&#xff1a; 二、项目工程结构 三、登录界面UI设计 四主界面 四、源码设计 login.h #ifndef LOGIN_H #define LOGIN_H#include <QDialog>namespace Ui { class login; }class login : public QDialog {Q_OBJECTpublic:explicit login(QWidge…

暴露自己IP地址有什么危险

暴露自己的IP地址确实存在一定的危险性&#xff0c;以下是关于这一问题的详细探讨&#xff1a; 一、IP地址的重要性 IP地址是互联网通信中的关键标识&#xff0c;它使得网络中的设备能够相互识别并进行数据传输。在网络世界中&#xff0c;每台设备都需要一个独特的IP地址来确…

2024蓝桥杯CTF writeUP--packet

根据流量分析&#xff0c;我们可以知道129是攻击机&#xff0c;128被留了php后门&#xff0c;129通过get请求来获得数据 129请求ls Respons在这 里面有flag文件 这里请求打开flag文件&#xff0c;并以base64编码流传输回来 获得flag的base64的数据 然后解码 到手

C语言 举例说明循环嵌套

今天 我们来说循环的嵌套 如果一个循环体内 又包含了另一个循环结构 我们称之为循环的嵌套 我们之前学的 While do-while for 都可以进行相互的嵌套 如下图 在 While 循环语句中再嵌套一个 While 循环语句 do-while 中嵌套 do-while for中嵌套 for 例如 我们做一个九九乘法…

mysql中varchar与bigint直接比较会导致精度丢失以至于匹配到多行数据

在mysql中&#xff0c;我们都知道如果一个索引字段使用了函数或者计算那么查询的时候索引会失效&#xff0c;可是我相信在联表的时候我们只会关注两个表关联字段是否都创建了索引&#xff0c;却没有关注过这两个字段的类型是否一致&#xff0c;如果不一致的话索引是会失效的&am…

Redis 实战3

系列文章目录 本文将从跳跃表的实现、整数集合来展开 Redis 实战 Ⅲ 系列文章目录跳跃表的实现跳跃表节点层 前进指针跨度 整数集合的实现升级升级的好处提升灵活性节约内存 降级整数集合 API总结 跳跃表的实现 Redis 的跳跃表由 redis.h/zskiplistNode 和 redis.h/zskiplist…

面向初学者:什么是图数据库

当数据成为关键生产要素&#xff0c;许多企业开始面临利用海量数据辅助企业复杂决策的现实难题。而在数据爆发式增长&#xff0c;关联复杂度激增的趋势下&#xff0c;图数据库成为企业加工关联数据、挖掘隐藏价值、智能决策升级的关键技术之一&#xff0c;在全球范围内开始被使…

如何更快地执行 Selenium 测试用例?

前言&#xff1a; 当我们谈论自动化时&#xff0c;首先想到的工具之一是 Selenium。我们都知道Selenium WebDriver 是一个出色的 Web 自动化工具。实施Selenium 自动化测试的主要原因是加速 selenium 测试。在大多数情况下&#xff0c;Selenium 的性能比手动的要好得多。但是&…

(2024,DONN,OCNN,复数域,交替的非线性激活层与振荡器层,复值反向传播)深度振荡神经网络

Deep Oscillatory Neural Network 公和众和号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0. 摘要 1. 简介 2. 方法 2.1 深度振荡神经网络&#xff08;DONN&#xff09; 2.2 振荡卷积神经网…

人物特效游戏玩法,门坎低,适合新手上手项目【揭密】

项目简介&#xff1a; 本项目涉及我们日常使用的美肤产品和效果维持&#xff0c;我们需要提交自己的作品&#xff0c;完成官方网站发布的任务。任务完成后&#xff0c;提交审核&#xff0c;一旦审批通过&#xff0c;收益就会到账。 项 目 地 址 &#xff1a; laoa1.cn/1961.…

Python-VBA函数之旅-round函数

目录 一、round函数的常见应用场景 二、round函数使用注意事项 三、如何用好round函数&#xff1f; 1、round函数&#xff1a; 1-1、Python&#xff1a; 1-2、VBA&#xff1a; 2、推荐阅读&#xff1a; 个人主页&#xff1a; https://blog.csdn.net/ygb_1024?spm1010.2…