工作汇报,龙岩seo公司首荐3火星,做ppt一般收费多少,分销小程序pytorch求导的初步认识
requires_grad
tensor(data, dtypeNone, deviceNone, requires_gradFalse)requires_grad是torch.tensor类的一个属性。如果设置为True#xff0c;它会告诉PyTorch跟踪对该张量的操作#xff0c;允许在反向传播期间计算梯度。
x.requires_grad 判…pytorch求导的初步认识
requires_grad
tensor(data, dtypeNone, deviceNone, requires_gradFalse)requires_grad是torch.tensor类的一个属性。如果设置为True它会告诉PyTorch跟踪对该张量的操作允许在反向传播期间计算梯度。
x.requires_grad 判断一个tensor是否可以求导返回布尔值
叶子变量-leaf variable
对于requires_gradFalse 的张量我们约定俗成地把它们归为叶子张量。对于requires_grad为True的张量如果他们是由用户创建的则它们是叶张量。 如果某一个叶子变量开始时不可导的后面想设置它可导该怎么办
x.requires_grad_(True/False) 设置tensor的可导与不可导
注意这种方法只适用于设置叶子变量否则会出现如下错误 x torch.tensor(2.0, requires_gradTrue)
y torch.pow(x, 2)
z torch.add(y, 3)
z.backward()
print(x.grad)
print(y.grad)
tensor(4.)
None创建一个浮点型张量x其值为2.0并设置requires_gradTrue使PyTorch可以跟踪x的计算历史并允许计算它的梯度。 创建一个新张量yy是x的平方。 创建一个新张量zz是y和3的和。 调用z.backward()进行反向传播计算z关于x的梯度。 打印x的梯度应该是2*x4.0。 试图打印y的梯度。但是PyTorch默认只计算并保留叶子节点的梯度。非叶子节点的梯度在计算过程中会被释放掉因此y的梯度应该为None。
保留中间变量的梯度
tensor.retain_grad() retain_grad()和retain_graph是用来处理两个不同的情况 retain_grad(): 用于保留非叶子节点的梯度。如果你想在反向传播结束后查看或使用非叶子节点的梯度你应该在非叶子节点上调用.retain_grad()。 retain_graph: 当你调用.backward()时PyTorch会自动清除计算图以释放内存。这意味着你不能在同一个计算图上多次调用.backward()。但是如果你需要多次调用.backward()例如在某些特定的优化算法中你可以在调用.backward()时设置retain_graphTrue来保留计算图。
.grad
通过tensor的grad属性查看所求得的梯度值。
.grad_fn
在PyTorch中.grad_fn属性是一个引用到创建该Tensor的Function对象。也就是说这个属性可以告诉你这个张量是如何生成的。对于由用户直接创建的张量它的.grad_fn是None。对于由某个操作创建的张量.grad_fn将引用到一个与这个操作相关的对象。
import torchx torch.tensor([1.0, 2.0], requires_gradTrue)
y x * 2
z y.mean()print(x.grad_fn)
print(y.grad_fn)
print(z.grad_fn)这里x是由用户直接创建的所以x.grad_fn是None。y是通过乘法操作创建的所以y.grad_fn是一个MulBackward0对象这表明y是通过乘法操作创建的。z是通过求平均数操作创建的所以z.grad_fn是一个MeanBackward0对象。 pytorch自动求导实现神经网络
numpy手动实现
import numpy as np
import matplotlib.pyplot as pltN, D_in, H, D_out 64, 1000, 100, 10 # 64个训练数据只是一个batch输入是1000维hidden是100维输出是10维随机创建一些训练数据
X np.random.randn(N, D_in)
y np.random.randn(N, D_out)W1 np.random.randn(D_in, H) # 1000维转成100维
W2 np.random.randn(H, D_out) # 100维转成10维learning_rate 1e-6all_loss []epoch 500for t in range(500): # 做500次迭代前向传播forward passh X.dot(W1) # N * Hh_relu np.maximum(h, 0) # 激活函数N * Hy_hat h_relu.dot(W2) # N * D_out计算损失函数compute lossloss np.square(y_hat - y).sum() # 均方误差忽略了÷Nprint(Epoch:{} Loss:{}.format(t, loss)) # 打印每个迭代的损失all_loss.append(loss)后向传播backward pass# 计算梯度此处没用torch用最普通的链式求导最终要得到 d{loss}/dXgrad_y_hat 2.0 * (y_hat - y) # d{loss}/d{y_hat}N * D_outgrad_W2 h_relu.T.dot(grad_y_hat) # 看前向传播中的第三个式子d{loss}/d{W2}H * D_outgrad_h_relu grad_y_hat.dot(W2.T) # 看前向传播中的第三个式子d{loss}/d{h_relu}N * Hgrad_h grad_h_relu.copy() # 这是h0时的情况d{h_relu}/d{h}1grad_h[h 0] 0 # d{loss}/d{h}grad_W1 X.T.dot(grad_h) # 看前向传播中的第一个式子d{loss}/d{W1}参数更新update weights of W1 and W2W1 - learning_rate * grad_W1W2 - learning_rate * grad_W2plt.plot(all_loss)
plt.xlabel(epoch)
plt.ylabel(Loss)
plt.show()
pytorch自动实现
import torchN, D_in, H, D_out 64, 1000, 100, 10 # 64个训练数据只是一个batch输入是1000维hidden是100维输出是10维随机创建一些训练数据
X torch.randn(N, D_in)
y torch.randn(N, D_out)W1 torch.randn(D_in, H, requires_gradTrue) # 1000维转成100维
W2 torch.randn(H, D_out, requires_gradTrue) # 100维转成10维learning_rate 1e-6for t in range(500): # 做500次迭代前向传播forward passy_hat X.mm(W1).clamp(min0).mm(W2) # N * D_out计算损失函数compute lossloss (y_hat - y).pow(2).sum() # 均方误差忽略了÷Nloss就是一个计算图computation graphprint(Epoch:{} Loss:{}.format(t, loss.item())) # 打印每个迭代的损失后向传播backward passloss.backward()参数更新update weights of W1 and W2with torch.no_grad():W1 - learning_rate * W1.gradW2 - learning_rate * W2.gradW1.grad.zero_()W2.grad.zero_()pytorch手动实现
import torch
import matplotlib.pyplot as pltN, D_in, H, D_out 64, 1000, 100, 10 # 64个训练数据只是一个batch输入是1000维hidden是100维输出是10维随机创建一些训练数据
X torch.randn(N, D_in)
y torch.randn(N, D_out)W1 torch.randn(D_in, H) # 1000维转成100维
W2 torch.randn(H, D_out) # 100维转成10维learning_rate 1e-6all_loss []for t in range(500): # 做500次迭代前向传播forward passh X.mm(W1) # N * Hh_relu h.clamp(min0) # 激活函数N * Hy_hat h_relu.mm(W2) # N * D_out计算损失函数compute lossloss (y_hat - y).pow(2).sum().item() # 均方误差忽略了÷Nprint(Epoch:{} Loss:{}.format(t, loss)) # 打印每个迭代的损失all_loss.append(loss)后向传播backward pass# 计算梯度此处没用torch用最普通的链式求导最终要得到 d{loss}/dXgrad_y_hat 2.0 * (y_hat - y) # d{loss}/d{y_hat}N * D_outgrad_W2 h_relu.t().mm(grad_y_hat) # 看前向传播中的第三个式子d{loss}/d{W2}H * D_outgrad_h_relu grad_y_hat.mm(W2.t()) # 看前向传播中的第三个式子d{loss}/d{h_relu}N * Hgrad_h grad_h_relu.clone() # 这是h0时的情况d{h_relu}/d{h}1grad_h[h 0] 0 # d{loss}/d{h}grad_W1 X.t().mm(grad_h) # 看前向传播中的第一个式子d{loss}/d{W1}参数更新update weights of W1 and W2W1 - learning_rate * grad_W1W2 - learning_rate * grad_W2plt.plot(all_loss)
plt.xlabel(epoch)
plt.ylabel(Loss)
plt.show()
torch.nn实现
import torch
import torch.nn as nn # 各种定义 neural network 的方法N, D_in, H, D_out 64, 1000, 100, 10 # 64个训练数据只是一个batch输入是1000维hidden是100维输出是10维随机创建一些训练数据
X torch.randn(N, D_in)
y torch.randn(N, D_out)model torch.nn.Sequential(torch.nn.Linear(D_in, H, biasTrue), # W1 * X b默认Truetorch.nn.ReLU(),torch.nn.Linear(H, D_out)
)# model model.cuda() #这是使用GPU的情况loss_fn nn.MSELoss(reductionsum)learning_rate 1e-4for t in range(500): # 做500次迭代前向传播forward passy_hat model(X) # model(X) model.forward(X), N * D_out计算损失函数compute lossloss loss_fn(y_hat, y) # 均方误差忽略了÷Nloss就是一个计算图computation graphprint(Epoch:{} Loss:{}.format(t, loss.item())) # 打印每个迭代的损失后向传播backward passloss.backward()参数更新update weights of W1 and W2with torch.no_grad():for param in model.parameters():param - learning_rate * param.grad # 模型中所有的参数更新model.zero_grad()
torch.nn的继承类
import torch
import torch.nn as nn # 各种定义 neural network 的方法
from torchsummary import summary
# pip install torchsummary
N, D_in, H, D_out 64, 1000, 100, 10 # 64个训练数据只是一个batch输入是1000维hidden是100维输出是10维随机创建一些训练数据
X torch.randn(N, D_in)
y torch.randn(N, D_out)定义两层网络class TwoLayerNet(torch.nn.Module):def __init__(self, D_in, H, D_out):super(TwoLayerNet, self).__init__()# 定义模型结构self.linear1 torch.nn.Linear(D_in, H, biasFalse)self.linear2 torch.nn.Linear(H, D_out, biasFalse)def forward(self, x):y_hat self.linear2(self.linear1(X).clamp(min0))return y_hatmodel TwoLayerNet(D_in, H, D_out)loss_fn nn.MSELoss(reductionsum)
learning_rate 1e-4
optimizer torch.optim.Adam(model.parameters(), lrlearning_rate)for t in range(500): # 做500次迭代前向传播forward passy_hat model(X) # model.forward(), N * D_out计算损失函数compute lossloss loss_fn(y_hat, y) # 均方误差忽略了÷Nloss就是一个计算图computation graphprint(Epoch:{} Loss:{}.format(t, loss.item())) # 打印每个迭代的损失optimizer.zero_grad() # 求导之前把 gradient 清空后向传播backward passloss.backward()参数更新update weights of W1 and W2optimizer.step() # 一步把所有参数全更新print(summary(model, (64, 1000)))