pytorch求导

pytorch求导的初步认识

requires_grad

tensor(data, dtype=None, device=None, requires_grad=False)

requires_grad是torch.tensor类的一个属性。如果设置为True,它会告诉PyTorch跟踪对该张量的操作,允许在反向传播期间计算梯度。

x.requires_grad    判断一个tensor是否可以求导,返回布尔值

叶子变量-leaf variable

  • 对于requires_grad=False 的张量,我们约定俗成地把它们归为叶子张量。
  • 对于requires_grad为True的张量,如果他们是由用户创建的,则它们是叶张量。

 如果某一个叶子变量,开始时不可导的,后面想设置它可导,该怎么办?

x.requires_grad_(True/False)   设置tensor的可导与不可导

注意:这种方法只适用于设置叶子变量,否则会出现如下错误

x = torch.tensor(2.0, requires_grad=True)
y = torch.pow(x, 2)
z = torch.add(y, 3)
z.backward()
print(x.grad)
print(y.grad)
tensor(4.)
None
  1. 创建一个浮点型张量x,其值为2.0,并设置requires_grad=True,使PyTorch可以跟踪x的计算历史并允许计算它的梯度。

  2. 创建一个新张量y,y是x的平方。

  3. 创建一个新张量z,z是y和3的和。

  4. 调用z.backward()进行反向传播,计算z关于x的梯度。

  5. 打印x的梯度,应该是2*x=4.0。

  6. 试图打印y的梯度。但是,PyTorch默认只计算并保留叶子节点的梯度非叶子节点的梯度在计算过程中会被释放掉,因此y的梯度应该为None。

保留中间变量的梯度

tensor.retain_grad()

 retain_grad()retain_graph是用来处理两个不同的情况

  1. retain_grad(): 用于保留非叶子节点的梯度。如果你想在反向传播结束后查看或使用非叶子节点的梯度,你应该在非叶子节点上调用.retain_grad()

  2. retain_graph: 当你调用.backward()时,PyTorch会自动清除计算图以释放内存。这意味着你不能在同一个计算图上多次调用.backward()。但是,如果你需要多次调用.backward()(例如在某些特定的优化算法中),你可以在调用.backward()时设置retain_graph=True保留计算图

.grad

通过tensor的grad属性查看所求得的梯度值。

.grad_fn

在PyTorch中,.grad_fn属性是一个引用到创建该Tensor的Function对象。也就是说,这个属性可以告诉你这个张量是如何生成的。对于由用户直接创建的张量,它的.grad_fnNone。对于由某个操作创建的张量,.grad_fn将引用到一个与这个操作相关的对象

import torchx = torch.tensor([1.0, 2.0], requires_grad=True)
y = x * 2
z = y.mean()print(x.grad_fn)
print(y.grad_fn)
print(z.grad_fn)

这里,x是由用户直接创建的,所以x.grad_fnNoney是通过乘法操作创建的,所以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 pass)'''h = X.dot(W1)  # N * Hh_relu = np.maximum(h, 0)  # 激活函数,N * Hy_hat = h_relu.dot(W2)  # N * D_out'''计算损失函数(compute loss)'''loss = np.square(y_hat - y).sum()  # 均方误差,忽略了÷Nprint("Epoch:{}   Loss:{}".format(t, loss))  # 打印每个迭代的损失all_loss.append(loss)'''后向传播(backward pass)'''# 计算梯度(此处没用torch,用最普通的链式求导,最终要得到 d{loss}/dX)grad_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()  # 这是h>0时的情况,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 W2)'''W1 -= 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_grad=True)  # 1000维转成100维
W2 = torch.randn(H, D_out, requires_grad=True)  # 100维转成10维learning_rate = 1e-6for t in range(500):  # 做500次迭代'''前向传播(forward pass)'''y_hat = X.mm(W1).clamp(min=0).mm(W2)  # N * D_out'''计算损失函数(compute loss)'''loss = (y_hat - y).pow(2).sum()  # 均方误差,忽略了÷N,loss就是一个计算图(computation graph)print("Epoch:{}   Loss:{}".format(t, loss.item()))  # 打印每个迭代的损失'''后向传播(backward pass)'''loss.backward()'''参数更新(update weights of W1 and W2)'''with 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 pass)'''h = X.mm(W1)  # N * Hh_relu = h.clamp(min=0)  # 激活函数,N * Hy_hat = h_relu.mm(W2)  # N * D_out'''计算损失函数(compute loss)'''loss = (y_hat - y).pow(2).sum().item()  # 均方误差,忽略了÷Nprint("Epoch:{}   Loss:{}".format(t, loss))  # 打印每个迭代的损失all_loss.append(loss)'''后向传播(backward pass)'''# 计算梯度(此处没用torch,用最普通的链式求导,最终要得到 d{loss}/dX)grad_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()  # 这是h>0时的情况,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 W2)'''W1 -= 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, bias=True),  # W1 * X + b,默认Truetorch.nn.ReLU(),torch.nn.Linear(H, D_out)
)# model = model.cuda()  #这是使用GPU的情况loss_fn = nn.MSELoss(reduction='sum')learning_rate = 1e-4for t in range(500):  # 做500次迭代'''前向传播(forward pass)'''y_hat = model(X)  # model(X) = model.forward(X), N * D_out'''计算损失函数(compute loss)'''loss = loss_fn(y_hat, y)  # 均方误差,忽略了÷N,loss就是一个计算图(computation graph)print("Epoch:{}   Loss:{}".format(t, loss.item()))  # 打印每个迭代的损失'''后向传播(backward pass)'''loss.backward()'''参数更新(update weights of W1 and W2)'''with 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, bias=False)self.linear2 = torch.nn.Linear(H, D_out, bias=False)def forward(self, x):y_hat = self.linear2(self.linear1(X).clamp(min=0))return y_hatmodel = TwoLayerNet(D_in, H, D_out)loss_fn = nn.MSELoss(reduction='sum')
learning_rate = 1e-4
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)for t in range(500):  # 做500次迭代'''前向传播(forward pass)'''y_hat = model(X)  # model.forward(), N * D_out'''计算损失函数(compute loss)'''loss = loss_fn(y_hat, y)  # 均方误差,忽略了÷N,loss就是一个计算图(computation graph)print("Epoch:{}   Loss:{}".format(t, loss.item()))  # 打印每个迭代的损失optimizer.zero_grad()  # 求导之前把 gradient 清空'''后向传播(backward pass)'''loss.backward()'''参数更新(update weights of W1 and W2)'''optimizer.step()  # 一步把所有参数全更新print(summary(model, (64, 1000)))

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

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

相关文章

TM4C123库函数学习(1)--- 点亮LED+TM4C123的ROM函数简介+keil开发环境搭建

前言 &#xff08;1&#xff09; 首先&#xff0c;我们需要知道TM4C123是M4的内核。对于绝大多数人而言&#xff0c;入门都是学习STM32F103&#xff0c;这款芯片是采用的M3的内核。所以想必各位对M3内核还是有一定的了解。M4内核就是M3内核的升级版本&#xff0c;他继承了M3的的…

【力扣每日一题】2023.8.5 合并两个有序链表

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 题目给我们两个有序的链表&#xff0c;要我们保持升序的状态合并它们。 我们可以马上想要把两个链表都遍历一遍&#xff0c;把所有节点的…

扫地机器人(dfs基础)

题面 Mike同学在为扫地机器人设计一个在矩形区域中行走的算法&#xff0c;Mike是这样设计的&#xff1a;先把机器人放在出发点 (1,1)(1,1) 点上&#xff0c;机器人在每个点上都会沿用如下的规则来判断下一个该去的点是哪里。规则&#xff1a;优先向右&#xff0c;如果向右不能走…

1-搭建一个最简单的验证平台UVM,已用Questasim实现波形!

UVM-搭建一个最简单的验证平台&#xff0c;已用Questasim实现波形 1&#xff0c;背景知识2&#xff0c;".sv"文件搭建的UVM验证平台&#xff0c;包括代码块分享3&#xff0c;Questasim仿真输出&#xff08;1&#xff09;compile all&#xff0c;成功&#xff01;&…

基于 CentOS 7 构建 LVS-DR 集群 及 配置nginx负载均衡

一、构建LVS-DR集群 1、主机规划 Node01&#xff1a;PC Node02&#xff1a;LVS Node03、Node04&#xff1a;Webserver 2、部署环境 2.1 在Node02上配置 2.1.1 安装ipvsadm管理软件按 [rootlocalhost ~]# yum install -y ipvsadm 2.1.2 配置VIP [rootlocalhost ~]# if…

【力扣每日一题】2023.8.8 任意子数组和的绝对值的最大值

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 题目给我们一个数组&#xff0c;让我们找出它的绝对值最大的子数组的和。 这边的子数组是要求连续的&#xff0c;让我们找出一个元素之和…

GG修改器安装与Root环境的安装

关于GG修改器大家应该都有一定的了解吧&#xff0c;就是类似于电脑端CE的一个软件。 GG修改器在百度云盘里请自行下载&#xff01; 百度网盘链接&#xff1a;https://pan.baidu.com/s/1p3KJRg9oq4s0XzRuEIBH4Q 提取码&#xff1a;vuwj 那我要开始了&#xff01; 本来不想讲GG…

Spring Boot集成EasyPoi实现导入导出操作

文章目录 Spring Boot集成EasyPoi实现导入导出操作0 简要说明1 环境搭建1.1 项目目录1.2 依赖管理2.3 关于swagger处理2.4 关于切面处理耗时1 自定义注解2 定义切面类3 如何使用 2.5 核心导入操作2.6 核心导出操作 2 最佳实线2.1 导入操作1 实体类说明2 业务层3 效果3 控制层 2…

常用抓包工具

Fiddler Fiddler 是一个很好用的抓包工具&#xff0c;可以用于抓取http/https的数据包&#xff0c;常用于Windows系统的抓包&#xff0c;它有个优势就是免费 Charles Charles是由JAVA开发的&#xff0c;可以运行在window Linux MacOS&#xff0c;但它是收费的&#xff0c;和…

.Net Framework请求外部Api

要在.NET Framework 4.5中进行外部API的POST请求&#xff0c;你可以使用HttpClient类。 1. Post请求 using System; using System.Net.Http; using System.Threading.Tasks;class Program {static async Task Main(string[] args){// 创建一个HttpClient实例using (HttpClien…

Python取得系统进程列表

Python取得系统进程列表 上代码 上代码 import psutilfor proc in psutil.process_iter():try:pinfo proc.as_dict(attrs[pid, name])except psutil.NoSuchProcess:passelse:print(pinfo)

httpd+Tomcat(jk)的Web动静分离搭建

动静分离是指将动态请求和静态请求分别交给不同的服务器来处理&#xff0c;可以提高服务器的效率和性能。在Java Web开发中&#xff0c;常见的动态请求处理方式是通过Tomcat来处理&#xff0c;而静态请求则可以通过Apache服务器来处理。本文将详细讲解如何结合Apache和Tomcat来…

Logback ThresholdFilter LevelFilter

当我们需要对日志的打印要做一些范围的控制的时候&#xff0c;通常都是通过为各个Appender设置不同的Filter配置来实现。在Logback中自带了两个过滤器实现&#xff1a; ch.qos.logback.classic.filter.LevelFilter和 ch.qos.logback.classic.filter.ThresholdFilter&#xff0c…

面试热题(翻转k个链表)

给你链表的头节点 head &#xff0c;每 k 个节点一组进行翻转&#xff0c;请你返回修改后的链表。 k 是一个正整数&#xff0c;它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍&#xff0c;那么请将最后剩余的节点保持原有顺序。 你不能只是单纯的改变节点内部的值&a…

使用Feign 的远程调用,把mysql数据导入es

要把数据库数据导入到elasticsearch中&#xff0c;包括下面几步&#xff1a; 1&#xff09;将商品微服务中的分页查询商品接口定义为一个FeignClient&#xff0c;放到feign-api模块中 2&#xff09;搜索服务编写一个测试业务&#xff0c;实现下面功能&#xff1a; 调用item-ser…

ctfshow-web7

0x00 前言 CTF 加解密合集 CTF Web合集 0x01 题目 0x02 Write Up 通过尝试&#xff0c;发现是数字型的注入&#xff0c;并且同样是过滤了空格 判断字段 获取一下flag即可 1/**/union/**/select/**/1,flag,3/**/from/**/web7.flag#&passworda以上

Spring接口ApplicationRunner的作用和使用介绍

在Spring框架中&#xff0c;ApplicationRunner接口是org.springframework.boot.ApplicationRunner接口的一部分。它是Spring Boot中用于在Spring应用程序启动完成后执行特定任务的接口。ApplicationRunner的作用是在Spring应用程序完全启动后&#xff0c;执行一些初始化任务或处…

kylin-Desktop gsettings 获取或设置系统配置

gsettings提供了对GSetings的命令行操作。GSetings实际上是一套高级API,用来操作dconf。 dconf存储着GNOME3的配置,是二进制格式。它做为GSettings的后端系统存在,暴露出低级API。在GNOME2时代,类似的角色是gconf,但它是以XML文本形式存储。 更接地气的说法是,dconf是G…

JavaScript基础知识

JavaScript基础知识 一、变量与数据类型1. 变量2. 数据类型 二、表达式与运算符1.字面量2.表达式3.运算符3.1 算术运算符3.2 比较运算符3.3 逻辑运算符3.4 赋值运算符 三、条件语句1. 控制流程2. 语句块3. if 语句3. switch 语句4. 条件运算符 四、循环语句1. while2. do...whi…

【框架篇】MyBatis 介绍及使用(详细教程)

一&#xff0c;MyBatis 介绍 MyBatis 是一款优秀的持久层框架&#xff0c;它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO&#xff…