当前位置: 首页 > news >正文

2、PyTorch基础教程:从张量到神经网络训练

1、PyTorch基础

PyTorch 是一个开源的深度学习框架,以其灵活性和动态计算图而广受欢迎。

PyTorch 主要有以下几个基础概念:张量(Tensor)、自动求导(Autograd)、神经网络模块(nn.Module)、优化器(optim)等。

  • 张量(Tensor):PyTorch 的核心数据结构,支持多维数组,并可以在 CPU 或 GPU 上进行加速计算。
  • 自动求导(Autograd):PyTorch 提供了自动求导功能,可以轻松计算模型的梯度,便于进行反向传播和优化。
  • 神经网络(nn.Module):PyTorch 提供了简单且强大的 API 来构建神经网络模型,可以方便地进行前向传播和模型定义。
  • 优化器(Optimizers):使用优化器(如 Adam、SGD 等)来更新模型的参数,使得损失最小化。
  • 设备(Device):可以将模型和张量移动到 GPU 上以加速计算。

2、张量(Tensor):深度学习的基础数据结构

核心概念:张量是多维数组的泛化形式:

  • 0 维张量:标量(单个数字)

  • 1 维张量:向量

  • 2 维张量:矩阵

  • 更高维度:处理图像、视频等复杂数据

import torch# ========= 创建张量 =========
# 创建全零张量 (2行3列)
zeros_tensor = torch.zeros(2, 3)
print("全零张量:\n", zeros_tensor)# 创建全一张量 (3行2列)
ones_tensor = torch.ones(3, 2)
print("\n全一张量:\n", ones_tensor)# 创建随机张量 (正态分布)
rand_tensor = torch.randn(2, 2)
print("\n随机张量:\n", rand_tensor)# 从Python列表创建
list_tensor = torch.tensor([[1, 2], [3, 4]])
print("\n列表转换张量:\n", list_tensor)# 从NumPy数组创建
import numpy as np
numpy_array = np.array([[5, 6], [7, 8]])
numpy_tensor = torch.from_numpy(numpy_array)
print("\nNumPy转换张量:\n", numpy_tensor)# ========= 张量运算 =========
a = torch.tensor([[1, 2], [3, 4]])
b = torch.tensor([[5, 6], [7, 8]])# 张量加法
print("\n加法结果:\n", a + b)# 张量乘法(逐元素)
print("\n逐元素乘法:\n", a * b)# 矩阵乘法
print("\n矩阵乘法:\n", torch.matmul(a, b))# 改变形状 (2x2 -> 4x1)
reshaped = a.view(4, 1)
print("\n重塑形状:\n", reshaped)# ========= 张量属性 =========
print("\n张量形状:", a.shape)      # 输出: torch.Size([2, 2])
print("数据类型:", a.dtype)       # 输出: torch.int64
print("存储设备:", a.device)      # 输出: cpu

关键属性

  • shape:维度结构(如 (3, 224, 224) 表示3通道224x224图像)

  • dtype:数据类型(float32, int64等)

  • device:存储位置(CPU/GPU)

3、自动求导(Autograd):深度学习的引擎

在 PyTorch 中,自动求导(Autograd)是其核心功能之一,它允许自动计算梯度,这对于训练神经网络至关重要。

  1. Tensor 的 requires_grad 属性

    • 当设置为 True 时,PyTorch 会跟踪在该张量上的所有操作。

    • 例如:x = torch.tensor([1.0], requires_grad=True)

  2. 计算图(Computation Graph)

    • PyTorch 动态构建一个计算图,记录张量之间的操作。

    • 反向传播时根据这个图计算梯度。

  3. backward() 方法

    • 调用此方法自动计算梯度,结果存储在 .grad 属性中。

    • 例如:loss.backward()

  4. 梯度累积

    • 梯度默认会累积(累加到 .grad 中),每次反向传播前需手动清零。

# ========= 基础梯度计算 =========
# 创建需要梯度的张量
x = torch.tensor(2.0, requires_grad=True)# 定义计算过程
y = x ** 3 + 2 * x + 1  # y = x³ + 2x + 1# 反向传播计算梯度
y.backward()# 查看x的梯度 (dy/dx = 3x² + 2)
print("x的梯度:", x.grad)  # 输出: tensor(14.) 因为 3*(2)^2 + 2 = 14# ========= 复杂计算图 =========
a = torch.tensor([1.0, 2.0], requires_grad=True)
b = torch.tensor([3.0, 4.0], requires_grad=True)c = a * b           # 逐元素乘法
d = c.sum()         # 求和d.backward()        # 反向传播print("\na的梯度:", a.grad)  # 输出: tensor([3., 4.])
print("b的梯度:", b.grad)  # 输出: tensor([1., 2.])# ========= 梯度控制 =========
# 临时禁用梯度计算(推理时使用)
# with限定了torch.no_grad()的作用范围,确保只在该代码块内禁用梯度计算,离开代码块后自动恢复。
with torch.no_grad():e = a * 10print("\n禁用梯度时的操作:", e.requires_grad)  # 输出: False# 永久禁用梯度
a.requires_grad_(False) # 原地修改张量的requires_grad属性
print("禁用梯度后的a:", a.requires_grad)  # 输出: False

梯度计算过程

  1. 前向传播:构建计算图

  2. 反向传播:从输出开始,应用链式法则计算梯度

  3. 梯度存储:结果存储在张量的 .grad 属性中

4、神经网络模块(nn.Module):模型构建核心

核心组件

  • nn.Linear:全连接层(y = xWᵀ + b

  • nn.Conv2d:卷积层(图像处理)

  • nn.ReLU:激活函数(引入非线性)

  • nn.Sequential:层容器(简化模型构建)

import torch
import torch.nn as nn# ========= 定义神经网络模型 =========
class NeuralNetwork(nn.Module):def __init__(self):super().__init__()# 定义网络层self.flatten = nn.Flatten()  # 展平输入 (例如将28x28图像->784维向量)self.linear1 = nn.Linear(784, 128)  # 全连接层 (输入784维,输出128维)self.relu = nn.ReLU()  # 激活函数self.linear2 = nn.Linear(128, 10)  # 输出层 (10个类别)def forward(self, x):# 定义前向传播路径x = self.flatten(x)x = self.linear1(x)x = self.relu(x)x = self.linear2(x)return x# 实例化模型
model = NeuralNetwork()
print("模型结构:\n", model)# 模拟输入 (批量大小64, 通道1, 28x28图像)
input_data = torch.randn(64, 1, 28, 28)
output = model(input_data)
print("\n输出形状:", output.shape)  # 输出: torch.Size([64, 10])

关键方法

  • __init__():定义网络层

  • forward():指定数据流动路径

  • 继承 nn.Module 自动获得参数管理功能

5、优化器与损失函数:训练的动力系统

优化器原理:通过梯度下降算法更新参数:

参数 = 参数 - 学习率 × 梯度

PyTorch 提供多种改进算法(SGD, Adam, RMSProp等)

import torch
import torch.nn as nn
from torch.optim import Adam# ========= 模型定义 =========
# 定义一个简单的神经网络模型
# 在PyTorch中,模型参数的requires_grad属性默认是True
class SimpleModel(nn.Module):def __init__(self, input_size=10, hidden_size=5, num_classes=5):super(SimpleModel, self).__init__()self.fc1 = nn.Linear(input_size, hidden_size)  # 输入层到隐藏层self.relu = nn.ReLU()                          # 激活函数self.fc2 = nn.Linear(hidden_size, num_classes) # 隐藏层到输出层def forward(self, x):out = self.fc1(x)out = self.relu(out)out = self.fc2(out)return out# ========= 初始化组件 =========
model = SimpleModel(input_size=10, num_classes=5)  # 创建模型实例
loss_fn = nn.CrossEntropyLoss()                    # 交叉熵损失函数
optimizer = Adam(model.parameters(), lr=0.001)     # Adam优化器# ========= 模拟数据 =========
# 生成3个样本,每个样本有10个特征
inputs = torch.randn(3, 10)          # 输入数据 (batch_size=3, input_size=10)
# 生成3个样本的真实标签 (类别索引)
labels = torch.tensor([1, 0, 4])     # 每个样本的真实类别# ========= 训练循环 =========
epochs = 100  # 训练轮数for epoch in range(epochs):# 前向传播 (Forward Pass)predictions = model(inputs)  # 模型计算预测结果# 计算损失 (Compute Loss)loss = loss_fn(predictions, labels)  # 比较预测值和真实标签# 反向传播前清零梯度 (Zero Gradients)optimizer.zero_grad()  # 清除上一轮计算的梯度,避免累积# 反向传播 (Backward Pass)loss.backward()  # 自动计算所有参数的梯度# 更新参数 (Update Parameters)optimizer.step()  # 根据梯度更新模型权重# 打印训练进度if (epoch+1) % 10 == 0:print(f'Epoch [{epoch+1}/{epochs}], Loss: {loss.item():.4f}')# ========= 输出最终结果 =========
print("\n训练完成!")
print(f"最终损失值: {loss.item():.4f}")

常用损失函数

  • nn.MSELoss():回归问题(均方误差)

  • nn.CrossEntropyLoss():分类问题

  • nn.BCELoss():二分类问题

6、GPU加速:深度学习的关键性能

# ========= 设备设置 =========
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"使用设备: {device}")# ========= 数据与模型迁移 =========
# 创建模型并移至设备
model = NeuralNetwork().to(device)# 创建数据并移至设备
data = torch.randn(64, 1, 28, 28).to(device)
labels = torch.randint(0, 10, (64,)).to(device)# ========= GPU加速验证 =========
import timestart_time = time.time()
output = model(data)
loss = loss_fn(output, labels)
loss.backward()
print(f"GPU计算时间: {time.time()-start_time:.4f}秒")

最佳实践

  1. 使用 .to(device) 统一模型和数据位置

  2. 避免 CPU-GPU 间不必要的数据传输

  3. 使用 torch.cuda.empty_cache() 清理GPU内存

7、完整训练流程示例

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset# ========= 1. 准备数据 =========
# 模拟数据集 (1000个样本, 10个特征)
X = torch.randn(1000, 10)
y = (X.sum(dim=1) > 0).float()  # 二分类标签# 创建数据集和数据加载器
dataset = TensorDataset(X, y)
dataloader = DataLoader(dataset, batch_size=32, shuffle=True)# ========= 2. 定义模型 =========
class Classifier(nn.Module):def __init__(self):super().__init__()self.layer1 = nn.Linear(10, 5)self.relu = nn.ReLU()self.output = nn.Linear(5, 1)self.sigmoid = nn.Sigmoid()def forward(self, x):x = self.relu(self.layer1(x))x = self.sigmoid(self.output(x))return xmodel = Classifier()# ========= 3. 设置损失函数和优化器 =========
criterion = nn.BCELoss()  # 二分类交叉熵
optimizer = optim.Adam(model.parameters(), lr=0.01)# ========= 4. 训练循环 =========
num_epochs = 10for epoch in range(num_epochs):total_loss = 0for batch_X, batch_y in dataloader:# 前向传播predictions = model(batch_X).squeeze()# 计算损失loss = criterion(predictions, batch_y)total_loss += loss.item()# 反向传播optimizer.zero_grad()loss.backward()optimizer.step()# 打印每个epoch的平均损失avg_loss = total_loss / len(dataloader)print(f"Epoch [{epoch+1}/{num_epochs}], Loss: {avg_loss:.4f}")# ========= 5. 模型验证 =========
with torch.no_grad():test_data = torch.randn(5, 10)predictions = model(test_data)print("\n测试预测:", predictions.squeeze().numpy())

标准训练流程

  1. 数据准备 → 2. 模型定义 → 3. 损失/优化器设置

  2. 训练循环:

    • 前向传播

    • 损失计算

    • 梯度清零

    • 反向传播

    • 参数更新

  3. 模型评估

8、关键概念总结

概念作用典型组件
张量(Tensor)基础数据结构torch.Tensor.shape.dtype
自动求导(Autograd)自动梯度计算requires_grad.backward().grad
神经网络(nn.Module)模型构建nn.Linearnn.Conv2dforward()
优化器(Optimizer)参数优化torch.optim.Adam.step().zero_grad()
损失函数(Loss)性能评估nn.MSELossnn.CrossEntropyLoss
数据加载(DataLoader)数据管理DatasetDataLoader, 批处理
设备管理(Device)GPU加速.to(device)torch.cuda.is_available()

PyTorch 的动态计算图设计使其特别适合研究和原型开发。掌握这些基础概念后,可以进一步学习:

  1. 卷积神经网络(CNN)处理图像数据

  2. 循环神经网络(RNN)处理序列数据

  3. 迁移学习利用预训练模型

  4. 模型部署和生产化

相关文章:

  • FactoryBean 接口
  • 【HW系列】—溯源与定位—Linux入侵排查
  • 【razor】采集模块设置了窗体句柄但并不能直接渲染
  • 【基础算法】高精度(加、减、乘、除)
  • 用JS实现植物大战僵尸(前端作业)
  • 数据结构:栈(Stack)和堆(Heap)
  • LeetCode[110]平衡二叉树
  • 前端-不对用户显示
  • 域权限维持和后渗透密码收集
  • [VMM]现代 CPU 中用于加速多级页表查找的Page‐Table Entry原理
  • Qt SQL模块基础
  • 元胞自动机(Cellular Automata, CA)
  • CQF预备知识:一、微积分 -- 1.8.3 二元泰勒展开详解
  • 【Rust 轻松构建轻量级多端桌面应用】
  • 利用aqs构建一个自己的非公平独占锁
  • 【LUT技术专题】图像自适应3DLUT
  • 设计模式——原型设计模式(创建型)
  • Cypress + React + TypeScript
  • macOS 上安装运行 PowerShell
  • 电路图识图基础知识-常用仪表识图及接线(九)
  • 中山企业网站建设定制/seo为什么要进行外部优化
  • 平面设计和ui设计哪个简单/英语seo
  • 南京投资建设代办服务中心网站/北京优化seo公司
  • 做网站有虚拟服务器/有没有免费的推广网站
  • 西安建设网站的公司哪家好/线上如何做推广
  • 购物网站建设技术难点/网站分析工具