Pytorch使用pytorch进行张量计算自动求导和神经网络构建

Posted 阿润菜菜

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Pytorch使用pytorch进行张量计算自动求导和神经网络构建相关的知识,希望对你有一定的参考价值。


本文参加新星计划人工智能(Pytorch)赛道:https://bbs.csdn.net/topics/613989052


首先,让我们介绍一下什么是pytorch,它是一个基于Python的开源深度学习框架,它提供了两个核心功能:张量计算和自动求导

张量计算

张量计算是指使用多维数组(称为张量)来表示和处理数据,例如标量、向量、矩阵等。pytorch提供了一个torch.Tensor类来创建和操作张量,它支持各种数据类型和设备(CPU或GPU)。我们可以使用torch.tensor()函数来创建一个张量,并指定它的形状、数据类型和是否需要梯度。

例如,我们可以创建一个2x3的浮点型张量,并设置requires_grad=True,表示我们想要跟踪这个张量的所有操作:

import torch
x = torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]], requires_grad=True)
print(x)

输出结果为:

tensor([[1., 2., 3.],
        [4., 5., 6.]], requires_grad=True)

自动求导

自动求导是指利用pytorch的autograd模块来自动计算张量的梯度,即导数。梯度是一个表示函数变化率的向量,它在深度学习中非常重要,因为它可以用来优化模型的参数。当我们对一个张量执行某些操作时,例如加法、乘法、指数等,pytorch会记录这些操作,并构建一个计算图。当我们调用.backward()方法时,pytorch会根据链式法则从后往前遍历这个计算图,并计算每个节点的梯度。我们可以通过.grad属性来访问这些梯度。

例如,我们可以定义一个简单的函数y = x ** 2,并对x = [2, 3]求导:

import torch
x = torch.tensor([2.0, 3.0], requires_grad=True)
y = x ** 2
print(y)
y.backward()
print(x.grad)

输出结果为:

tensor([4., 9.], grad_fn=<PowBackward0>)
tensor([4., 6.])

神经网络的构建

神经网络构建是指使用pytorch提供的nn模块来定义和训练复杂的神经网络模型。nn模块包含了各种预定义的层、损失函数、优化器等组件,可以方便地组合成不同类型的神经网络。我们可以使用nn.Module类来定义自己的神经网络层或模型,并实现forward()方法来定义前向传播逻辑。backward()方法会由autograd自动实现。

例如,我们可以定义一个简单的线性回归模型,并用随机数据进行训练:

import torch
import torch.nn as nn

# 定义线性回归模型 y = wx + b
class LinearRegression(nn.Module):
    def __init__(self):
        super(LinearRegression, self).__init__()
        self.linear = nn.Linear(1, 1) # 输入维度为1,输出维度为1

    def forward(self, x):
        y = self.linear(x) # 前向传播逻辑
        return y

# 创建模型实例
model = LinearRegression()
print(model)

# 创建损失函数(均方误差)和优化器(随机梯度下降)
criterion = nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.

# 生成随机数据
x = torch.randn(100, 1) # 100个随机输入
y = 3 * x + 2 + torch.randn(100, 1) # 对应的输出,加上一些噪声

# 训练模型
epochs = 20 # 迭代次数
for epoch in range(epochs):
    # 前向传播,得到预测值
    y_pred = model(x)
    # 计算损失值
    loss = criterion(y_pred, y)
    # 反向传播,计算梯度
    loss.backward()
    # 更新参数
    optimizer.step()
    # 清零梯度
    optimizer.zero_grad()
    # 打印损失值和参数值
    print(f"Epoch epoch, loss: loss.item():.4f")
    for name, param in model.named_parameters():
        print(name, param.data)

# 测试模型
x_test = torch.tensor([[4.0]]) # 测试输入
y_test = model(x_test) # 预测输出
print(f"Predicted y for x = 4: y_test.item():.4f") 

输出结果为:

Epoch 0, loss: 9.9758
linear.weight tensor([[2.8277]])
linear.bias tensor([0.0145])
Epoch 1, loss: 4.0609
linear.weight tensor([[2.9056]])
linear.bias tensor([0.2308])
...
Epoch 19, loss: 0.9866
linear.weight tensor([[2.9877]])
linear.bias tensor([1.9679])
Predicted y for x = 4: 13.9166 

可以看到,经过训练,模型的参数接近真实值(w=3,b=2),并且能够对新的输入进行预测。

参考:) PyTorch官方网站

自动求梯度(pytorch版本)——2.20

一、Tensor用于自动求梯度

"tensor"这个单词?般可译作“张量”,张量可以看作是?个多维数组。标量可以看作是0维张量,向量可以看作1维张量,矩阵可以看作是?维张量。

????在深度学习中,我们经常需要对函数求梯度(gradient)。PyTorch提供的autograd 包能够根据输?和前向传播过程?动构建计算图,并执?反向传播。本节将介绍如何使?autograd包来进??动求梯度的有关操作。

概念
????Pytorch中的Tensor 是这个包的核?类,如果将其属性 .requires_grad 设置为 True ,它将开始追踪(track)在其上的所有操作(这样就可以利?链式法则进?梯度传播了)。完成计算后,可以调? .backward() 来完成所有梯度计算。此 Tensor 的梯度将累积到 .grad 属性中。

注意在 y.backward() 时,如果 y 是标量,则不需要为backward()传?任何参数;否则,需要传??个与 y同形的 Tensor

????如果不想要被继续追踪,可以调? .detach() 将其从追踪记录中分离出来,这样就可以防?将来的计算被追踪,这样梯度就传不过去了。此外,还可以? with torch.no_grad() 将不想被追踪的操作代码块包裹起来,这种?法在评估模型的时候很常?,因为在评估模型时,我们并不需要计算可训练参数(requires_grad=True)的梯度。

????Function 是另外?个很?要的类。 TensorFunction 互相结合就可以构建?个记录有整个计算过程的有向?环图(DAG)。每个 Tensor 都有?个 .grad_fn 属性,该属性即创建该 TensorFunction , 就是说该 Tensor 是不是通过某些运算得到的,若是,则 grad_fn 返回?个与这些运算相关的对象,否则是None。

import torch

# 通过设置`requires_grad=Ytue`,使得操作通过链式法则进行梯度传播
x = torch.ones(2, 2, requires_grad=True)
print(x)
print(x.grad_fn)

+的运算操作
y = x+2
print(y)
print(y.grad_fn)
print(x.is_leaf,y.is_leaf)

# 复杂一点的运算操作
z = y*y*2
print(z)
print(z.grad_fn)
out = z.mean()
print(z, out)

????输出结果:
技术图片

以上是关于Pytorch使用pytorch进行张量计算自动求导和神经网络构建的主要内容,如果未能解决你的问题,请参考以下文章

PyTorch入门学习:Autogard之自动求梯度

实践·pytorch梯度计算

pytorch-torch2:张量计算和连接

PyTorch 1.0 中文文档:自动求导机制

Pytorch自动求解梯度

pytorch 可以优化顺序操作(如张量流图或 JAX 的 jit)吗?