人工智能之深度学习_[3] -PyTorch自动微分模块和构建线性回归模型

ops/2025/1/22 8:54:04/

文章目录

    • 自动微分模块
      • 9.1 梯度基本计算
      • 9.2 梯度下降法求最优解
      • 9.3 梯度计算注意点
      • 9.4 自动微分模块应用
    • 10 PyTorch构建线性回归模型

自动微分模块

自动微分就是自动计算梯度值,也就是计算导数。

  • 什么是梯度
    • 对函数求导的值就是梯度
  • 什么是梯度下降法
    • 是一种求最优梯度值的方法,使得损失函数的值最小
  • 梯度经典语录
    • 对函数求导得到的值就是梯度 (在数值上的理解)
      • 在某一个点上,对函数求导得到的值就是该点的梯度
      • 没有点就无法求导,没有梯度
    • 梯度就是上山下山最快的方向 (在方向上理解)
    • 在平面内,梯度就是某一点上的斜率
      • y = 2x^2 某一点x=1的梯度,就是这一点上的斜率
    • 反向传播传播的是梯度
      • 反向传播利用链式法则不断的从后向前求导,求出来的值就是梯度,所以大家都经常说反向传播传播的是梯度
    • 链式法则中,梯度相乘,就是传说中的梯度传播

训练神经网络时,最常用的算法就是反向传播。在该算法中,参数(模型权重)会根据损失函数关于对应参数的梯度进行调整。为了计算这些梯度,PyTorch内置了名为 torch.autograd 的微分模块。它支持任意计算图的自动梯度计算:在这里插入图片描述
接下来我们使用这个结构进行自动微分模块的介绍,我们使用 backward 方法、grad 属性来实现梯度的计算和访问。

9.1 梯度基本计算

  • pytorch不支持向量张量对向量张量的求导,只支持标量张量对向量张量的求导
    • x如果是张量,y必须是标量(一个值)才可以进行求导
  • 计算梯度: y.backward(), y是一个标量
  • 获取x点的梯度值: x.grad, 会累加上一次的梯度值
  • 标量张量梯度计算

    # 定义一个标量张量(点)
    # requires_grad=:默认为False,不会自动计算梯度;为True的话是将自动计算的梯度值保存到grad中
    x = torch.tensor(10, requires_grad=True, dtype=torch.float32)
    print("x-->", x)# 定义一个曲线
    y = 2 * x ** 2
    print("y-->", y)
    # 查看梯度函数类型,即曲线函数类型
    print(y.grad_fn)# 计算x点的梯度
    # 此时y是一个标量,可以不用使用y.sum()转换成标量
    print("y.sum()-->", y.sum())
    # y'|(x=10) = (2*x**2)'|(x=10) = 4x|(x=10) = 40
    y.sum().backward()# 打印x的梯度值
    print("x的梯度值是:", x.grad)
    
  • 向量张量梯度计算

    # 定义一个向量张量(点)
    x = torch.tensor([10, 20], requires_grad=True, dtype=torch.float32)
    print("x-->", x)# 定义一个曲线
    y = 2 * x ** 2
    print("y-->", y)# 计算梯度
    # x和y都是向量张量,不能进行求导,需要将y转换成标量张量-->y.sum()
    # y'|(x=10) = (2*x**2)'|(x=10) = 4x|(x=10) = 40
    # y'|(x=20) = (2*x**2)'|(x=20) = 4x|(x=20) = 80
    y.sum().backward()# 打印x的梯度
    print("x.grad-->", x.grad)
    

9.2 梯度下降法求最优解

  • 梯度下降法公式: w = w - r * grad (r是学习率, grad是梯度值)

  • 清空上一次的梯度值: x.grad.zero_()

    # 求 y = x**2 + 20 的极小值点 并打印y是最小值时 w的值(梯度)
    # 1 定义点 x=10 requires_grad=True  dtype=torch.float32
    # 2 定义函数 y = x**2 + 20
    # 3 利用梯度下降法 循环迭代1000 求最优解
    # 3-1 正向计算(前向传播)
    # 3-2 梯度清零 x.grad.zero_()
    # 3-3 反向传播
    # 3-4 梯度更新 x.data = x.data - 0.01 * x.grad# 1 定义点x=10 requires_grad=True  dtype=torch.float32
    x = torch.tensor(10, requires_grad=True, dtype=torch.float32)# 2 定义函数 y = x ** 2 + 20
    y = x ** 2 + 20
    print('开始 权重x初始值:%.6f (0.01 * x.grad):无 y:%.6f' % (x, y))# 3 利用梯度下降法 循环迭代1000 求最优解
    for i in range(1, 1001):# 3-1 正向计算(前向传播)y = x ** 2 + 20# 3-2 梯度清零 x.grad.zero_()# 默认张量的 grad 属性会累加历史梯度值 需手工清零上一次的提取# 一开始梯度不存在, 需要做判断if x.grad is not None:x.grad.zero_()# 3-3 反向传播y.sum().backward()# 3-4 梯度更新 x.data = x.data - 0.01 * x.grad# x.data是修改原始x内存中的数据,前后x的内存空间一样;如果使用x,此时修改前后x的内存空间不同x.data = x.data - 0.01 * x.grad  # 注:不能 x = x - 0.01 * x.grad 这样写print('次数:%d 权重x: %.6f, (0.01 * x.grad):%.6f y:%.6f' % (i, x, 0.01 * x.grad, y))print('x:', x, x.grad, 'y最小值', y)
    

9.3 梯度计算注意点

  • 不能将自动微分的张量转换成numpy数组,会发生报错,可以通过detach()方法实现

    # 定义一个张量
    x1 = torch.tensor([10, 20], requires_grad=True, dtype=torch.float64)# 将x张量转换成numpy数组
    # 发生报错,RuntimeError: Can't call numpy() on Tensor that requires grad. Use tensor.detach().numpy() instead.
    # 不能将自动微分的张量转换成numpy数组
    # print(x1.numpy())# 通过detach()方法产生一个新的张量,作为叶子结点
    x2 = x1.detach()
    # x1和x2张量共享数据,但是x2不会自动微分
    print(x1.requires_grad)
    print(x2.requires_grad)
    # x1和x2张量的值一样,共用一份内存空间的数据
    print(x1.data)
    print(x2.data)
    print(id(x1.data))
    print(id(x2.data))# 将x2张量转换成numpy数组
    print(x2.numpy())
    

9.4 自动微分模块应用

import torch# 输入张量 2*5
x = torch.ones(2, 5)
# 目标值是 2*3    
y = torch.zeros(2, 3)
# 设置要更新的权重和偏置的初始值
w = torch.randn(5, 3, requires_grad=True)
b = torch.randn(3, requires_grad=True)
# 设置网络的输出值
z = torch.matmul(x, w) + b  # 矩阵乘法
# 设置损失函数,并进行损失的计算
loss = torch.nn.MSELoss()
loss = loss(z, y)
# 自动微分
loss.backward()
# 打印 w,b 变量的梯度
# backward 函数计算的梯度值会存储在张量的 grad 变量中
print("W的梯度:", w.grad)
print("b的梯度", b.grad)

10 PyTorch构建线性回归模型

我们使用 PyTorch 的各个组件来构建线性回归模型。在pytorch中进行模型构建的整个流程一般分为四个步骤:

  • 准备训练集数据
  • 构建要使用的模型
  • 设置损失函数和优化器
  • 模型训练

在这里插入图片描述
要使用的API:

  • 使用 PyTorch 的 nn.MSELoss() 代替平方损失函数
  • 使用 PyTorch 的 data.DataLoader 代替数据加载器
  • 使用 PyTorch 的 optim.SGD 代替优化器
  • 使用 PyTorch 的 nn.Linear 代替假设函数
import torch
from torch.utils.data import TensorDataset  # 构造数据集对象
from torch.utils.data import DataLoader  # 数据加载器
from torch import nn  # nn模块中有平方损失函数和假设函数
from torch import optim  # optim模块中有优化器函数
from sklearn.datasets import make_regression  # 创建线性回归模型数据集
import matplotlib.pyplot as pltplt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号# 构造数据集
def create_dataset():x, y, coef = make_regression(n_samples=100,n_features=1,noise=10,coef=True,bias=14.5,random_state=0)# 将构建数据转换为张量类型x = torch.tensor(x)y = torch.tensor(y)return x, y, coef# 训练模型
def train():# 构造数据集x, y, coef = create_dataset()# 构造数据集对象dataset = TensorDataset(x, y)# 构造数据加载器# dataset=:数据集对象# batch_size=:批量训练样本数据# shuffle=:样本数据是否进行乱序dataloader = DataLoader(dataset=dataset, batch_size=16, shuffle=True)# 构造模型# in_features指的是输入的二维张量的大小,即输入的[batch_size, size]中的size# out_features指的是输出的二维张量的大小,即输出的[batch_size,size]中的sizemodel = nn.Linear(in_features=1, out_features=1)# 构造平方损失函数criterion = nn.MSELoss()# 构造优化函数# params=model.parameters():训练的参数,w和b# lr=1e-2:学习率, 1e-2为10的负二次方print("w和b-->", list(model.parameters()))print("w-->", model.weight)print("b-->", model.bias)optimizer = optim.SGD(params=model.parameters(), lr=1e-2)# 初始化训练次数epochs = 100# 损失的变化epoch_loss = [] total_loss=0.0 train_sample=0.0for _ in range(epochs):for train_x, train_y in dataloader:# 将一个batch的训练数据送入模型y_pred = model(train_x.type(torch.float32))# 计算损失值loss = criterion(y_pred, train_y.reshape(-1, 1).type(torch.float32))total_loss += loss.item() train_sample += len(train_y)# 梯度清零optimizer.zero_grad()# 自动微分(反向传播)loss.backward()# 更新参数optimizer.step()# 获取每个batch的损失 epoch_loss.append(total_loss/train_sample)# 打印回归模型的wprint(model.weight)# 打印回归模型的bprint(model.bias)# 绘制损失变化曲线 plt.plot(range(epochs), epoch_loss) plt.title('损失变化曲线') plt.grid() plt.show()# 绘制拟合直线plt.scatter(x, y)x = torch.linspace(x.min(), x.max(), 1000)y1 = torch.tensor([v * model.weight + model.bias for v in x])y2 = torch.tensor([v * coef + 14.5 for v in x])plt.plot(x, y1, label='训练')plt.plot(x, y2, label='真实')plt.grid()plt.legend()plt.show()if __name__ == '__main__':train()

在这里插入图片描述
在这里插入图片描述


http://www.ppmy.cn/ops/152155.html

相关文章

HTB:Remote[WriteUP]

目录 连接至HTB服务器并启动靶机 信息收集 使用rustscan对靶机TCP端口进行开放扫描 将靶机TCP开放端口号提取并保存 使用nmap对靶机TCP开放端口进行脚本、服务扫描 使用nmap对靶机TCP开放端口进行漏洞、系统扫描 使用nmap对靶机常用UDP端口进行开放扫描 使用ftp尝试匿名…

自动化01

测试用例的万能公式:功能测试界面测试性能测试易用性测试安全性测试兼容性测试 自动化的主要目的就是用来进行回归测试 新产品--第一个版本 (具备丰富的功能),将产品的整体进行测试,人工创造一个自动化测试用例,在n个版本的时候…

【腾讯云】docker创建网络遇到Unable to enable SKIP DNAT rule

docker创建网络遇到Unable to enable SKIP DNAT rule 背景 今天打算在服务器上安装es,但是在创建网络时,提示 Error response from daemon: Failed to Setup IP tables: Unable to enable SKIP DNAT rule: (iptables failed: iptables --wait -t nat -I DOCKER…

【2024年终总结】我与CSDN的一年

👉作者主页:心疼你的一切 👉作者简介:大家好,我是心疼你的一切。Unity3D领域新星创作者🏆,华为云享专家🏆 👉记得点赞 👍 收藏 ⭐爱你们,么么哒 文章目录 …

@RabbitListener处理重试机制完成后的异常捕获

application.properties中配置开启手动签收 spring.rabbitmq.listener.direct.acknowledge-modemanual spring.rabbitmq.listener.simple.acknowledge-modemanual定义一个重试器 Slf4j Configuration public class RabbitMQRetryConfing {Bean("customRetry")publi…

【深度学习入门】深度学习知识点总结

一、卷积 (1)什么是卷积 定义:特征图的局部与卷积核做内积的操作。 作用:① 广泛应用于图像处理领域。卷积操作可以提取图片中的特征,低层的卷积层提取局部特征,如:边缘、线条、角。 ② 高层…

更新布局元素的属性

每个布局元素都有一组可以通过编程来更新的属性.布局元素有很多种不同的类型,如图例,图形,文本,地图整饰等等. 操作方法: 1.打开目标活动地图文档 2.打开python窗口 3.导入arcpy模块 import arcpy.mapping as mapping 4.引用当前活动地图文档,把该引用赋值给变量 mxd map…

Apache SeaTunnel 2.3.9 正式发布:多项新特性与优化全面提升数据集成能力

近日,Apache SeaTunnel 社区正式发布了最新版本 2.3.9。本次更新新增了Helm 集群部署、Transform 支持多表、Zeta新API、表结构转换、任务提交队列、分库分表合并、列转多行 等多个功能更新! 作为一款开源、分布式的数据集成平台,本次版本通过…