电商网站建设公司,网站开发未按合同约定工期完工,模板网站官网,微楼书网站建设引言
前序学习进程中#xff0c;已经对pytorch基本运算中的求导进行了基础讨论#xff0c;相关文章链接为#xff1a;
导数运算pytorch基本运算-导数和f-string-CSDN博客
实际上#xff0c;求导是微分的进一步计算#xff0c;要想求导的前一步其实是计算微分#xff1…引言
前序学习进程中已经对pytorch基本运算中的求导进行了基础讨论相关文章链接为
导数运算pytorch基本运算-导数和f-string-CSDN博客
实际上求导是微分的进一步计算要想求导的前一步其实是计算微分
导数表达式 f ′ ( x ) 或 d y d x f^{}(x) 或 \frac{dy}{dx} f′(x)或dxdy 微分表达式 f ′ ( x ) d x 或 d y f ′ ( x ) d x f^{}(x) dx 或 {dyf^{}(x) dx} f′(x)dx或dyf′(x)dx 导数是某一点处的变化率微分是某一点附近的变化量。 如果一个函数在多个点进行导数求解或者说子安多维度上进行导数计算实际上就是在求梯度。
pytorch自动微分获取梯度
为完整展示pytorch的梯度计算功能将测试分为以下部分。
初始定义
首先是引入模块完成变量定义
# 导入模块
import torch
# 定义变量
xtorch.arange(3.0)
print(x,x)这里的输出结果是 x tensor([0., 1., 2.]) 需要说明的是因为pytorch默认对浮点数进行求导所以定义变量的时候pyorch.arange()使用了3.0而不是整数3。 紧接着需要对变量执行梯度运算。
梯度运算标定
梯度运算标定的目的是声明要对x进行梯度运算。任何没有经过提前标定的量都不能正常执行梯度运算。
# 标记需要对x进行梯度计算
zx.requires_grad_(True)
print(z,z)梯度标定使用requires_grad_(True)就像对话一样需要求梯度_(需要)。 代码运行的效果为 z tensor([0., 1., 2.], requires_gradTrue) 下一步是定义一个函数。
函数定义
这里定义一个简单函数 f ( x ) 2 x 2 f(x)2x^{2} f(x)2x2 具体定义代码为
# 点乘定义
m2*torch.dot(x,x)
print(m,m)计算微分对函数开展才有意义所以必须定义函数这里只是一个示例也可以是其他函数。 torch.dot()函数的计算规则为对位相乘然后求和。 代码运行效果为 m tensor(10., grad_fn) 这里输出了两个部分 第一部分是10就是元素对位相乘后求和的效果2X0X02X1X12X2X210。 第二部分是grad_fngrad_fn的意思是grad_function就是求导函数的意思后面的MulBackward0是对求导函数的具体定义。 MulBackward0 表示这是一个乘法操作的梯度函数具体拆开来multiplication-backward字面意思解释乘法-反向传播。 这就是pytorch自动微分的核心机制它可以自动测算求导函数的类型比如这是一个自变量相乘的函数并且指出要用哪种方法比如这里要用反向传播法。 到这一步还无法计算微分只是通过输出效果知道用反向传播方法计算微分然后就是正式使用反向传播方法计算微分。
梯度计算
微分计算使用的代码为
# 执行梯度运算
nm.backward()
kx.grad
print(n,n)
print(k,k)这里用了两步第一步是定义对函数m调用backward方法求倒数然后具体是对x求导数所获得计算结果为 n None k tensor([0., 4., 8.]) n对应的其实是方法定义k才是具体的对x的求导效果。
实际上到这一步如何用pytorch直接计算导数已经非常清晰先要标定梯度计算的变量然后要对函数声明梯度计算的方法最后直接计算梯度。完整代码为
# 导入模块
import torch
# 定义变量
xtorch.arange(3.0)
print(x,x)
# 标记需要对x进行梯度计算
zx.requires_grad_(True)
print(z,z)
# 点乘定义
m2*torch.dot(x,x)
print(m,m)
# 执行梯度运算
nm.backward()
kx.grad
print(n,n)
print(k,k)新的函数
未计算对新函数进行求导运算需要提前将梯度清零避免梯度计算效果彼此叠加出现预料之外的效果。
梯度清零
代码为
# 梯度清零
kkx.grad.zero_()
print(kk,kk)代码运行效果为 kk tensor([0., 0., 0.]) 定义新函数
代码为
# 定义新函数
hhx.sum()
print(hh,hh)这里使用了求和函数sim()代码运行效果为 hh tensor(3., grad_fn) 这里也输出了两个部分 第一部分是3就是元素求和的效果0123。 第二部分是grad_fngrad_fn的意思是grad_function就是求导函数的意思后面的SumBackward0是对求导函数的具体定义。 SumBackward0 表示这是一个加法操作的梯度函数具体拆开来Sum-backward字面意思解释加法-反向传播。
导数计算
此时可以直接计算导数代码为
# 定义用backward方法计算导数
nnhh.backward()
print(nn,nn)
# 导数计算
ttx.grad
print(tt,tt)代码运行效果为 nn None tt tensor([1., 1., 1.]) 因为是各个变量直接叠加所以每个变量前的系数都是1所以导数运算的结果是[1.0,1.0,1.0]. 此时的完整代码为
# 导入模块
import torch
# 定义变量
xtorch.arange(3.0)
print(x,x)
# 标记需要对x进行梯度计算
zx.requires_grad_(True)
print(z,z)
# 点乘定义
m2*torch.dot(x,x)
print(m,m)
# 执行梯度运算
nm.backward()
kx.grad
print(n,n)
print(k,k)
# 梯度清零
kkx.grad.zero_()
print(kk,kk)
# 定义新函数
hhx.sum()
print(hh,hh)
# 定义用backward方法计算导数
nnhh.backward()
print(nn,nn)
# 导数计算
ttx.grad
print(tt,tt)完整的输出效果为 x tensor([0., 1., 2.]) z tensor([0., 1., 2.], requires_gradTrue) m tensor(10., grad_fn) n None k tensor([0., 4., 8.]) kk tensor([0., 0., 0.]) hh tensor(3., grad_fn) nn None tt tensor([1., 1., 1.]) 梯度清零操作的讨论
前述有一个梯队清零的操作如果没有这步操作输出效果会如何变化这里直接给出完整代码来测试。给出完整代码为
# 导入模块
import torch
# 定义变量
xtorch.arange(3.0)
print(x,x)
# 标记需要对x进行梯度计算
zx.requires_grad_(True)
print(z,z)
# 点乘定义
m2*torch.dot(x,x)
print(m,m)
# 执行梯度运算
nm.backward()
kx.grad
print(n,n)
print(k,k)
# 梯度清零
#kkx.grad.zero_()
#print(kk,kk)
# 定义新函数
hhx.sum()
print(hh,hh)
# 定义用backward方法计算导数
nnhh.backward()
print(nn,nn)
# 导数计算
ttx.grad
print(tt,tt)此时的输出效果为 x tensor([0., 1., 2.]) z tensor([0., 1., 2.], requires_gradTrue) m tensor(10., grad_fn) n None k tensor([0., 4., 8.]) hh tensor(3., grad_fn) nn None tt tensor([1., 5., 9.]) 这里可以看到sum()函数的梯度输出为[1.,5.,9.]这个结果的来源其实是[0., 4., 8.][1., 1., 1.][1., 5., 9.]。 此处可见及时将梯度清零很有必要。
总结
掌握了通过pythonpytorch执行梯度运算的基本技巧。