案例驱动,手把手教你学PyTorch(二)

news2024/11/23 7:54:02

通过案例学PyTorch。

扫码关注《Python学研大本营》,加入读者群,分享更多精彩

Autograd

Autograd 是 PyTorch 的自动微分包。多亏了它,我们不需要担心偏导数、链式法则或类似的东西。

那么,我们如何告诉 PyTorch 做它的事情并计算所有梯度呢?这就是backward()的好处。

你还记得计算梯度的起点吗?这是损失,因为我们根据我们的参数计算了它的偏导数。因此,我们需要从相应的 Python 变量调用backward()方法,例如,loss.backward().

梯度的实际值如何?我们可以通过查看张量的grad属性来检查它们。

如果您查看该方法的文档,它会清楚地说明梯度是累积的。因此,每次我们使用梯度来更新参数时,我们都需要在之后将梯度归零。这就是zero_()的好处。

方法名称末尾的下划线( _ )是什么意思?你还记得吗?如果没有,请滚动回上一节并找出答案。

因此,让我们放弃梯度的手动 计算,并同时使用backward()zero_()方法。

但是,总有一个问题,这次它与参数的更新有关……

lr = 1e-1
n_epochs = 1000

torch.manual_seed(42)
a = torch.randn(1, requires_grad=True, dtype=torch.float, device=device)
b = torch.randn(1, requires_grad=True, dtype=torch.float, device=device)

for epoch in range(n_epochs):
    yhat = a + b * x_train_tensor
    error = y_train_tensor - yhat
    loss = (error ** 2).mean()

    # No more manual computation of gradients! 
    # a_grad = -2 * error.mean()
    # b_grad = -2 * (x_tensor * error).mean()
    
    # We just tell PyTorch to work its way BACKWARDS from the specified loss!
    loss.backward()
    # Let's check the computed gradients...
    print(a.grad)
    print(b.grad)
    
    # What about UPDATING the parameters? Not so fast...
    
    # FIRST ATTEMPT
    # AttributeError: 'NoneType' object has no attribute 'zero_'
    # a = a - lr * a.grad
    # b = b - lr * b.grad
    # print(a)

    # SECOND ATTEMPT
    # RuntimeError: a leaf Variable that requires grad has been used in an in-place operation.
    # a -= lr * a.grad
    # b -= lr * b.grad        
    
    # THIRD ATTEMPT
    # We need to use NO_GRAD to keep the update out of the gradient computation
    # Why is that? It boils down to the DYNAMIC GRAPH that PyTorch uses...
    with torch.no_grad():
        a -= lr * a.grad
        b -= lr * b.grad
    
    # PyTorch is "clingy" to its computed gradients, we need to tell it to let it go...
    a.grad.zero_()
    b.grad.zero_()
    
print(a, b)

在第一次尝试中,如果我们使用与Numpy代码中相同的更新结构,我们将得到下面的奇怪错误……但我们可以通过查看张量本身来了解发生了什么——我们又一次“迷路”了梯度,同时将更新结果重新分配给我们的参数。因此,grad属性结果是,它引发了None错误……

# FIRST ATTEMPT
tensor([0.7518], device='cuda:0', grad_fn=<SubBackward0>)
AttributeError: 'NoneType' object has no attribute 'zero_'

然后,我们在第二次尝试中使用熟悉的就地 Python 赋值对其进行轻微更改。而且,PyTorch 再次抱怨并引发错误。

# SECOND ATTEMPT
RuntimeError: a leaf Variable that requires grad has been used in an in-place operation.

为什么?事实证明这是一个“好事太多”的案例。罪魁祸首是 PyTorch 能够从涉及任何梯度计算张量或其依赖项的每个Python 操作构建动态计算图。

我们将在下一节中深入探讨动态计算图的内部工作原理。

那么,我们如何告诉 PyTorch “后退”并让我们更新参数而不弄乱其花哨的动态计算图?这torch.no_grad()就是好处。它允许我们独立于 PyTorch 的计算图对张量执行常规 Python 操作。

最后,我们成功地运行了我们的模型并获得了结果参数。果然,它们与我们在Numpy- only 实现中得到的匹配。

# THIRD ATTEMPT
tensor([1.0235], device='cuda:0', requires_grad=True) tensor([1.9690], device='cuda:0', requires_grad=True)

动态计算图

“不幸的是,没有人能知道动态计算图是什么。你必须亲自去看看。”

PyTorchViz包及其make_dot(variable)方法使我们能够轻松地可视化与给定 Python 变量关联的图形。

所以,让我们坚持最低限度:两个(梯度计算)张量用于我们的参数、预测、误差和损失。

torch.manual_seed(42)
a = torch.randn(1, requires_grad=True, dtype=torch.float, device=device)
b = torch.randn(1, requires_grad=True, dtype=torch.float, device=device)

yhat = a + b * x_train_tensor
error = y_train_tensor - yhat
loss = (error ** 2).mean()

如果我们调用make_dot(yhat),我们将得到下面图 3 中最左边的图表:

让我们仔细看看它的组件:

  • 蓝色框:这些对应于我们用作参数的张量,我们要求 PyTorch 为其计算梯度的张量;

  • 灰色框:涉及梯度计算张量或其依赖项的Python 操作;

  • 绿色框:与灰框相同,除了它是计算梯度的起点(假设该backward()方法是从用于可视化图形的变量调用的)——它们是从图形中自下而上计算的。

如果我们为error(中心)和loss(右)变量绘制图表,它们与第一个变量之间的唯一区别是中间步骤的数量(灰色框)。

现在,仔细看看最左边图表的绿色框:有两个箭头指向它,因为它是将两个变量ab*x的和相加。看起来很明显,对吧?

然后,看同一个图的灰色框:它在进行乘法运算,即b*x。但是只有一个箭头指向它!箭头来自与我们的参数b对应的蓝色 框。

为什么我们的数据x没有一个盒子?答案是:我们不为它计算梯度!因此,即使计算图执行的操作涉及更多张量,它也仅显示梯度计算张量及其依赖项。

如果我们为参数a的requires_grad设置为False,计算图会发生什么情况?

不出所料,参数a对应的蓝色框没有了!足够简单:没有梯度,没有图形。

动态计算图的最大优点是您可以根据需要将其复杂化。您甚至可以使用控制流语句(例如,if 语句)来控制梯度流。

下面的图 5 显示了一个示例。

优化器

到目前为止,我们一直在使用计算出的梯度手动更新参数。这对于两个参数来说可能没问题……但是如果我们有很多参数怎么办?!我们使用 PyTorch 的优化器之一,例如SGD或Adam。

优化器获取我们想要更新的参数、我们想要使用的学习率(可能还有许多其他超参数!)并通过其step()方法执行 更新。

此外,我们也不再需要将梯度一一归零了。我们只需调用优化器的zero_grad()方法就可以了!

在下面的代码中,我们创建了一个随机梯度下降(SGD) 优化器来更新我们的参数a和b。

不要被优化器的名字所迷惑:如果我们一次使用所有训练数据进行更新——就像我们在代码中实际做的那样——优化器正在执行批量梯度下降,不管它的名字是什么。

PyTorch 的优化器在行动——不再需要手动更新参数!

torch.manual_seed(42)
a = torch.randn(1, requires_grad=True, dtype=torch.float, device=device)
b = torch.randn(1, requires_grad=True, dtype=torch.float, device=device)
print(a, b)

lr = 1e-1
n_epochs = 1000

# Defines a SGD optimizer to update the parameters
optimizer = optim.SGD([a, b], lr=lr)

for epoch in range(n_epochs):
    yhat = a + b * x_train_tensor
    error = y_train_tensor - yhat
    loss = (error ** 2).mean()

    loss.backward()    
    
    # No more manual update!
    # with torch.no_grad():
    #     a -= lr * a.grad
    #     b -= lr * b.grad
    optimizer.step()
    
    # No more telling PyTorch to let gradients go!
    # a.grad.zero_()
    # b.grad.zero_()
    optimizer.zero_grad()
    
print(a, b)

让我们检查一下之前和之后的两个参数,以确保一切正常:

# BEFORE: a, b
tensor([0.6226], device='cuda:0', requires_grad=True) tensor([1.4505], device='cuda:0', requires_grad=True)
# AFTER: a, b
tensor([1.0235], device='cuda:0', requires_grad=True) tensor([1.9690], device='cuda:0', requires_grad=True)

我们优化了优化过程。还剩下什么?

Lose

我们现在处理损失计算。正如预期的那样,PyTorch 再次让我们受益匪浅。根据手头的任务,有许多损失函数可供选择。由于我们的是回归,因此我们使用均方误差 (MSE) 损失。

请注意,这nn.MSELoss实际上为我们创建了一个损失函数——它不是损失函数本身。此外,您可以指定要应用的缩减方法,也就是说,您希望如何聚合各个点的结果——您可以对它们进行平均 (reduction='mean') 或简单地将它们相加 (reduction='sum') .

然后,我们稍后在第 20 行使用创建的损失函数来计算给定预测和标签的损失。

我们的代码现在看起来像这样:

torch.manual_seed(42)
a = torch.randn(1, requires_grad=True, dtype=torch.float, device=device)
b = torch.randn(1, requires_grad=True, dtype=torch.float, device=device)
print(a, b)

lr = 1e-1
n_epochs = 1000

# Defines a MSE loss function
loss_fn = nn.MSELoss(reduction='mean')

optimizer = optim.SGD([a, b], lr=lr)

for epoch in range(n_epochs):
    yhat = a + b * x_train_tensor
    
    # No more manual loss!
    # error = y_tensor - yhat
    # loss = (error ** 2).mean()
    loss = loss_fn(y_train_tensor, yhat)

    loss.backward()    
    optimizer.step()
    optimizer.zero_grad()
    
print(a, b)

此时,只剩下一段代码需要更改:predictions。然后是时候介绍 PyTorch 的实现方式了。

推荐书单

《PyTorch深度学习简明实战 》

本书针对深度学习及开源框架——PyTorch,采用简明的语言进行知识的讲解,注重实战。全书分为4篇,共19章。深度学习基础篇(第1章~第6章)包括PyTorch简介与安装、机器学习基础与线性回归、张量与数据类型、分类问题与多层感知器、多层感知器模型与模型训练、梯度下降法、反向传播算法与内置优化器。计算机视觉篇(第7章~第14章)包括计算机视觉与卷积神经网络、卷积入门实例、图像读取与模型保存、多分类问题与卷积模型的优化、迁移学习与数据增强、经典网络模型与特征提取、图像定位基础、图像语义分割。自然语言处理和序列篇(第15章~第17章)包括文本分类与词嵌入、循环神经网络与一维卷积神经网络、序列预测实例。生成对抗网络和目标检测篇(第18章~第19章)包括生成对抗网络、目标检测。

本书适合人工智能行业的软件工程师、对人工智能感兴趣的学生学习,同时也可作为深度学习的培训教程。

作者简介:

日月光华:网易云课堂资深讲师,经验丰富的数据科学家和深度学习算法工程师。擅长使用Python编程,编写爬虫并利用Python进行数据分析和可视化。对机器学习和深度学习有深入理解,熟悉常见的深度学习框架( PyTorch、TensorFlow)和模型,有丰富的深度学习、数据分析和爬虫等开发经验,著有畅销书《Python网络爬虫实例教程(视频讲解版)》。

链接(新书限时5.5折):https://item.jd.com/13528847.html

精彩回顾

《Pandas1.x实例精解》新书抢先看!

【第1篇】利用Pandas操作DataFrame的列与行

【第2篇】Pandas如何对DataFrame排序和统计

【第3篇】Pandas如何使用DataFrame方法链

【第4篇】Pandas如何比较缺失值以及转置方向?

【第5篇】DataFrame如何玩转多样性数据

【第6篇】如何进行探索性数据分析?

【第7篇】使用Pandas处理分类数据

【第8篇】使用Pandas处理连续数据

【第9篇】使用Pandas比较连续值和连续列

【第10篇】如何比较分类值以及使用Pandas分析库

扫码关注《Python学研大本营》,加入读者群,分享更多精彩

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

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

相关文章

python在线及离线安装库

目录 一、配置python环境变量&#xff1a; 二、在线安装python库&#xff1a; 三、离线安装python库&#xff1a; 一、配置python环境变量&#xff1a; 1、以windows10为例&#xff0c;右键电脑->>属性: 2、选择高级系统设置&#xff1a; 3、选择环境变量&#xff1a…

八行代码一键照片转漫画

有些小程序可以实现照片转漫画的功能&#xff0c;本文和你一起来探索其背后的原理。用Python实现八行代码一键照片转漫画。    文章目录一、效果展示二、代码详解1 导入库2 照片转漫画一、效果展示 在介绍代码之前&#xff0c;先来看下本文的实现效果。    喜欢的小伙伴也…

操作系统主引导扇区代码是如何被加载到内存的?

1. 问题&#xff1a;OS引导代码为什么需要org 07c00h&#xff1f; 在前几天在知乎上的的一个回答《想带着学生做一个操作系统&#xff0c;可行性有多大&#xff1f;》中&#xff0c;我们引用了一段主引导扇区MBR中的操作系统加载代码&#xff1a; org 07c00h ; 告诉编译器程…

PCA实现降维的过程

PCA将相关性高的变量转变为较少的独立新变量&#xff0c;实现用较少的综合指标分别代表存在于各个变量中的各类信息&#xff0c;既减少高维数据的变量维度&#xff0c;又尽量降低原变量数据包含信息的损失程度&#xff0c;是一种典型的数据降维方法。PCA保留了高维数据最重要的…

web前端期末大作业 HTML+CSS+JavaScript仿京东

⛵ 源码获取 文末联系 ✈ Web前端开发技术 描述 网页设计题材&#xff0c;DIVCSS 布局制作,HTMLCSS网页设计期末课程大作业 | 在线商城购物 | 水果商城 | 商城系统建设 | 多平台移动商城 | H5微商城购物商城项目| HTML期末大学生网页设计作业&#xff0c;Web大学生网页 HTML&am…

SpringBoot发送邮件

06.发送邮件 在使用javaSE时&#xff0c;我们会发现发送邮件较为麻烦&#xff0c;而在SpringBoot中&#xff0c;发送邮件就变成一件较为简单的时。 导入mail的maven的启动类。 <dependency><groupId>org.springframework.boot</groupId><artifactId>…

DSPE PEG Azide, DSPE-PEG-N3;磷脂聚乙二醇叠氮

中文名称&#xff1a;磷脂聚乙二醇叠氮(DSPE-PEG-N3) 中文别名&#xff1a;N-二硬脂酰磷脂酰乙酰胺-PEG-叠氮 磷脂PEG叠氮 英文名称&#xff1a;DSPE PEG Azide, DSPE-PEG-N3 性状&#xff1a;根据不同的分子量为固体或者粘稠液体。 溶剂&#xff1a;溶于DCM&#xff0c;…

表单标签。。

一、任务目标 掌握表单标签及其属性的使用 二、任务背景 HTML表单用于收集用户输入。表单元素指的是不同类型的 input 元素、复选框、单选按钮、提交按钮等。 三、任务内容 1、<form></form>标签 用于创建HTML表单&#xff0c;常用属性如下&#xff1a; action&…

OpenGL ES 学习(一) -- 基本概念

最近在研究 SurfaceView 和 TextureView&#xff0c;发现栅格化这东西&#xff0c;一直没怎么搞明白&#xff0c;一搜都是关于 OpenGL 的&#xff0c;没办法&#xff0c;当初也是要学习这个&#xff0c;现在重试拾起。 之前接触 OpenGL &#xff0c;是主要解决一个渲染模糊问题…

JavaEE-操作系统

✏️作者&#xff1a;银河罐头 &#x1f4cb;系列专栏&#xff1a;JavaEE &#x1f332;“种一棵树最好的时间是十年前&#xff0c;其次是现在” 目录操作系统介绍操作系统的定位进程进程控制块内存管理进程间通信思维导图总结操作系统介绍 操作系统是一组做计算机资源管理的软…

文献学习01_Attention Is All You Need_20221119

论文信息 Subjects: Computation and Language (cs.CL); Machine Learning (cs.LG) &#xff08;1&#xff09;题目&#xff1a;Attention Is All You Need &#xff08;你需要的就是关注&#xff09; &#xff08;2&#xff09;文章下载地址&#xff1a;https://doi.org/10.4…

今天给大家介绍一篇基于javaWeb的汽车订票系统的设计与实现

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…

牛客网之SQL非技术快速入门(3)-排序、关联关系

知识点&#xff1a; &#xff08;1&#xff09;order by colunm_name(s) ASC|DESC order by ID ASC,name ASC,sex DESC 不写就是默认升序&#xff0c;DESC降序 &#xff08;2&#xff09;3中关联关系&#xff1a;left join、right join、inner join/join 21、现在运营想要查…

【微信开发第四章】SpringBoot实现微信H5支付

前言 在进行微信公众号业务开发的时候,微信支付可以说是非常重要的一环。该篇文章每一步都有记录&#xff0c;力争理解的同时各位小伙伴也能够实现功能 文章目录前言1、公众号配置2、微信支付实现代码总结1、公众号配置 1、绑定域名 先登录微信公众平台进入“设置与开发”&…

阿里云架构实战之ALB(应用型负载均衡)介绍与搭建

ALB介绍 服务器端负载均衡SLB&#xff08;Server Load Balancer&#xff09;是一种对流量进行按需分发的服务&#xff0c;通过将流量分发到不同的后端服务来扩展应用系统的服务吞吐能力&#xff0c;并且可以消除系统中的单点故障&#xff0c;提升应用系统的可用性。 阿里云负…

代码随想录算法训练营第60天 | 一刷结束篇 84.柱状图中最大的矩形

代码随想录系列文章目录 一刷总结篇 文章目录代码随想录系列文章目录84.柱状图中最大的矩形dp 普通思路单调栈一刷总结篇84.柱状图中最大的矩形 题目链接 这道题和接雨水是两个相似的题&#xff0c;相辅相成的那种&#xff0c;双指针是过不了力扣的会超时&#xff0c;所以我也…

pandas提取键值对(json和非json格式)

&#xff08;欢迎大家关注我的公众号“机器学习面试基地”&#xff0c;之后将在公众号上持续记录本人从非科班转到算法路上的学习心得、笔经面经、心得体会。未来的重点也会主要放在机器学习面试上&#xff01;&#xff09; 最近工作中需要解析一些有模型输入输出信息的csv日志…

SpringBoot+Mybaits搭建通用管理系统实例七:访问接口Api层功能实现

一、本章内容 系统api接口层实现,实现系统对外接口相应功能定义及实现,并通过Swagger实现接口文档的自动生成。 完整课程地址 二、开发视频 SpringBoot+Mybaits搭建通用管理系统实例二:api层实现 三、代码实现 使用基类的方式实现各方法接口的抽象实现,使用泛型的方式指定具…

linux上配置jdk和maven环境 (deepin适用)

前言 安装那些&#xff0c;就不说了&#xff0c;应该大家都下好才来配置的&#xff0c;下载安装的话&#xff0c;直接解压到一个目录就好&#xff0c;给个链接给你 jdk8下载链接&#xff1a; https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html 命…

Docker Buildkit(新增 --mount、--security、--network 等特性)

BuildKit是Docker官方社区推出的下一代镜像构建神器。 可以更加快速&#xff0c;有效&#xff0c;安全地构建docker 镜像&#xff0c;自 docker v18.06 版本起已经集成了该组件。 Buildkit 是下一代 docker 构建组件&#xff0c;拥有众多特性&#xff1a; 自动垃圾收集可扩展…