开始学习pytorch第一天。感谢和鲸社区里K同学啊的分享。
- 🍨 本文为🔗小白入门Pytorch中的学习记录博客
- 🍦 参考文章:【小白入门Pytorch】教案一
- 🍖 原作者:K同学啊
一、张量的概念和表示
在PyTorch中,张量(tensor)是最基本的数据结构,它类似于多维数组。张量在深度学习中扮演着核心的角色,用于表示和处理数据以及进行数值计算。
1. 张量的维度和形状
张量可以具有不同的维度和形状。在PyTorch中,我们可以使用torch.Tensor
类来创建张量。以下是一些常见的张量及其对应的维度和形状的示例:
- 标量(0维张量):一个单独的数值。例如,
tensor = torch.tensor(5)
表示一个标量,其维度为0,形状为空。 - 向量(1维张量):具有一个轴的张量。例如,
tensor = torch.tensor([1, 2, 3, 4, 5])
表示一个向量,其维度为1,形状为(5,)。 - 矩阵(2维张量):具有两个轴的张量。例如,
tensor = torch.tensor([[1, 2, 3], [4, 5, 6]])
表示一个矩阵,其维度为2,形状为(2, 3)。 - 3维张量:具有三个轴的张量。例如,
tensor = torch.tensor([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
表示一个3维张量,其维度为3,形状为(2, 2, 2)。
import torch
print (torch.__version__)#查看pytorch版本
#如果报错Torch not compiled with CUDA enabled,见https://blog.csdn.net/weixin_72056722/article/details/126651703,
#torch版本会影响到是否能用gpu
# 查看张量shape
tensor=torch.tensor([[1,2,3],[4,5,6]])#括号确定维度
print(tensor.shape)
2.张量的操作
加减乘除按照对应项或广播机制进行。
广播指低维张量自动转化为高维张量。低维沿长度为1的轴复制。要进行广播,每个张量至少有一个维度;循环访问维度大小时,从尾随维度开始,维度大小必须相等、其中一个为1,或其中一个不存在。
tensor1=torch.tensor([1,2,3])
tensor2=torch.tensor([[4,5,6],[7,8,9]])
item=2
print(tensor1+tensor2)
print(tensor1+item)
张量访问特定元素或子张量时,与numpy相似,使用切片。
配置完成后,可以使用gpu加速
#GPU加速
import torch
tensor=torch.tensor([[1,2],[3,4]])
tensor=tensor.to('cuda')
tensor
#张量转移到cpu
tensor=tensor.to('cpu')
tensor
创建张量
import numpy as np
#从Python列表创建张量
data_list=[1,2,3,4]
x=torch.tensor(data_list)
#从Numpy数组创建张量
data_array=np.array([6,7,8,9,10])
x=torch.tensor(data_array)
#创建具有特定数据类型的张量
x=torch.tensor([1,2,3],dtype=torch.float32)
张量形状变换:reshape函数
a=torch.tensor([[[0,1,2],[3,4,5]],[[6,7,8],[9,10,11]]])
b=a.reshape(3,2,2)#改变为3×2的张量
print(a)
print(b)
关于维度的理解要注意,维度的观察方式是根据括号来看。具体可以看这篇:理解 PyTorch 中维度的概念 | 文艺数学君
c1=a.transpose(1,2)
c2=a.transpose(0,2)
#在numpy中,transpose可按轴交换;在pytorch中,只能对两个维度进行转换
print(a)
print(c1)
print(c2)
张量转化
import torch
import numpy as np
#创建一个PyTorch张量
tensor=torch.tensor([[1,2,3],[4,5,6],[7,8,9]])
#将张量转换为Numpy数组
array=tensor.numpy()
#将张量转换为列表
tensor_list=tensor.tolist()
二、自动求导原理
在PyTorch中,自动求导是一个关键的功能,它允许我们自动计算梯度,从而进行反向传播和优化。
1. 计算图
计算图是一个有向无环图(DAG),它描述了计算过程中的操作和数据之间的依赖关系。在PyTorch中,每个计算图由一系列的节点和边组成。节点表示函数(例如加法、乘法)或者张量,边表示张量和函数的依赖关系。举例:用计算图表示:y=(x1+w)*(x2+w),如图
计算图分为两个阶段:前向传播和反向传播。
- 前向传播:在前向传播阶段,计算图从输入节点开始,按照节点之间的依赖关系依次进行计算,直到到达输出节点。这个过程中,每个节点将计算并传递输出给下一个依赖节点。
- 反向传播:在反向传播阶段,计算图从输出节点开始,沿着边的反方向传播梯度。这个过程中,每个节点根据链式法则将梯度传递给输入节点,以便计算它们的梯度。
通过构建计算图,PyTorch可以记录整个计算过程,并在需要时自动计算梯度。这使得我们可以轻松地进行反向传播,并在优化算法中使用梯度信息。
2.梯度
梯度是一个向量,方向指向函数值增长最快的方向,大小表示函数值的变化率。在深度学习中,我们通常希望最小化损失函数,因此要沿着梯度的反方向更新模型参数,以逐步降低损失值。
PyTorch中的torch.Tensor
类是PyTorch的核心数据结构,同时也是计算梯度的关键。每个张量都有一个属性requires_grad
,默认为False
。如果我们希望计算某个张量的梯度,需要将requires_grad
设置为True
,那么就会开始追踪在该变量上的所有操作,而完成计算后,可以调用 .backward()
并自动计算所有的梯度,得到的梯度都保存在属性 .grad
中
3.梯度计算过程
在PyTorch中,计算梯度的过程主要分为以下几个步骤
- 创建张量并设置
requires_grad=True
:首先,我们需要创建一个张量,并将requires_grad
属性设置为True
,以便PyTorch跟踪其梯度。 - 定义计算图:接下来,我们使用创建的张量进行计算,可以使用任何PyTorch支持的函数、操作和模型。
- 计算梯度:一旦我们得到了最终的输出张量,我们可以使用
backward()
方法自动计算梯度 - 获取梯度值:通过访问张量的
grad
属性,我们可以获得计算得到的梯度值
import torch
x = torch.tensor([2.0, 3.0], requires_grad=True)
y = x**2 + 3*x + 1
y.sum().backward()
print(x.grad)
4.梯度计算示例
线性回归模型,使用梯度下降算法更新直线参数。
import torch
# 创建训练数据
x_train = torch.tensor([[1.0], [2.0], [3.0]])
y_train = torch.tensor([[2.0], [4.0], [6.0]])
# 定义模型参数
w = torch.tensor([[0.0]], requires_grad=True)
b = torch.tensor([[0.0]], requires_grad=True)
# 定义模型
#matmul函数实现两个张量矩阵相乘
def linear_regression(x):
return torch.matmul(x, w) + b
# 定义损失函数
def loss_fn(y_pred, y):
return torch.mean((y_pred - y)**2)
# 定义优化器
#torch.optim是实现各种优化算法的包
optimizer = torch.optim.SGD([w, b], lr=0.01)
# 训练模型
for epoch in range(100):
# 前向传播
y_pred = linear_regression(x_train)
# 计算损失
loss = loss_fn(y_pred, y_train)
# 反向传播
loss.backward()
# 更新参数
optimizer.step()
# 清零梯度
optimizer.zero_grad()
print(w,b)
三、反向传播
1. 反向传播原理
在深度学习中,我们通常使用梯度下降法来最小化损失函数,从而训练神经网络模型。而反向传播是计算损失函数对模型参数梯度的一种有效方法。通过计算参数梯度,我们可以根据梯度的反方向更新参数,使得模型的预测结果逐渐接近真实标签。反向传播的过程可以概括为以下几个步骤:
- 前向传播:将输入样本通过神经网络的前向计算过程,计算出预测结果。
- 计算损失:将预测结果与真实标签进行比较,并计算损失函数的值。
- 反向传播梯度:根据损失函数的值,计算损失函数对模型参数的梯度。
- 参数更新:根据参数的梯度和优化算法的规则,更新模型的参数。
在PyTorch中,反向传播过程是自动完成的。通过调用backward()
函数,PyTorch会自动计算损失函数对所有可学习参数的梯度,并将其保存在相应的参数张量的.grad
属性中。接下来,我们将通过具体示例来演示这一过程。
2. 反向传播示例
假设我们有一个简单的线性回归模型,其中只有一个输入特征和一个输出标签。我们的目标是通过训练模型来找到最佳的线性关系。首先,我们需要导入所需的库和模块、定义模型类
import torch
import torch.nn as nn
import torch.optim as optim
class LinearRegression(nn.Module):
def __init__(self):
#使用super函数在子类中调用父类的方法
super(LinearRegression, self).__init__()
#nn.Linear定义一个神经网络的线性层
self.linear = nn.Linear(1, 1) # 输入维度为1,输出维度为1
def forward(self, x):
#linear对象是磕掉用的,那么传入参数后会自动读取参数
return self.linear(x)
然后,我们创建模型的实例、定义损失函数和优化器:
model = LinearRegression()
criterion = nn.MSELoss() # 均方误差损失函数
# 随机梯度下降优化器
optimizer = optim.SGD(model.parameters(), lr=0.01)
现在,我们生成一些样本数据,并进行训练:
# 生成样本数据
x_train = torch.tensor([[1.0], [2.0], [3.0], [4.0]])
y_train = torch.tensor([[2.0], [4.0], [6.0], [8.0]])
# 训练模型
for epoch in range(500):
optimizer.zero_grad() # 梯度清零
# 前向传播
y_pred = model(x_train)
# 计算损失
loss = criterion(y_pred, y_train)
#输出loss,可以观察预测值与真实值差距,若差距较大说明没有收敛,那么增加迭代次数
print('Epoch=',epoch+1,loss.item())
# 反向传播
loss.backward()
# 参数更新
optimizer.step()
#输出权重和偏置
print('Weight=',model.linear.weight.item())
print('Bias=',model.linear.bias.item())
在上述代码中,我们使用了一个简单的数据集,包含了输入特征x_train
和对应的真实标签y_train
。在每个训练迭代中,我们首先将梯度清零,然后进行前向传播计算预测值y_pred
,接着计算损失loss
,然后通过调用backward()
函数执行反向传播,最后使用优化器的step()
方法来更新模型的参数。
通过上述示例,我们可以看到在PyTorch中实现反向传播是非常简单的。PyTorch会自动计算参数的梯度,并通过优化器来更新参数,从而实现模型的训练过程。
在本节中,我们详细介绍了PyTorch中反向传播的原理和实现。我们学习了反向传播的步骤,包括前向传播、计算损失、反向传播梯度和参数更新。通过一个简单的线性回归示例,我们演示了如何在PyTorch中执行反向传播。
反向传播是深度学习中非常重要的一部分,它为训练神经网络模型提供了有效的方法。理解和掌握反向传播对于使用PyTorch进行深度学习任务至关重要。在接下来的章节中,我们将进一步探索PyTorch中的其他重要概念和技术,帮助读者建立更深入的理解。