快速了解 PyTorch:十分钟入门介绍
深度学习已成为当今科技领域最热门的话题之一,而 PyTorch 作为其核心框架,正受到越来越多开发者和研究者的青睐。它以其易用性、灵活性和强大的功能,迅速崛起并与 TensorFlow 形成双雄鼎立之势。如果你想快速掌握一个深度学习框架,PyTorch 绝对是一个值得优先学习的选择。
本文旨在用“十分钟”的思维导图式介绍,带你快速触达 PyTorch 的核心概念和基本用法。虽然十分钟不足以精通,但足以让你了解它的全貌,并为你后续的深入学习打下坚实的基础。我们将从 PyTorch 是什么、为什么选择它开始,逐步深入到其最基础也是最重要的组成部分:张量(Tensor)、自动微分(Autograd)以及构建神经网络的基本模块(nn.Module
)。
1. PyTorch 是什么?
简单来说,PyTorch 是一个开源的机器学习库,主要用于构建和训练神经网络。它由 Facebook AI Research (FAIR) 团队开发并维护。
它的核心特点在于:
- Pythonic: 与 Python 语言深度融合,语法直观,易于使用。
- 动态计算图: 这是 PyTorch 相较于早期 TensorFlow 版本最显著的优势之一。计算图在运行时动态构建,使得调试更加方便,模型结构可以更灵活地变化(例如处理变长序列)。
- 强大的 GPU 加速: 可以无缝利用 NVIDIA GPU 进行高性能计算。
- 丰富的生态系统: 提供了众多配套库,如
torchvision
(计算机视觉)、torchaudio
(音频处理)、torchtext
(自然语言处理) 等。 - 强大的社区支持和文档: 拥有活跃的社区和高质量的官方文档。
2. 为什么选择 PyTorch?
- 上手快,学习曲线平缓: 如果你熟悉 Python 和 NumPy,那么 PyTorch 会让你感觉非常亲切。它的 API 设计直观,逻辑清晰。
- 研究友好: 动态图的特性让模型原型设计和实验变得非常便捷,尤其是在处理复杂模型或需要频繁改变计算流程的场景下。这也是为什么 PyTorch 在学术界非常受欢迎的原因。
- 灵活: 你可以轻松地构建自定义层、损失函数和优化器,不受框架过度约束。
- 日益成熟的生产部署能力: 虽然早期 PyTorch 更偏向研究,但现在通过 TorchScript 和其他工具,它在生产环境中的部署能力也越来越强大。
3. PyTorch 的核心概念
理解 PyTorch,需要抓住以下三个核心概念:
3.1 张量 (Tensor)
张量是 PyTorch 中最基本的数据结构,它类似于 NumPy 中的 ndarray
,但增加了对 GPU 计算和自动微分的支持。可以简单地将张量理解为多维数组。
-
创建张量:
-
从 Python 列表或 NumPy 数组创建:
“`python
import torch
import numpy as np从列表创建
data = [[1, 2], [3, 4]]
x_data = torch.tensor(data)
print(f”From list:\n {x_data}”)从 NumPy 数组创建
np_array = np.array(data)
x_np = torch.from_numpy(np_array)
print(f”From NumPy:\n {x_np}”)
* **创建特定类型的张量:**
python全零张量
x_zeros = torch.zeros_like(x_data) # 创建与 x_data 形状和数据类型相同的全零张量
print(f”Zeros:\n {x_zeros}”)全一张量
x_ones = torch.ones_like(x_data) # 创建与 x_data 形状和数据类型相同的全一张量
print(f”Ones:\n {x_ones}”)随机张量
x_rand = torch.rand_like(x_data, dtype=torch.float) # 指定数据类型
print(f”Random:\n {x_rand}”)直接指定形状创建
shape = (2, 3,)
rand_tensor = torch.rand(shape)
ones_tensor = torch.ones(shape)
zeros_tensor = torch.zeros(shape)
print(f”Random Tensor:\n {rand_tensor}”)
print(f”Ones Tensor:\n {ones_tensor}”)
print(f”Zeros Tensor:\n {zeros_tensor}”)
* **创建未初始化张量:**
python
x_empty = torch.empty(shape) # 创建指定形状的张量,其内容未初始化(随机值)
print(f”Empty Tensor:\n {x_empty}”)
“`
-
-
张量的属性: 张量有很多有用的属性,如形状 (
shape
)、数据类型 (dtype
) 和存储设备 (device
)。
python
tensor = torch.ones(4, 4)
print(f"Shape of tensor: {tensor.shape}")
print(f"Dtype of tensor: {tensor.dtype}")
print(f"Device tensor is stored on: {tensor.device}") -
张量的操作: 张量支持各种数学运算、索引、切片等,用法与 NumPy 非常相似。
-
数学运算:
“`python
tensor = torch.ones(4, 4)
tensor[:,1] = 0 # 第二列设置为零
print(tensor)t1 = torch.ones(2, 3)
t2 = torch.zeros(2, 3)
print(f”t1 + t2:\n {t1 + t2}”) # 元素级加法
print(f”t1 * t2:\n {t1 * t2}”) # 元素级乘法
print(f”t1 @ t2.T:\n {t1 @ t2.T}”) # 矩阵乘法 (@ 运算符 或 torch.matmul())
* **索引和切片:**
python
tensor = torch.arange(9).reshape(3, 3)
print(f”Original tensor:\n {tensor}”)
print(f”First row: {tensor[0]}”)
print(f”First column: {tensor[:, 0]}”)
print(f”Last column: {tensor[…, -1]}”)
* **形状变换:**
python
tensor = torch.ones(4, 4)view 用于改变张量形状,共享底层数据,要求元素总数不变
rearranged_tensor = tensor.view(16)
print(f”Rearranged tensor:\n {rearranged_tensor}”)reshape 功能类似 view,但当内存不连续时会复制数据
reshaped_tensor = tensor.reshape(2, 8)
print(f”Reshaped tensor:\n {reshaped_tensor}”)
* **与 NumPy 相互转换:**
python
np_array = tensor.numpy() # Tensor -> NumPy
print(f”Tensor to NumPy:\n {np_array}”)tensor_from_np = torch.from_numpy(np_array) # NumPy -> Tensor
print(f”NumPy to Tensor:\n {tensor_from_np}”)
“`
注意: CPU 上的张量和 NumPy 数组共享底层内存,修改一个会影响另一个。GPU 上的张量则不会。
-
-
GPU 加速: 将张量移动到 GPU 可以显著加速计算。
python
if torch.cuda.is_available():
device = "cuda"
tensor = tensor.to(device)
print(f"Tensor device after .to('cuda'): {tensor.device}")
else:
device = "cpu"
print("CUDA not available, using CPU.")
3.2 自动微分 (Autograd)
自动微分是 PyTorch 强大的核心功能,它能够自动计算神经网络中参数的梯度。这是反向传播算法的基础,也是训练神经网络的关键。
- 跟踪计算历史: PyTorch 会记住对张量的所有操作,构建一个计算图(或称为计算轨迹)。
-
requires_grad=True
: 默认情况下,张量不跟踪其计算历史。如果你希望 PyTorch 为某个张量(通常是模型的参数)计算梯度,你需要将其requires_grad
属性设置为True
。
“`python
x = torch.ones(5, requires_grad=True) # 跟踪所有操作
y = torch.zeros(3) # 默认不跟踪
z = torch.ones(5, requires_grad=True) * 2 # 跟踪print(f”x.requires_grad: {x.requires_grad}”)
print(f”y.requires_grad: {y.requires_grad}”)
print(f”z.requires_grad: {z.requires_grad}”)进行一些计算
a = x + 2
b = a.mean()
print(f”a.requires_grad: {a.requires_grad}”) # 依赖于 x,所以跟踪
print(f”b.requires_grad: {b.requires_grad}”) # 依赖于 a,所以跟踪
* **计算梯度:** 当你在一个张量上调用 `.backward()` 方法时,PyTorch 会根据之前记录的计算历史,利用链式法则自动计算出所有需要梯度的叶子节点(即 `requires_grad=True` 的输入张量)的梯度,并将结果累加到它们的 `.grad` 属性中。
python举例:计算 y = w*x + b 中 y 对 w 和 b 的导数 (一个简化的例子)
x = torch.tensor(2.0, requires_grad=True)
w = torch.tensor(3.0, requires_grad=True)
b = torch.tensor(1.0, requires_grad=True)y = w * x + b # y = 3 * 2 + 1 = 7
计算梯度
y.backward()
查看梯度
print(f”Gradient of y w.r.t. x: {x.grad}”) # dy/dx = w = 3.0
print(f”Gradient of y w.r.t. w: {w.grad}”) # dy/dw = x = 2.0
print(f”Gradient of y w.r.t. b: {b.grad}”) # dy/db = 1.0
* **停止跟踪梯度:** 在推理阶段(不需要计算梯度来更新模型参数时),或者当你只是想进行一些普通的张量操作而不希望它们被记录在计算图中时,可以使用 `torch.no_grad()` 上下文管理器或 `.detach()` 方法。这可以节省内存和计算。
python
x = torch.tensor(2.0, requires_grad=True)
with torch.no_grad():
y = x + 1
print(f”y.requires_grad in no_grad block: {y.requires_grad}”) # False或者使用 .detach()
z = x.detach()
print(f”z.requires_grad after detach: {z.requires_grad}”) # False
“`
3.3 nn.Module
在 PyTorch 中构建神经网络通常会用到 torch.nn
模块。nn.Module
是所有神经网络层(如全连接层、卷积层)、损失函数以及整个模型的基本类。继承 nn.Module
可以方便地管理模型参数(它们会自动被注册,并在调用 .cuda()
或 .to()
时移动到相应的设备上)以及定义模型的前向传播计算。
-
定义一个简单的模型:
“`python
from torch import nnclass SimpleModel(nn.Module):
def init(self, input_size, output_size):
super(SimpleModel, self).init() # 调用父类构造函数
# 定义层:一个全连接层
self.linear = nn.Linear(input_size, output_size)def forward(self, x): # 定义前向传播计算 out = self.linear(x) return out
实例化模型
input_dim = 10
output_dim = 1
model = SimpleModel(input_dim, output_dim)
print(model) # 打印模型结构模型的参数会自动注册
print(“Model parameters:”)
for name, param in model.named_parameters():
print(f”Param name: {name}, shape: {param.shape}”)
print(f”Param requires_grad: {param.requires_grad}”) # 模型参数默认 requires_grad=True示例输入
dummy_input = torch.randn(1, input_dim) # 批次大小为1,特征维度为 input_dim
进行前向传播
output = model(dummy_input)
print(f”Model output shape: {output.shape}”)
* **损失函数 (Loss Functions):** `torch.nn` 中也包含了常用的损失函数。
python举例:均方误差损失 (用于回归任务)
loss_fn = nn.MSELoss()
举例:交叉熵损失 (用于分类任务)
loss_fn = nn.CrossEntropyLoss()
* **优化器 (Optimizers):** `torch.optim` 模块提供了各种优化算法(如 SGD, Adam 等)来更新模型参数。
python
from torch import optim创建一个优化器,它会负责更新 model 的所有参数
第一个参数是需要优化的参数列表 (model.parameters())
第二个参数是学习率 (lr)
optimizer = optim.SGD(model.parameters(), lr=0.01)
举例:使用 Adam 优化器
optimizer = optim.Adam(model.parameters(), lr=0.001)
“`
4. 训练循环的流程 (概念介绍)
虽然构建一个完整的训练脚本超出了“十分钟”的代码范围,但理解训练循环的基本流程至关重要。使用 PyTorch 训练一个神经网络通常遵循以下步骤:
- 数据准备: 加载并预处理数据。PyTorch 提供了
Dataset
和DataLoader
类来高效地处理数据加载、批处理、洗牌等。 - 模型构建: 定义并实例化你的神经网络模型(通常继承自
nn.Module
)。 - 定义损失函数: 选择适合任务的损失函数(如
nn.MSELoss
,nn.CrossEntropyLoss
等)。 - 定义优化器: 选择优化算法(如
optim.SGD
,optim.Adam
等),并将模型的参数传递给优化器。 - 训练迭代 (Epochs): 重复多次遍历整个数据集。
- 批次迭代 (Batches): 在每个 epoch 中,将数据分成小批量 (batch) 进行处理。
- 前向传播 (Forward Pass): 将一个批次的数据输入模型,获得预测输出。
- 计算损失 (Calculate Loss): 比较模型预测输出与真实标签,计算损失值。
- 清零梯度 (Zero Gradients): 在反向传播之前,需要将之前计算的梯度清零,因为梯度默认是累加的 (
optimizer.zero_grad()
)。 - 反向传播 (Backward Pass): 调用损失张量的
.backward()
方法,自动计算损失函数对模型所有可学习参数的梯度。 - 参数更新 (Optimizer Step): 调用优化器的
.step()
方法,根据计算出的梯度和优化算法更新模型的参数。
- 批次迭代 (Batches): 在每个 epoch 中,将数据分成小批量 (batch) 进行处理。
- 评估模型: 在训练过程中或训练完成后,使用独立的验证集或测试集评估模型的性能,通常在
torch.no_grad()
环境下进行。
这个循环是深度学习训练的核心,理解它对于使用 PyTorch 至关重要。
5. 进阶与生态系统 (简述)
- torchvision/torchaudio/torchtext: 这些是 PyTorch 官方提供的领域库,包含了常用的数据集、模型结构和预处理工具,极大地方便了在这些领域进行开发。
- 模型保存与加载: 使用
torch.save()
和torch.load()
可以方便地保存和加载模型的权重或整个模型。 - GPU 使用: 通过
.to(device)
将模型和数据移动到 GPU (device="cuda"
),实现计算加速。需要确保安装了支持 CUDA 的 PyTorch 版本。 - TorchScript: 用于将 PyTorch 模型从 Python 转换到可序列化的格式,以便在不需要 Python 环境的地方部署(如 C++)。
6. 总结
十分钟的时间,我们快速浏览了 PyTorch 的核心:
- 张量 (Tensor): 它是数据的载体,支持 GPU 加速。
- 自动微分 (Autograd): 它是训练的引擎,自动计算梯度。
nn.Module
: 它是构建网络的基石,方便定义和管理模型结构及参数。- 训练循环: 核心流程是前向传播、计算损失、反向传播、参数更新。
PyTorch 的设计哲学是“Python优先”,它提供了极大的灵活性和易用性。虽然这里只是一个初步的介绍,但希望它为你打开了通往 PyTorch 世界的大门。
下一步建议:
- 安装 PyTorch: 访问 PyTorch 官网 (pytorch.org) 获取适合你环境的安装命令。
- 动手实践: 运行本文中的代码示例,亲手体验张量操作和自动微分。
- 查阅官方文档和教程: PyTorch 的官方文档非常出色,提供了详细的 API 参考和丰富的教程。
- 尝试构建一个小项目: 例如,使用 PyTorch 构建一个简单的线性回归模型或手写数字识别模型 (MNIST)。
掌握 PyTorch 需要时间和实践,但一旦你理解了其核心概念,你将能够利用它强大的能力来构建和训练复杂的深度学习模型。开始你的 PyTorch 之旅吧!