深度学习19:PyTorch:自动微分模块

目录标题

一、概念

训练神经网络时,框架会根据设计好的模型构建一个计算图(computational graph),来跟踪计算是哪些数据通过哪些操作组合起来产生输出,并通过反向传播算法来根据给定参数的损失函数的梯度调整参数(模型权重)。

PyTorch 具有一个内置的微分引擎 torch.autograd 以支持计算图的梯度自动计算。

考虑最简单的单层神经网络,具有输入 x、参数 w、偏置 b 以及损失函数:

二、代码

python 复制代码
import torch
x = torch.tensor(10.0)
y = torch.tensor([[3.0]])
print(x)
print(y)
#初始化参数
w = torch.rand(1,1,requires_grad=True)
b = torch.rand(1,1,requires_grad=True)
#前向传播,得到输出
z = x * w + b
print(z)
#查看是否是叶子节点
print(x.is_leaf)
print(w.is_leaf)
print(b.is_leaf)
print(y.is_leaf)
print(z.is_leaf)
#设置损失函数
loss = torch.nn.MSELoss()
loss_value = loss(z,y)
print(loss_value)
print(loss_value.is_leaf)
#反向传播
loss_value.backward(retain_graph=True)
print(w.grad)
print(b.grad)

三、代码底层涉及内容

自动微分的关键就是记录节点的数据与运算。数据记录在张量的 data 属性中,计算记录在张量的 grad_fn 属性中。

计算图根据搭建方式可分为静态图和动态图,PyTorch 是动态图机制,在计算的过程中逐步搭建计算图,同时对每个 Tensor 都存储 grad_fn 供自动微分使用。

若设置张量参数 requires_grad=True,则 PyTorch 会追踪所有基于该张量的操作,并在反向传播时计算其梯度。依赖于叶子节点的节点,requires_grad 默认为 True。当计算到根节点后,在根节点调用 backward() 方法即可反向传播计算计算图中所有节点的梯度。

非叶子节点的梯度在反向传播之后会被释放掉(除非设置参数 retain_graph=True)。而叶子节点的梯度在反向传播之后会保留(累积)。通常需要使用 optimizer.zero_grad() 清零参数的梯度

四、想把其中计算图里面的张量临时拿出来处理

前向传播没问题,但是反向传播,如果某个节点有分支,分出来两条路,按照全微分公式把两个导数相加

有时我们希望将某些计算移动到计算图之外,可以使用 Tensor.detach()返回一个新的变量,该变量与原变量具有相同的值,但丢失计算图中如何计算原变量的信息。换句话说,梯度不会在该变量处继续向下传播。

代码介绍detach

python 复制代码
import torch
x = torch.tensor(2.0,requires_grad=True)
y = x.detach()
print(x)
print(y)
print(id(x))
print(id(y))
print('-------------')
#use tensor.untyped_storage() instead of tensor.storage()
# print(x.storage().data_ptr())
# print(y.storage().data_ptr())
#数据共享
print(x.untyped_storage().data_ptr())
print(y.untyped_storage().data_ptr())

tensor(2., requires_grad=True)
tensor(2.)
2654791112800
2654791113680
-------------
3408417266880
3408417266880




#分别对x,y进行后续计算
z1 = x ** 2
z2 = y ** 2
print(z1)
print(z2)

tensor(4., grad_fn=<PowBackward0>)
tensor(4.)


#用sum当损失函数,可以反向传播
z1.sum().backward()
#z2 报错 element 0 of tensors does not require grad and does not have a grad_fn
z2.sum().backward()

五、detach实际应用

python 复制代码
x = torch.ones(2,2,requires_grad=True)
y = x * x
print(x)
print(y)

#分离y
u = y.detach()

tensor([[1., 1.],
        [1., 1.]], requires_grad=True)
tensor([[1., 1.],
        [1., 1.]], grad_fn=<MulBackward0>)


#让u参与新张量的计算
z = u * x
#反向传播,计算所有梯度
z.sum().backward()
print(x.grad)
print('------------')
print(x.grad == u)


tensor([[1., 1.],
        [1., 1.]])
------------
tensor([[True, True],
        [True, True]])

这里u不是3x*2

六、detach vs data 修改数据,影响各自原数据的反向传播(但是detach修改微分引擎能发现,data却发现不了)

修改data数据最好只读取不修改,自动微分引擎发现不了,不会报错

修改detach数据最好只读取不修改,自动微分引擎会发现,会报错

相关推荐
TMT星球1 小时前
“什么值得买”兴趣消费服务接入乐奇AI眼镜,开启“看见即搜索”新体验
人工智能
乌恩大侠1 小时前
Supermicro 发布六款 NVIDIA ARC 服务器:从 1U 边缘基站到 4U 八卡 AI-RAN 平台,全面对比
运维·服务器·人工智能
辛迪聊物业数字化2 小时前
物业费收缴率从68%提升到97%落地复盘:中小物业收费系统选型避坑指南
人工智能·嵌入式硬件·物联网·网络协议·系统架构
科技之门2 小时前
大捷智能携手中科曙光打造工业AI设计超级云平台——AI设计应用进入快车道!
人工智能
4SAPI2 小时前
营销内容生成大模型 API 生产选型指南:4SAPI、硅基流动与 OpenRouter 的架构权衡
数据库·人工智能·架构·php
lazy熊2 小时前
AI 编程工具跑通后,第一条任务应该怎么写?
人工智能
天树星智源2 小时前
J-Comm:不传文本传雅可比坐标,token 省下 74.8%
人工智能·机器人·大模型
谢白羽2 小时前
从传统运维到 AI Infra: K8s 上调度 100 张 GPU踩坑笔记
运维·人工智能·缓存·kubernetes·vllm·sglang·vllm-omni
镜子AI2 小时前
镜子AI工程实践:用熵权法 + TOPSIS 做多方案选型排序(零依赖 Python)
开发语言·人工智能·python