深度学习基础:从原理到实践——附录A:PyTorch 深度学习框架基础(上)
1、概述
度学习技术的快速发展催生了众多优秀的深度学习框架,其中 PyTorch 以其独特的设计理念和强大的功能特性脱颖而出。PyTorch 由 Facebook 人工智能研究院(FAIR)开发,于 2016 年首次发布,是对早期 Torch 框架的 Python 重构。与传统的静态图框架不同,PyTorch 采用了动态计算图机制,允许开发者以命令式编程的方式构建和修改计算图,极大地提升了开发效率和调试便利性。
PyTorch 作为当今最流行的深度学习框架之一,凭借其动态计算图机制和Python 优先的设计理念,已成为学术界和工业界广泛采用的深度学习开发平台。研究表明,PyTorch 在 2025 年已占据约68% 的深度学习研究论文,其动态图机制使调试效率提升 40%,在中小型模型训练中性能优势明显。
随着大语言模型(LLM)和多模态 AI 技术的兴起,PyTorch 在学术界和工业界的地位日益重要。截至 2025 年,PyTorch 已成为全球最流行的深度学习框架之一,在 GitHub 上的星标数量超过850,000,拥有超过 4,200 名贡献者。特别是在自然语言处理、计算机视觉、强化学习等前沿研究领域,PyTorch 已成为研究者的首选工具。
2、PyTorch 的发展历程与背景
2.1 从 Torch 到 PyTorch 的演进
PyTorch 的发展历程可以追溯到 2002 年诞生的 Torch 框架。Torch 是一个由纽约大学和 Facebook 等团队开发的科学计算框架,最初基于 Lua 语言实现。尽管 Torch 在学术界获得了一定认可,但其使用的 Lua 语言相对小众,限制了其广泛应用。许多研究者因需要学习新语言而对 Torch 望而却步。
2015 年,Facebook 开始了一项重要的技术重构工作。由 Luca Antiga、Andreas Köpf、Sergey Zagoruyko 等人领导的团队,将 Torch 的 C 后端进行了语言无关化改造,使其能够独立于 Lua 使用。这一技术基础为后续 PyTorch 的开发奠定了重要基础。
2016 年初,Facebook 人工智能研究院(FAIR)的 Soumith Chintala 收到了 Adam Paszke 的实习申请。当时整个 LuaTorch 团队仅有约 3 人(Gregory Chanan、Trevor Killeen 和 Soumith Chintala)。Soumith 邀请 Adam 参与开发下一代 Torch 框架,并采用现代化的设计理念。Sam Gross 也加入了这个项目,他们从 LuaTorch 的 fork 开始,专注于两个关键部分:TH/THC 和 THNN/THCUNN C 后端,以及与 LuaTorch 检查点的兼容性。
2.2 核心开发团队与设计理念
PyTorch 的核心开发团队由多位深度学习领域的专家组成,其中Adam Paszke作为主要开发者,最初是 Soumith Chintala 的学生,PyTorch 项目最初是他的实习项目。团队还包括 Sam Gross(全职参与)、Zeming Lin(受 Chainer 启发)、Natalia Gimelshein、Adam Lerer 等贡献者。
在设计理念上,PyTorch 受到了多个项目的启发:
torch-autograd(由 Alex Wiltschko 和 Clement Farabet 开发)提供了自动微分的基础思想
Chainer(由 Preferred Networks 开发)的动态图设计理念对 PyTorch 产生了重要影响
HIPS/autograd 库为 PyTorch 的自动微分机制提供了灵感
PyTorch 的设计哲学与 Python 的设计哲学高度一致:易读性和简洁性优于隐式的复杂性。这种设计理念贯穿于 PyTorch 的整个架构设计中,使其 API 设计更加直观、易于学习和使用。
2.3 版本演进与里程碑
PyTorch 的发展历程可以划分为以下几个重要阶段:
初期发布阶段(2016-2017 年):
2016 年 9 月,PyTorch 发布了0.1.0 版本,初始版本主要面向学术研究,提供了自动微分和动态计算图功能2017 年 1 月,Facebook 正式向世界推出 PyTorch,标志着其从内部项目走向开源社区
2017 年 8 月,PyTorch 0.2.0 版本发布,引入了广播、高级索引、高阶梯度、新图层以及分布式训练等重要特性
成长期(2018-2019 年):
2018 年 4 月,Caffe2 代码合并到 PyTorch,Facebook 旨在将 PyTorch 的研究特性与 Caffe2 的生产特性完美融合
2018 年 10 月,PyTorch 1.0.0 版本重磅发布,标志着 PyTorch 从实验性框架转为稳定的、可用于生产的框架
2019 年 8 月,PyTorch 1.2 版本发布,支持 ONNX 导出模型到跨平台格式
成熟期(2020 年至今):
2020 年 1 月,PyTorch 1.4 版本发布,这是最后一个支持 Python 2 和 C++11 的版本
2022 年 9 月,扎克伯格亲自宣布,PyTorch 基金会正式成立,并归入 Linux 基金会旗下
2022 年,PyTorch 2.0 版本发布,引入了 TorchDynamo 编译器,在 ResNet-50 训练中实现 30% 性能提升
2025 年 4 月,PyTorch 2.7 版本发布,新增了 Torch Function Modes 等特性
2025 年 8 月,PyTorch 2.8 版本发布,支持多种量化模式和控制流算子
3、PyTorch 核心概念与基础架构
3.1 张量(Tensor):PyTorch 的基础数据结构
量(Tensor)是 PyTorch 中最基础的数据结构,类似于 NumPy 的 ndarray,但具有 GPU 加速和自动微分功能。张量是多维数组,可以存储各种类型的数据,支持在 CPU 和 GPU 之间快速转换。
张量具有以下8 种基本属性:
data:被包装的 Tensor 数据
dtype:张量的数据类型
shape:张量的形状
device:张量所在的设备(CPU 或 GPU)
grad:data 的梯度
grad_fn:记录创建张量时用到的方法
requires_grad:表示是否需要计算梯度
is_leaf:表示是否是叶子节点
创建张量的常见方法包括:
# 从Python列表创建张量 x = torch.tensor([1, 2, 3, 4]) print(x) # tensor([1, 2, 3, 4]) # 创建全零张量 zeros_tensor = torch.zeros(3, 3) print(zeros_tensor) # tensor([[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]]) # 创建全一张量 ones_tensor = torch.ones(2, 4) print(ones_tensor) # tensor([[1., 1., 1., 1.], [1., 1., 1., 1.]]) # 创建单位矩阵 identity_tensor = torch.eye(4) print(identity_tensor) # tensor([[1., 0., 0., 0.], [0., 1., 0., 0.], [0., 0., 1., 0.], [0., 0., 0., 1.]]) # 创建随机张量(0-1之间) random_tensor = torch.rand(3, 3) print(random_tensor) # 随机值,例如 tensor([[0.12, 0.34, 0.56], [0.78, 0.90, 0.11], [0.22, 0.33, 0.44]]) # 创建指定值的张量 full_tensor = torch.full((2, 3), 5) print(full_tensor) # tensor([[5, 5, 5], [5, 5, 5]]) |
张量支持多种数学运算,包括元素级运算和矩阵运算:
# 张量加法 x = torch.tensor([1, 2, 3]) y = torch.tensor([4, 5, 6]) z = x + y # 元素级加法 print(z) # tensor([5, 7, 9]) # 矩阵乘法 a = torch.randn(2, 3) b = torch.randn(3, 4) c = torch.matmul(a, b) # 或使用a @ b print(c.shape) # torch.Size([2, 4]) |
3.2 动态计算图机制
PyTorch 最核心的特性是其动态计算图(Dynamic Computation Graph)机制,这是区别于 TensorFlow 1.x 等静态图框架的关键特征。动态计算图允许在代码运行时动态构建计算图,而不是预先定义完整的计算流程。
动态计算图的工作原理可以概括为以下几个步骤:
张量追踪:当创建张量并设置requires_grad=True时,PyTorch 开始追踪所有施加于该张量的操作
操作记录:每个对张量的数学运算都会在计算图中创建一个 Function 节点,记录具体操作并在反向传播时知道如何计算导数
前向传播:前向传播过程即时执行运算,计算图随之构建
反向传播:调用.backward()方法时,PyTorch 从输出开始,沿动态构建的计算图反向回溯,利用链式法则自动计算所有requires_grad=True张量的梯度
动态计算图的优势在于:
极高的灵活性:可以使用标准 Python 控制流语句(if-else、for 循环、while 循环)改变模型行为
直观易用,调试方便:计算图构建与代码编写顺序一致,调试直观
更适合研究实验:便于快速尝试各种新奇想法和模型结构
相比之下,静态计算图需要预先定义完整的计算流程,然后才能执行,虽然在大规模部署时可能有性能优势,但在研究和原型设计阶段灵活性不足。
3.3 自动微分系统(Autograd)
PyTorch 的自动微分系统通过torch.autograd 模块实现,这是 PyTorch 的基石。自动微分系统维护一个有向无环图(DAG),记录所有操作的历史,并通过链式法则自动计算梯度。
自动微分的核心组件包括:
Function 类:定义计算图中操作的前向传播和反向传播逻辑
Variable 类:代表张量,与 Function 类紧密相连,保留对原始 Function 的引用
使用自动微分的基本步骤:
# 创建需要梯度计算的张量 x = torch.tensor(3.0, requires_grad=True) w = torch.tensor(2.0, requires_grad=True) b = torch.tensor(1.0, requires_grad=True) # 构建计算图 y = w * x + b # 前向传播 z = y ** 2 # 前向传播 # 计算梯度(反向传播) z.backward() # dz/dw, dz/db print(w.grad) # tensor(6.) (dz/dw = 2 * (2*3+1) * 3 = 6*3=18? 实际应为 2*y * x = 2*7*3=42? 此处计算有误,正确应为:y=2*3+1=7, z=49, dz/dw=2y*x=2*7*3=42) print(b.grad) # tensor(14.) (dz/db = 2y = 2*7=14) print(x.grad) # tensor(42.) (dz/dx = 2y*w = 2*7*2=28? 实际应为 2y*w = 2*7*2=28) |
需要注意的是:
只能对叶子节点(用户直接创建的张量)获取梯度
多次调用.backward()会累积梯度,需通过.grad.zero_()手动清零
非叶子节点的梯度在反向传播后会被释放以节省内存
3.4 神经网络模块(nn.Module)
nn.Module是 PyTorch 中所有神经网络层和模型的基类,采用面向对象的设计思路,是构建复杂网络的核心工具。nn.Module 既是存放各种网络层结构的容器,也可以看作是一种结构类型。
nn.Module 具有以下核心属性:
_parameters:存储管理属于 nn.Parameter 类的属性(如权重、偏置)
_modules:存储管理 Module 类型的结构(如卷积层、池化层)
_buffers:存储管理缓冲属性(如 BN 层的 running_mean、std)
_hooks:存储管理钩子函数
创建自定义神经网络的标准流程:
import torch import torch.nn as nn import torch.nn.functional as F class NeuralNetwork(nn.Module): def __init__(self): super().__init__() self.flatten = nn.Flatten() # 将2D图像展平为1D向量 self.linear_relu_stack = nn.Sequential( nn.Linear(28*28, 512), # 输入层:784个特征 nn.ReLU(), nn.Linear(512, 512), nn.ReLU(), nn.Linear(512, 10) # 输出层:10个类别 )
def forward(self, x): x = self.flatten(x) logits = self.linear_relu_stack(x) return logits # 创建模型实例 model = NeuralNetwork() print(model) # 打印模型参数 for name, param in model.named_parameters(): print(f"Layer: {name} | Size: {param.size()} | Values : {param[:2, :2]}") |
输出结果显示模型结构:
NeuralNetwork( (flatten): Flatten(start_dim=1, end_dim=-1) (linear_relu_stack): Sequential( (0): Linear(in_features=784, out_features=512, bias=True) (1): ReLU() (2): Linear(in_features=512, out_features=512, bias=True) (3): ReLU() (4): Linear(in_features=512, out_features=10, bias=True) ) ) |
3.5 优化器与损失函数
PyTorch 提供了丰富的优化器实现,位于torch.optim模块中,包括 多种常用优化器:
- SGD(随机梯度下降)
- Adagrad(自适应学习率梯度下降)
- RMSprop(Adagrad 的改进)
- Adadelta(Adagrad 的改进)
- Adam(RMSprop 结合 Momentum)
- AdamW(Adam 的权重衰减版本)
- 以及其他如 Adamax、SparseAdam、ASGD、Rprop、LBFGS 等
使用优化器的基本步骤:
# 定义优化器 learning_rate = 0.01 momentum = 0.9 optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate, momentum=momentum) # 或使用Adam优化器 optimizer = torch.optim.Adam(model.parameters(), lr=0.001) # 训练循环中的使用 for epoch in range(num_epochs): optimizer.zero_grad() # 清零梯度 outputs = model(inputs) loss = criterion(outputs, labels) # 计算损失 loss.backward() # 反向传播 optimizer.step() # 更新参数 |
PyTorch 还提供了各种损失函数,如用于分类的交叉熵损失、用于回归的均方误差损失等。损失函数通常结合 nn.functional 模块使用。