PyTorch入门与实战:从Tensor到自动微分与线性回归模型

PyTorch入门与实战:从Tensor到自动微分与线性回归模型

一、什么是 PyTorch?

PyTorch 是一个开源的深度学习框架,广泛应用于图像识别、自然语言处理等领域。它由 Python 编写,易学易用,非常适合机器学习开发者快速上手。

PyTorch 的三大核心特点是:

  1. 易于安装:支持多平台,安装过程简单。
  2. 灵活的 Tensor 操作:提供类似 Numpy 的多维数组,且支持 GPU 加速。
  3. 自动微分机制:通过反向传播自动计算梯度,让模型训练更加高效。

接下来,我将详细介绍如何安装 PyTorch、Tensor 的使用方法以及自动微分的原理和应用,最后一起动手实现一个简单的线性回归模型。

二、如何安装PyTorch?

  1. 安装前准备:

    • 已安装Python 3.9及以上版本;
    • 已安装Anaconda;
  2. 进入Pytorch官网,下滑到【install Pytorch】模块,获取安装Pytorch的pip命令。
    在这里插入图片描述

  • Compute Platform 如何选择?

    • CUDA:用于支持 NVIDIA GPU 的设备。如果你的电脑配有NVIDIA显卡,并且安装了CUDA(CUDA Toolkit版本如11.8、12.1或12.4),你可以利用GPU加速PyTorch的计算,提高训练和推理速度。
    • CPU:选择CPU意味着PyTorch将仅使用你的中央处理器(CPU)进行计算。如果你没有兼容的GPU或者CUDA环境,或者你只是进行一些简单的小规模任务,可以选择CPU。
  • 可以通过以下方法确认显卡是否为NVIDIA GPU:

    • Win + R,输入 dxdiag,检查显示标签页是否有 NVIDIA 相关显卡型号

    在这里插入图片描述

  1. 拷贝pip命令在cmd下运行
    在这里插入图片描述

  2. 安装成功后,打开pycharm运行一个demo检查安装是否成功:

    from __future__ import  print_function
    import  torch
    x = torch.rand(5,3)
    print(x)
    

在这里插入图片描述
通过上述步骤,我们成功安装了 PyTorch,接下来我们将深入学习 Tensor 的基本操作。

三、PyTorch 核心概念:张量(Tensor)

1. 什么是张量(Tensor)?

张量(Tensor) 是 PyTorch 中的核心数据结构,它可以理解为:

  • 通用的多维数组,类似于 NumPy 的 ndarray
  • 可以表示标量(0维)、向量(1维)、矩阵(2维)和高维数组(3维及以上)。
  • 张量的优势在于支持 自动微分GPU加速,适合机器学习和深度学习任务。

2. 张量(Tensor)的基本操作:

(1) 创建张量

你可以用以下方法创建张量:

1) 从数据创建
import torch	#导入PyTorch库,用于创建和操作张量。

# 创建一个张量
data = [[1, 2], [3, 4]]
x = torch.tensor(data)	#将python列表转换为张量(Tensor)
print("张量x:", x)
print("x的形状:", x.shape)
2) 随机初始化张量
# 随机生成一个 3x3 的张量
x = torch.rand(3, 3)  #torch.rand() 函数是用来生成随机张量。生成的随机数取值范围在 [0, 1)之间
print("随机张量x:", x)

# 生成全零或全一的张量
zeros = torch.zeros(2, 2)
ones = torch.ones(2, 2)
print("全零张量:", zeros)
print("全一张量:", ones)
3) 从 NumPy 数组创建张量
import numpy as np

arr = np.array([[1, 2], [3, 4]])
x = torch.from_numpy(arr)  # 从NumPy数组创建张量
print("NumPy转张量:", x)

(2) 张量的基本运算
1) 加减乘除
x = torch.tensor([[1, 2], [3, 4]], dtype=torch.float32)	#dtype=torch.float32,用于指定Tensor的数据类型是32位浮点数,如果不指定会创建int类型的Tensor
y = torch.tensor([[5, 6], [7, 8]], dtype=torch.float32)

# 张量加法
print("x + y:\n", x + y)

# 张量乘法(按元素相乘)
print("x * y:\n", x * y)

# 张量除法
print("x / y:\n", x / y)
2) 矩阵乘法
# 矩阵乘法 (dot product)
result = torch.matmul(x, y.T)  # x和y的转置相乘
print("矩阵乘法:\n", result)
3) 维度变换

通过 .view() 方法改变Tensor的维度,数据的顺序没有改变,只是重新排列成了指定的形状。

注意:使用 .view() 改变形状时,张量中的元素数量必须保持一致

x = torch.tensor([[1, 2, 3], [4, 5, 6]])	#2行3列的张量

# 查看形状
print("原始x形状:", x.shape)

# 改变形状
x_reshaped = x.view(3, 2)  # 变成3行2列
print("变形后的x:\n", x_reshaped)

代码输出结果:

原始x形状: torch.Size([2, 3])
变形后的x:
 tensor([[1, 2],
         [3, 4],
         [5, 6]])

3. 张量与 GPU 之间的交互

PyTorch 支持使用 GPU 加速计算。要将张量移动到 GPU 上,需要以下步骤:

(1) 检查是否支持 GPU
import torch

# 检查GPU是否可用
print("GPU是否可用:", torch.cuda.is_available())
(2) 将张量移动到 GPU 上
# 创建张量
x = torch.tensor([[1, 2], [3, 4]])

# 将张量移动到GPU
if torch.cuda.is_available():
    x = x.to("cuda")
    print("x在GPU上:", x)
(3) 在 GPU 和 CPU 之间切换
# 张量在GPU上
x_gpu = x.to("cuda")

# 张量移动回CPU
x_cpu = x_gpu.to("cpu")
print("x移动回CPU:", x_cpu)

4. 完整代码示例

以下代码展示了张量的创建、基本操作和 GPU 使用:

import torch

# 1. 创建张量
x = torch.rand(3, 3)  # 随机生成一个3x3的张量
y = torch.ones(3, 3)  # 生成一个全1的张量
print("张量x:\n", x)
print("张量y:\n", y)

# 2. 张量基本运算
sum_result = x + y  # 加法
mul_result = x * y  # 按元素乘法
matmul_result = torch.matmul(x, y.T)  # 矩阵乘法
print("加法结果:\n", sum_result)
print("矩阵乘法结果:\n", matmul_result)

# 3. 维度变换
reshaped_x = x.view(9, 1)  # 改变形状
print("改变形状后的x:\n", reshaped_x)

# 4. GPU操作
if torch.cuda.is_available():
    x_gpu = x.to("cuda")  # 将张量移动到GPU
    print("x在GPU上:", x_gpu)
    x_cpu = x_gpu.to("cpu")  # 再移动回CPU
    print("x回到CPU:\n", x_cpu)

四、自动微分 (Autograd):梯度计算详解

1. 什么是自动梯度(Autograd)?

  • PyTorch 的自动梯度(Autograd) 是实现反向传播的核心工具,用于自动计算张量(Tensor)梯度。
  • 在深度学习中,梯度 用于更新模型参数,以最小化损失函数(Loss Function)。
  • PyTorch 中的 requires_grad 属性告诉系统:需要对张量进行梯度计算

2. 关键概念

  1. requires_grad 属性
    • 如果设置 requires_grad=True,那么 PyTorch 会自动追踪这个张量上的操作,方便计算梯度。
  2. .backward()
    • 调用 .backward() 方法会根据前向传播的计算图,自动执行反向传播,计算出梯度。
  3. .grad 属性
    • 用于访问张量的梯度值。

3. 代码示例与解释

以下是代码,逐行讲解:

import torch  # 导入PyTorch库

# 1. 创建一个张量,并指定需要计算梯度
x = torch.tensor([2.0, 3.0], requires_grad=True)
print("张量x:", x)

# 2. 定义一个函数 y,对x进行运算
y = x ** 2 + 3 * x + 1  # y = x^2 + 3x + 1
print("函数y:", y)

# 3. 计算y的和,并进行反向传播
y.sum().backward()  # 调用.backward()计算梯度
print("x的梯度:", x.grad)
(1) 执行结果
张量x: tensor([2., 3.], requires_grad=True)		#在python中2.2.0表示是浮点数(float)。
函数y: tensor([11., 19.], grad_fn=<AddBackward0>)
x的梯度: tensor([7., 9.])
(2) 反向传播的详细解释
  1. 第一部分: 创建张量。

    先创建一个一维张量(包含2个元素),requires_grad=True 表示 PyTorch 需要对 x 计算梯度。

  2. 第二部分: 运算。

    • 定义一个函数,并将2个元素传给函数。
      • 第一个元素:
        y 1 = ( 2 ) 2 + 3 ⋅ 2 + 1 = 11 y_1 = (2)^2 +3\cdot2 +1 = 11 y1=(2)2+32+1=11
      • 第二个元素:
        y 2 = ( 3 ) 2 + 3 ⋅ 3 + 1 = 19 y_2=(3)^2+3\cdot3+1=19 y2=(3)2+33+1=19
    • grad_fn=<AddBackward0> 表示 PyTorch 已经记录了这一步的操作,用于反向传播。
  3. 第三部分: 反向传播

    • 使用 .sum()
      • 由于.backward() 只能对标量(一个数)执行反向传播。
      • 如果 y 是一个向量(例如多个元素),使用 .sum() 将其转为标量,再执行反向传播。
      • 计算 y 的和:
        y 1 + y 2 = 11 + 19 = 30 y_1+y_2=11+19=30 y1+y2=11+19=30
    • .backward():执行反向传播,自动计算梯度。
    • x.grad:访问计算得到的梯度。
      • x.grad存储了计算得到的梯度,即:
      • 计算结果为:
        ∂ y . s u m ∂ x i = ∂ ( x i 2 + 3 x i + 1 ) ∂ x i \frac{\partial y.sum}{\partial x_i} = \frac{\partial (x_i^2 + 3x_i + 1)}{\partial x_i} xiy.sum=xi(xi2+3xi+1)
  • 对第一个元素:
    ∂ y ∂ x 1 = 2 x 1 + 3 = 2 ⋅ 2 + 3 = 7 \frac{\partial y}{\partial x_1} = 2x_1+3=2\cdot2+3=7 x1y=2x1+3=22+3=7
  • 对第二个元素:
    ∂ y ∂ x 2 = 2 x 2 + 3 = 2 ⋅ 3 + 3 = 9 \frac{\partial y}{\partial x_2} = 2x_2+3=2\cdot3+3=9 x2y=2x2+3=23+3=9
  • 所以,x.grad 为:tensor([7., 9.])
(3) 总结
  1. requires_grad=True:告诉 PyTorch 需要计算梯度。
  2. .backward():执行反向传播,自动计算梯度。
  3. x.grad:访问计算得到的梯度。

4. 如何禁用梯度计算?

  • 可以使用
    with torch.no_grad()
    
    禁用梯度计算,节省内存和计算资源。
    with torch.no_grad():
        x = torch.tensor([2.0, 3.0], requires_grad=True)
        y = x ** 2 + 3 * x + 1
        print(y)  # 这里不会计算梯度
    

五、实战一下:实现线性回归模型

让我们结合之前学到的 Tensor 和 Autograd 知识,实现一个简单的线性回归模型。

完整流程介绍:

  1. 数据准备:用 torch.randn 生成数据,模拟线性关系的输入和输出,定义线性关系。
  2. 模型构建:用 torch.nn.Linear 创建线性模型 y= Wx + b。
  3. 定义损失函数:用 torch.nn.MSELoss 定义回归任务的损失。
  4. 优化器设置:用 torch.optim.SGD 设定参数更新的优化方式。
  5. 训练模型:不断调整 W 和 b 以最小化损失
    • 前向传播:model(x)
    • 计算损失:criterion(y_pred, y)
    • 反向传播:loss.backward()
    • 参数更新:optimizer.step()
  6. 保存和加载模型:用 torch.savetorch.load 将学习到的权重和偏置保存到文件中。
    在这里插入图片描述

1. 数据准备:生成人工数据集

目标:生成符合线性关系的数据,模拟真实任务中的输入和输出。

代码

import torch

# 生成随机输入数据 x,包含 100 个样本,每个样本有 1 个特征
x = torch.randn(100, 1)  # 形状为 [100, 1]

# 人工生成线性关系数据 y = 3 * x + 2,加上随机噪声
y = 3 * x + 2 + torch.randn(100, 1) * 0.5  # 噪声控制在0.5范围内

print("输入数据 x 的前5个样本:\n", x[:5])
print("输出数据 y 的前5个样本:\n", y[:5])

解释

  • y = 3 * x + 2 + torch.randn(100, 1) * 0.5 :为什么要加上随机噪声?
    • 加入随机噪声的目的是模拟真实世界的数据特性,在现实中,数据往往会受到各种因素的干扰,很少完全符合一个精确的数学模型,加入随机噪声可以让模型更健壮(more robust),更贴近实际应用场景。
    • 它可以帮助防止过拟合(Overfitting),提高模型的泛化能力。
    • 噪声的幅度可以通过参数(如 * 0.5)调整,具体取决于任务需求。
  • x[:5]):Tensor的切片操作:
    • 类似于 Python 中对列表的切片,x[:5] 表示从第 0 行开始(默认)到第 5 行(不包括第 5 行),即取出第 0 行到第 4 行的数据。
    • 如果 x 是二维张量,x[:5] 会取前 5 行的所有列。

执行结果

输入数据 x 的前5个样本:
tensor([[-0.4322],
        [ 0.0967],
        [ 1.2571],
        [-0.3540],
        [-1.4387]])

输出数据 y 的前5个样本:
tensor([[0.5902],
        [2.1607],
        [6.5485],
        [1.6901],
        [-1.3721]])

2. 模型构建

目标:搭建一个具有一个输入和一个输出的线性模型。

代码

import torch.nn as nn

# 定义一个线性模型:1个输入特征 -> 1个输出特征
model = nn.Linear(1, 1)

# 打印模型的初始权重和偏置
print("初始权重:", model.weight)
print("初始偏置:", model.bias)

解释

  • nn.Linear(1, 1):创建一个线性模型,表示 y=Wx+by = Wx + b,其中 WW 是权重,bb 是偏置。
  • PyTorch 会随机初始化权重和偏置。

执行结果

初始权重: Parameter containing:
tensor([[0.1041]], requires_grad=True)
初始偏置: Parameter containing:
tensor([0.1812], requires_grad=True)

3. 定义损失函数和优化器

目标:定义模型优化所需的工具,包括损失函数(评估模型预测的好坏)和优化器(用于更新模型参数)。

代码

import torch.optim as optim

# 定义损失函数:均方误差(Mean Squared Error)
criterion = nn.MSELoss()

# 定义优化器:随机梯度下降(Stochastic Gradient Descent),学习率为 0.01
optimizer = optim.SGD(model.parameters(), lr=0.01)

解释

  • nn.MSELoss():均方误差损失,衡量预测值与真实值之间的差异:
    MSE = 1 n ∑ i = 1 n ( y ^ i − y i ) 2 \text{MSE} = \frac{1}{n} \sum_{i=1}^n (\hat{y}_i - y_i)^2 MSE=n1i=1n(y^iyi)2

  • optim.SGD:随机梯度下降法,用于更新模型参数以最小化损失函数。


4. 训练模型

目标:通过前向传播、损失计算和反向传播的循环,让模型学会拟合数据。

代码

# 训练模型
for epoch in range(200):  # 共训练200次
    # 前向传播:预测输出
    y_pred = model(x)
    
    # 计算损失
    loss = criterion(y_pred, y)
    
    # 梯度清零(PyTorch 中梯度是累加的,必须每轮清零)
    optimizer.zero_grad()
    
    # 反向传播:计算梯度
    loss.backward()
    
    # 更新参数
    optimizer.step()
    
    # 每20轮打印一次损失
    if (epoch + 1) % 20 == 0:
        print(f'Epoch {epoch+1}, Loss: {loss.item()}')

# 打印学习到的权重和偏置
print(f"学习到的权重:{model.weight.item()}, 偏置:{model.bias.item()}")

解释

  1. 前向传播:输入数据 x 通过模型得到预测值 y_pred
  2. 计算损失:用损失函数衡量预测值 y_pred 和真实值 y 的差距。
  3. 反向传播:调用 loss.backward(),根据损失值计算梯度。
  4. 更新参数:调用 optimizer.step() 使用梯度更新权重和偏置。

执行结果

Epoch 20, Loss: 0.5156
Epoch 40, Loss: 0.2573
...
Epoch 200, Loss: 0.0101
学习到的权重:3.005, 偏置:2.002

5. 保存和加载模型

目标:将训练好的模型保存到文件,便于以后使用。

代码

# 保存模型参数
torch.save(model.state_dict(), 'linear_regression.pth')
print("模型已保存到 'linear_regression.pth'")

# 加载模型参数
loaded_model = nn.Linear(1, 1)  # 重新创建模型
loaded_model.load_state_dict(torch.load('linear_regression.pth'))  # 加载保存的参数
loaded_model.eval()  # 切换到评估模式
print("加载的模型权重:", loaded_model.weight)
print("加载的模型偏置:", loaded_model.bias)

解释

  • torch.save():保存模型的参数到文件。
  • torch.load():从文件中加载模型参数。
  • eval():切换到评估模式(与训练模式不同,评估模式会关闭 Dropout 等功能)。

六、总结与展望

在本篇文章中,我们从 PyTorch 的基础概念入手,逐步学习了 Tensor 的基本操作、自动微分机制,并通过实战实现了一个简单的线性回归模型。接下来,你可以尝试更复杂的网络结构,如 CNNRNN,或在真实数据集上进行实战项目,进一步提升技能。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值