PyTorch 背后有一位被反复提起的人:Soumith Chintala。他是 PyTorch 的联合创始人,现在也是 Meta 副总裁,长期在 Meta AI 团队里推动这个开源深度学习框架往前走。很多人只知道 PyTorch 装起来方便、跑模型好用,却不清楚它为什么能在早期一堆框架里冒出来。这篇不打算做人物传记式复述,我想从工程角度拆两件事:Soumith 为什么坚持把动态计算图和 Python 优先做到极致,以及今天你要学 PyTorch、搭环境、跑批量实验、甚至做生产部署时,最该先搞清楚哪些问题。
1. 从被拒多次到改变深度学习研究方式
1.1 PyTorch 出现之前,深度学习框架并不好用
在 PyTorch 发布之前,深度学习框架的主流用法是静态计算图。以 TensorFlow 1.x 为代表,你要先定义一张完整的图,再放进会话里执行。图的结构一旦确定,运行阶段就不能随意改。这样做的好处是容易在编译和部署阶段做优化,但坏处也很明显:调试困难。中间某个张量不对,你很难直接打断点看每一步的值。
同一时期还有一个叫 Torch 7 的框架。它在学术圈有很多研究者使用,底层能力很强,但前端用的是 Lua 语言。Lua 本身不复杂,问题是当时的 Python 生态已经非常庞大,数据科学、机器学习、可视化社区都集中在 Python 里。框架想被更多人接受,语言前端是一个绕不过去的门槛。
Soumith Chintala 最早就是 Torch 7 社区里的核心人物。他做过大量底层库、模型实现和社区维护工作,很清楚 Lua 生态对框架传播的制约。后来的 PyTorch 选择 Python 优先,本质上不是简单的“换一门语言”,而是把整个框架融入到 Python 的开发习惯和工具链里。这个选择在今天看起来理所当然,但在当时需要非常大的决心。
1.2 “被拒 15 次”和持续投入
公开报道里经常提到,Soumith 早期申请研究岗位或项目时多次被拒,比较常见的说法是 15 次。具体每一次发生在什么阶段、什么项目,我没有办法替代当事人核实。但这件事放在 PyTorch 的形成背景下看,确实有参考意义。
被拒绝没有让他退出社区。他持续出现在 Torch 和后来 PyTorch 的开发一线,做底层实现、参与社区讨论、维护工具链。这种持续投入带来的不是某个单点突破,而是对“研究者到底需要什么样的框架”这件事越来越准确的判断。到了 2017 年前后,PyTorch 正式发布,很快依靠动态计算图、Python 优先和调试友好的体验,逐渐成为深度学习研究社区的重要选择。
对普通开发者来说,这个经历值得注意的不是“坚持就能成功”之类的结论。更实际的价值是:一个项目能不能成,很大程度上取决于方向是否踩中了真实需求,而不是你把商业计划或论文写得有多漂亮。动态图、Python 生态、调试体验,这些今天被反复提起的特性,都是真实需求导向的结果。
2. PyTorch 到底解决了什么问题
2.1 动态计算图让研究和调试变顺了
PyTorch 最核心的设计,是动态计算图。简单说,代码执行到哪一层,计算图就构建到哪一层。你在模型 forward 里写 if、for、print,都是普通 Python 逻辑,中间任意一个张量的形状和数值都能直接打印。
静态图不是不能做调试,但在图编译阶段暴露问题,和运行阶段暴露问题,体验差别很大。早期用静态图写模型,经常遇到“图建完了,一执行报错,错误堆栈却和源代码对不上”的情况。PyTorch 把这个过程变直观了:哪里错,定位哪里,print 和张量断言都能用。
对做研究的人来讲,这个特性非常关键。因为研究工作的主要成本是模型迭代:改结构、调损失、换数据、观察中间结果。如果框架让每次迭代都很痛,再高的运行性能也抵消不了。早期很多 PyTorch 用户对比的感受是:“同样的想法,用 PyTorch 一个下午能跑通,用静态图可能要加两天调试时间。”这是运维性能之外的真实收益。
2.2 Python 生态和社区网络效应
PyTorch 另一个重要选择是拥抱 Python。张量操作风格和 NumPy 很接近,自动求导机制透明,模型组织通过 nn.Module 完成。这些设计降低了学习成本,也让现有 Python 开发者能快速迁移。
社区方面,torchvision、torchaudio、torchtext 覆盖了图像、音频、文本的常用数据和处理流程。更关键的是 HuggingFace 等第三方生态大量基于 PyTorch 提供预训练模型,很多论文作者开源权重和示例代码时,首选也是 PyTorch。使用的人越多,能搜到的问题答案越多,新模型接入越快,这种网络效应会让框架越来越难被替代。
2.3 训练和部署不是一回事
PyTorch 经常被说“研究好用,部署麻烦”。更准确的说法是:训练阶段用动态图,生产阶段需要另一套工具链衔接。TorchScript、ONNX 导出、torch.compile、量化工具以及各种推理引擎,都是解决“从研究模型到线上服务”这一段路的。
所以不要指望只用训练时的 Python 脚本就能完成高性能线上推理。你在 PyTorch 里训练出来的权重,到了线上可能要转成 torch.jit 或 ONNX,再用专门引擎加载。这个步骤不复杂,但要单独学、单独测。能跑通训练,不代表能直接部署。
3. 先搭一个能跑的 PyTorch 环境
3.1 为什么建议用 Anaconda 创建独立环境
我见过很多初学者直接把 PyTorch 装进系统 Python,半年后项目一多,版本冲突全来了。PyTorch 和 torchvision、CUDA 组件、NumPy 之间有版本绑定关系,装在全局环境里很容易互相覆盖。
更稳妥的做法是使用 Anaconda 或 Miniconda 创建虚拟环境。这样每个项目一套 Python 和依赖,环境坏了直接删掉重建,不会影响其他项目。
常用命令是:
# 创建环境,python 版本以你要安装的 PyTorch 版本要求为准 conda create -n pytorch python=3.10 -y conda activate pytorch创建完成后,去 PyTorch 官方安装页选择你的操作系统和包管理器,官方会生成对应的安装命令。这里要特别注意:官方安装页是最新信息的来源,第三方博客里的旧命令经常和当前版本不匹配。
3.2 CPU 版和 GPU 版怎么选
学习阶段,CPU 版完全够用。入门教程、张量操作、自动求导、小模型训练,CPU 都能跑,只是慢一些。很多人的第一个模型其实卡在环境问题,而不是算力问题。
GPU 版需要注意三点:
- 先看 NVIDIA 驱动支持的 CUDA 版本,用
nvidia-smi查看。 - 再去 PyTorch 官方安装页选择对应的 CUDA 标签,比如 cu118、cu121 这类格式。
- 安装完成后用
torch.cuda.is_available()验证,输出 True 才说明 GPU 环境可用。
Windows 用户最容易踩的坑,是随便复制网上的安装命令,结果 CUDA 标签和驱动不匹配。比如驱动只支持某个 CUDA 版本,你却装了需要更高 CUDA 版本的 PyTorch,启动时可能直接报找不到 cuda runtime。正确做法是先看驱动,再选安装包。
AMD 显卡用户要特别留意。PyTorch 对 AMD GPU 的支持,通常走 ROCm 路线,不能直接照搬 NVIDIA 的 CUDA 安装命令。不同系统、驱动和 PyTorch 版本的匹配情况不一样,要先看官方支持矩阵再操作。
3.3 一个最小的验证脚本
装完环境后,不要急着跑大模型。先写一个最小脚本验证张量和自动求导:
import torch x = torch.randn(4, 3) w = torch.randn(3, 1, requires_grad=True) y = x @ w loss = y.pow(2).mean() loss.backward() print("x shape:", x.shape) print("w grad:", w.grad)如果 GPU 版安装成功,再单独执行:
print(torch.cuda.is_available())看到 True 就可以继续了。如果输出 False,先检查是否装了 CPU 版、驱动是否正常、PyTorch 和 CUDA 版本是否匹配。CPU 版输出 False 是正常的,这一步要分清楚。
注意:验证环境时,一条命令跑通了只说明环境基本可用。真正进入项目后,还要检查数据集路径、GPU 显存和依赖之间的兼容性。
4. 从最小样例到完整项目的学习路线
4.1 先吃透五个核心抽象
很多人学 PyTorch 时喜欢直接找热门模型代码,结果读得云里雾里。我的建议是先吃透五个核心概念:
- Tensor:张量,一切数据的基本容器,要注意 dtype 和 device。
- autograd:自动求导,所有反向传播的基础,由
requires_grad控制。 - nn.Module:模型模块,PyTorch 里模型基本都继承这个类。
- optimizer:优化器,负责更新参数。
- DataLoader:数据加载器,负责按批次取数。
这五个概念看起来简单,但所有模型都是它们的组合。比如自定义模型时,你要定义一个继承 nn.Module 的类,在__init__里放子模块和参数,在forward里写计算过程。调用 loss.backward() 后,梯度值会挂到每个参数的.grad上,优化器再根据.grad更新参数。把这条链路想清楚,后面看任何模型都不会太慌。
4.2 用经典项目练手,比追新模型更重要
官方 60 分钟入门、CIFAR-10 分类、迁移学习、给 seq2seq 的 decoder 加 attention,这些经典项目用来练手足够了。特别是迁移学习,很多人会用到“冻结部分模型”的操作:
for param in model.parameters(): param.requires_grad = False # 只让分类头继续更新 for param in model.fc.parameters(): param.requires_grad = True optimizer = torch.optim.Adam(filter(lambda p: p.requires_grad, model.parameters()))这里的关键是:冻结参数后,优化器里也要过滤参数,否则梯度虽然不更新,但 optimizer 仍然会管理这些参数,只是不需要的显存和计算白白浪费。很多人只改了 requires_grad,忘了过滤 optimizer,结果发现训练没有变快。
时间序列相关的项目也可以拿来练手,比如用 TCN、Transformer 做序列预测实验。但要注意,股票价格这类金融时序预测非常容易出现过拟合,必须先想清楚数据划分、特征构造和验证方式。拿 PyTorch 做实验练习完全没问题,但不要把它当成一个能稳定赚到钱的现成方案。
4.3 进阶能力:compile、混合精度、分布式训练、模型加载
基础跑顺后,再往这些方向扩展:
- torch.compile:有些模型能明显加速,有些模型收益有限,先当可选项。
- 混合精度:在 NVIDIA GPU 上训练大模型很常用,能降低显存占用,但需要验证精度变化。
- 分布式训练:单卡跑不动了再上,不要一开始就设计复杂集群。
- 模型保存和加载:要注意 checkpoint 的结构、路径、权限,以及新版 PyTorch 对
torch.load的weights_only参数默认值有调整。
特别提一下 weights_only。新版 PyTorch 出于安全考虑,改变了torch.load在部分版本中的默认行为,旧代码加载训练好的模型时可能报错。如果是从网上下载的权重,要尽量按要求使用安全的默认配置;如果你确定文件来自自己的训练脚本,可以按版本要求显式传参。看到这类报错时,不要急着换回旧版本,先看官方 Release 说明。
5. PyTorch 不是全能,也不是唯一
5.1 框架生态与真实趋势
现在讨论框架选型,不能只说“谁比谁强”。PyTorch、TensorFlow、JAX 各有侧重。
| 框架 | 定位 | 典型场景 |
|---|---|---|
| PyTorch | 动态图优先,Python 友好 | 学术研究、模型训练、快速迭代 |
| TensorFlow | 生产链路完整,静态图传统强 | 历史项目、部分企业部署 |
| JAX | 函数式、可微分编程 | 科研实验、高性能矩阵运算 |
这几年研究论文和开源模型里,PyTorch 权重和示例更多,许多新项目默认优先给 PyTorch 实现。TensorFlow 仍在不少存量项目里运行,但不是新项目的默认首选。这不是说它“没用了”,而是生态重心转移。个人开发者如果要从头学,我建议先主攻 PyTorch,需要时再补其他框架。
5.2 vLLM、LangChain 和 PyTorch 不是一个层面
最近很多人问:LangChain、vLLM 和 PyTorch 是一个类型的东西吗?不是。
| 项目 | 定位 | 典型作用 |
|---|---|---|
| PyTorch | 底层深度学习训练/研究框架 | 张量计算、自动求导、模型训练 |
| vLLM | 大模型推理加速和服务引擎 | 优化线上推理延迟和吞吐 |
| LangChain | 大模型应用编排层 | 组合提示词、外部工具和模型调用 |
| ONNX | 模型交换中间格式 | 在不同框架之间迁移模型 |
它们的层级不同。你拿 LangChain 写应用时,底层模型可能还是 PyTorch 或 PyTorch 衍生工具在跑;你用 vLLM 部署模型时,也要先有训练好的 PyTorch 权重。这些工具解决不同阶段的问题,不是“有一个就不用其他”的关系。