PyTorch 和 TensorFlow,选一个还是两个都学?我的看法是:前期别急着做排除法,两个都装上、都跑一遍,反而能更快建立对深度学习框架的整体认知。
这篇文章面向刚入门深度学习、想在本地环境把 PyTorch 和 TensorFlow 都跑通的读者。内容覆盖两套框架的安装、环境搭建、GPU 验证、首个分类任务实战,以及两个框架并存时的切换技巧和常见排查思路。最值得关注的点不是某个安装命令本身,而是两套框架的设计逻辑差异——动态图与静态图分别适合什么阶段,学术研究和工业部署各自偏爱哪一套。搞懂这些之后,你再看新项目、读论文源码、接部署任务,都会比死记 API 舒服得多。
先说结论:如果目标是快速验证想法、跑论文代码、做研究实验,PyTorch 更顺手;如果团队已经沉淀了 TensorFlow 的 Serving 和部署链路,或者要面对移动端、嵌入式设备,那 TensorFlow 的成熟工具链会更有优势。但这两个结论不是劝你只选一个,而是告诉你:两条路都值得走一遍,而且完全可以同时走。
1. 两个框架不是二选一,而是两条技术路线
1.1 动态图与静态图:核心设计差异
PyTorch 默认采用动态计算图,模型在每次前向传播时都会实时构建计算图。这意味着你可以直接用普通 Python 的条件判断、for 循环去控制网络结构,调试时也能打断点查看中间张量。对研究和实验阶段来说,这种灵活性非常关键。我最初从 TensorFlow 1.x 转到 PyTorch 时,最明显的感觉就是:写模型像写普通 Python 代码,不再需要先定义占位符和 Session,出错的位置一眼就能看到。
TensorFlow 从 2.x 开始也默认开启 Eager Execution(动态执行模式),但它的底层设计仍然保留了静态图、SavedModel、GraphDef 这一整套序列化体系。换句话说,TensorFlow 给你的是“动态调试 + 静态部署”的组合方案:研究阶段用 Keras 高层 API 快速建模,部署阶段再通过tf.saved_model.save导出成固化模型,交给 Serving、Lite、JS 等工具链去跑。
这个差异会影响你写代码的方式,也会影响你排查问题的思路。PyTorch 的报错往往直接指向 Python 栈,TensorFlow 的报错则可能出现在底层图执行阶段,信息量更大,但定位起来也更绕。
1.2 学术研究与工业部署:各自的主场
看论文复现代码时,你会发现大量项目默认提供 PyTorch 版本。Transformer、Diffusion、LLM 微调这些热门方向,PyTorch 生态的更新速度通常更快。原因也不复杂:研究者需要随时改动模型结构,动态图 + Python 原生控制流最省事,社区里互相传代码的门槛也低。
TensorFlow 的强项在工业落地。从 TF Serving 到 TensorFlow Lite,再到 TensorFlow.js,它的部署链路是完整的。如果你的产品需要长时间稳定运行、需要标准化的模型版本管理、需要跑到手机或嵌入式设备上,TensorFlow 这套工具链依然很有竞争力。另外,很多老项目、企业内部项目还是 TensorFlow 写的,你会读、能改、能迁移,都是实打实的能力。
所以我的建议是:入门阶段不要把两个框架放在对立面。PyTorch 适合帮你“想明白”,TensorFlow 适合帮你“送上线”。两条腿走路,比单押一边稳得多。
2. 动手之前先确认环境:显卡、CUDA 和 Conda
2.1 先看显卡,再定安装方案
装框架之前,第一件事不是复制安装命令,而是确认机器的硬件和驱动情况。Windows 和 Linux 上最简单的方式是打开终端执行:
nvidia-smi重点看两行信息:显卡型号,以及右上角的 CUDA Version。这个版本号表示当前驱动支持的最高 CUDA 版本,不是你系统里已经装好的 CUDA 工具包版本。PyTorch 和 TensorFlow 安装时会自带运行时所需的 CUDA 库,多数情况下不需要你单独去装完整版 CUDA Toolkit,但驱动版本必须够新,否则底层库加载时会报错。
如果你没有 NVIDIA 显卡,或者用的是 Mac、纯 CPU 服务器,也不用放弃。PyTorch 和 TensorFlow 都有 CPU 版本,跑 MNIST、文本分类这类入门任务完全够用,只是训练速度会慢很多。学习阶段先把流程跑通,后面再考虑 GPU。
2.2 用 Conda 建独立环境,避免依赖互相打架
PyTorch 和 TensorFlow 对 Python 版本、CUDA 运行时、第三方库的要求并不完全一致,直接装在同一个环境里很容易出现依赖冲突。最省心的做法是装 Anaconda 或 Miniconda,然后给每个框架建独立虚拟环境。
conda create -n pytorch_env python=3.9 -y conda create -n tf_env python=3.9 -y这里选择 Python 3.9 是比较稳的折中方案,主流版本的 PyTorch 和 TensorFlow 基本都支持。如果你的机器已经装了更高版本的 Python,也可以先查一下目标框架官方文档里的支持列表,再决定具体版本。
为什么强调用虚拟环境?因为我在实际开发中见过太多“昨天还能跑,今天 import 就报错”的情况,最后排查下来都是某个包被升级了,或者两个项目共用了同一个 site-packages。虚拟环境隔离的不只是 Python 版本,还有一堆传递依赖。前期多花一分钟建环境,后面能省一晚上的排查时间。
2.3 CPU 版和 GPU 版怎么选
CPU 版安装简单、体积小、兼容性好,适合学习语法、跑小数据集。GPU 版训练速度快,但安装时要额外确认显卡驱动、CUDA 版本和框架版本的匹配关系。
判断标准很简单:如果你只是想体验框架的写法,CPU 版够了;如果你的模型稍大、数据稍多,或者想真实感受训练流程,那就优先 GPU 版。GPU 版安装失败的概率确实更高,但这不代表你的操作有问题,多数情况下是版本匹配问题。后面我会专门讲排查顺序。
3. PyTorch 安装与首个实战
3.1 安装步骤:从 pip 到验证
PyTorch 官方提供了一套按 CUDA 版本区分的安装命令。安装前先激活环境:
conda activate pytorch_env然后去 PyTorch 官网的 Get Started 页面选择系统、包管理器和 CUDA 版本,复制对应的命令即可。常见形式是:
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118这段是示例命令,实际安装时以你选择的 CUDA 版本为准。如果你不打算用 GPU,直接执行下面这条更简单:
pip install torch torchvision torchaudio这里有一个容易被忽略的点:PyTorch 的 CPU 版和 GPU 版都叫 torch,区别在于安装源不同。如果你之前装过 CPU 版,后来想换 GPU 版,最好先卸载干净再装,否则可能出现torch.cuda.is_available()一直返回 False 的情况。
3.2 验证 CUDA 是否真的可用
安装完成后,打开 Python 交互环境或写一个临时脚本,执行:
import torch print(torch.__version__) print(torch.cuda.is_available()) print(torch.cuda.get_device_name(0) if torch.cuda.is_available() else "CPU only")如果torch.cuda.is_available()返回 True,说明 PyTorch 能正常调用 GPU,可以进入下一步。如果返回 False,先不要急着重装,按下面顺序检查:
- 确认安装的是 GPU 版本,而不是 CPU 版本。
- 确认 nvidia-smi 能正常显示显卡信息。
- 确认显卡驱动版本够新,必要时去显卡官网更新驱动。
- 确认你选的安装源 CUDA 版本和驱动支持的 CUDA 版本不矛盾。
大多数情况下,第 1 条和第 3 条就能解决 80% 的问题。
3.3 用 MNIST 跑通第一个训练流程
环境没问题之后,我建议用 MNIST 手写数字分类作为第一个实战项目。这个数据集小、任务清晰、训练速度快,非常适合验证整个流程。下面是一个最小可运行的 PyTorch 训练脚本:
import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,)) ]) train_loader = DataLoader( datasets.MNIST('./data', train=True, download=True, transform=transform), batch_size=64, shuffle=True ) class Net(nn.Module): def __init__(self): super().__init__() self.fc = nn.Sequential( nn.Flatten(), nn.Linear(28 * 28, 128), nn.ReLU(), nn.Linear(128, 10) ) def forward(self, x): return self.fc(x) model = Net() loss_fn = nn.CrossEntropyLoss() optimizer = optim.Adam(model.parameters(), lr=0.001) for epoch in range(3): for x, y in train_loader: optimizer.zero_grad() out = model(x) loss = loss_fn(out, y) loss.backward() optimizer.step() print(f'epoch {epoch + 1}, loss: {loss.item():.4f}')这个脚本有几个值得注意的点。nn.Sequential只是把层堆起来,方便示例展示;真实项目里你经常会自定义forward逻辑,这就体现出 PyTorch 动态图的优势。optimizer.zero_grad()必须放在每次反向传播之前,否则梯度会在多次迭代中累积,导致训练结果异常。loss.item()的作用是把张量转成 Python 数字,方便打印,同时避免梯度图上的无关引用。
跑通这个脚本后,你可以试着改两个参数:一是把batch_size从 64 改成 128,观察训练速度和 loss 变化;二是把nn.Linear的隐藏层维度从 128 改成 256,感受模型容量对收敛过程的影响。这种“改一个参数,看一个结果”的实验方式,比一口气读完整个框架文档高效得多。
4. TensorFlow 安装与首个实战
4.1 安装步骤:TensorFlow 2.x 的简化逻辑
TensorFlow 从 2.x 开始把 API 大幅简化,Keras 被整合为官方推荐的高层接口。安装也简单了很多,GPU 和 CPU 版本不再分成两个包名,直接安装 tensorflow 即可:
conda activate tf_env pip install tensorflow这套命令在绝大多数普通环境里都能直接安装成功,如果机器有可用的 NVIDIA GPU 且驱动满足要求,TensorFlow 会自动启用 GPU 加速。如果你看到 TensorFlow 2.18 这类比较新的版本号,不用着急,安装后先确认 Python 版本在支持列表里就行。新版 TensorFlow 对 Python 版本的要求比较严格,Python 版本太新可能装不上,太老又可能缺少依赖,所以环境创建时选 Python 3.9 或 3.10 是比较稳妥的。
4.2 验证 GPU 是否被识别
安装完成后,执行:
import tensorflow as tf print(tf.__version__) print(tf.config.list_physical_devices('GPU'))如果输出里包含 GPU 设备信息,说明 TensorFlow 已经识别到显卡。如果只显示空列表,说明 TensorFlow 运行在 CPU 模式。
这里有一个容易误解的地方:TensorFlow 安装包本身的体积很大,因为它在底层集成了大量 CUDA 相关库。装完之后磁盘占用好几个 GB 是正常现象,不要以为出了问题。另外,TensorFlow 的 GPU 支持对驱动版本有要求,如果list_physical_devices('GPU')返回空,先检查驱动版本,再检查安装日志里是否有 CUDA 库加载失败的提示。
4.3 用 Keras 快速完成同一个分类任务
同一个 MNIST 任务,用 TensorFlow 的 Keras 接口写起来会非常紧凑:
import tensorflow as tf (x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data() x_train = x_train.astype('float32') / 255.0 x_test = x_test.astype('float32') / 255.0 model = tf.keras.Sequential([ tf.keras.layers.Flatten(input_shape=(28, 28)), tf.keras.layers.Dense(128, activation='relu'), tf.keras.layers.Dense(10, activation='softmax') ]) model.compile( optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'] ) model.fit(x_train, y_train, epochs=3, batch_size=64, validation_data=(x_test, y_test))如果你手写过 PyTorch 版本,再看这段代码会明显感觉到差异。Keras 把训练循环封装进了model.fit,你不需要手动处理zero_grad、backward、step这些步骤,适合快速验证想法。但封装也意味着可控性下降,当你想在训练过程中加入自定义逻辑(比如梯度裁剪、分层学习率、自定义回调)时,就需要去理解 Keras 的回调机制和自定义训练循环。
对比两个实现你会发现:PyTorch 把控制权交给你,TensorFlow/Keras 把训练流程标准化。没有好坏之分,只看你当前的场景需要什么。
5. 两个框架并存:环境切换与项目选型
5.1 环境切换的两个实用技巧
既然两个环境都建好了,平时使用时的核心就是切换干净。我一般会这样做:
# 切到 PyTorch 环境 conda activate pytorch_env python train_pytorch.py # 切到 TensorFlow 环境 conda activate tf_env python train_tf.py只要命令在对应环境里执行,依赖就不会混。需要注意两个容易踩的坑:
第一,Jupyter Notebook 或 VS Code 这类编辑器,在启动时一定要确认当前解释器是哪个环境的 Python,否则会出现“明明装了 torch,但 import 报错”的情况。第二,不要在同一个 Python 进程里同时 import torch 和 tensorflow。虽然大部分时候不会立刻崩,但两个框架底层可能使用不同的 CUDA 运行时版本,混用容易触发奇怪的段错误或显存分配异常。如果确实需要同时用,建议拆成两个独立进程,通过文件、数据库或消息队列做数据中转。
5.2 项目选型:什么时候用谁
我给出的判断标准很简单:
- 复现论文、做实验、快速验证 idea,优先 PyTorch。
- 已有项目是 TensorFlow 维护的,优先沿用 TensorFlow,不要为了“用新的”而重写。
- 需要服务化部署、移动端/嵌入式部署,TensorFlow 的 Serving、Lite 工具链更成熟。
- 团队里大多数人都熟悉哪个,就用哪个。团队协作的成本往往比框架本身的技术差异大得多。
- 如果你在 Jetson 这类嵌入式设备上开发,比如 JetPack 6.x 系统,不能直接照搬 PC 的安装命令。ARM 架构和 JetPack 版本对 PyTorch 有严格的版本对应关系,需要先查清设备支持哪个版本的 PyTorch,再按官方指引安装,否则很容易遇到编译失败或无法加载。
5.3 从 PyTorch 切到 TensorFlow 的常见坑
两个框架的 API 命名和数据处理方式差异不小,切换时最常遇到三类问题。
第一,Dataset 接口不通用。PyTorch 的DataLoader、Dataset和 TensorFlow 的tf.data.Dataset完全两套体系,写数据处理代码时不能只复制前一半。
第二,模型保存方式不同。PyTorch 常用torch.save保存状态字典,而 TensorFlow 2.x 推荐使用SavedModel格式或 Keras 的.h5。如果模型要在两个框架之间迁移,不能直接读文件,只能重新训练或者用中间格式转换。
第三,版本更新带来的行为变化需要注意。比如较新版本的 PyTorch 里,torch.load对weights_only参数的默认值做了调整,如果你加载的是别人很久之前保存的模型文件,可能会遇到警告甚至加载失败。解决办法是加载时明确指定weights_only的值,同时确认模型文件的来源是可信的,不要随意加载不明来源的权重文件。这类问题在社区里很常见,遇到时先查一下当前版本的 release notes,很多时候不是你的代码写错,而是默认行为变了。
6. 安装失败和训练异常的排查清单
6.1 安装失败先看这三层
不管是 PyTorch 还是 TensorFlow,安装失败时我建议从下往上排查。
第一层是网络和下载源。pip 下载超时、安装到一半中断,多半是网络波动。国内用户可以把 pip 源换成镜像源,或者直接看安装命令里的下载地址是否能访问。这个问题和框架本身无关,但最容易让人误判。
第二层是 Python 版本和 pip 版本。pip 版本太旧可能导致无法解析某些 wheel 包;Python 版本不在框架支持列表里,则可能找不到匹配的安装包。建议先执行python --version和pip --version确认基础环境。
第三层是系统依赖。Linux 上常见的是缺少某些系统库,Windows 上常见的是缺少 Visual C++ 运行库。这类错误信息通常比较明确,照着提示装即可。
一个好消息是,绝大多数安装问题在你换一个干净的虚拟环境后都会消失。所以我一直强调先建环境、再安装,这是一条成本极低的容错路径。
6.2 训练时报错的定位顺序
训练脚本报错时,我的排查顺序是这样的:
- 先看完整报错栈,不要只看最后一行。PyTorch 报错栈会指向具体代码行,TensorFlow 有时会把底层 C++ 的信息混进来,但最初的 Error 类型往往已经说明了问题。
- 再确认输入形状。
Linear层的输入维度和数据形状不匹配,是新手最常见的错误之一。 - 再看损失函数和标签的类型。分类任务里标签是整数还是独热编码,决定了你该用哪种损失函数。
- 然后看显存和内存。训练中途突然崩溃、进程被杀,通常不是代码逻辑问题,而是显存或内存耗尽。把
batch_size调小,或者改用梯度累积,往往比优化代码更快见效。 - 最后考虑环境问题。确认当前进程用的是哪个 Python、哪套 CUDA 库,不要在排查到一半时发现环境切错了。
6.3 新手学习路线:先跑通,再深入
如果你刚接触这两个框架,我不建议一上来就啃官方文档的每一个 API。更实际的做法是:
第一步,把上面两个 MNIST 脚本分别跑通,确保两个环境都正常工作。第二步,改参数、改网络结构,观察训练结果的变化。第三步,用同一个数据集(比如猫狗分类、文本情感分类)分别用两个框架实现一遍,体会 API 组织方式的不同。第四步,找一份开源项目的代码,先读懂数据加载和模型定义,再跑起来,最后尝试替换里面的一两个模块。
等你走到第四步,就会发现框架之间的差别逐渐变小,因为真正核心的东西——数据处理、模型结构、损失函数、优化器、评估指标——是相通的。框架只是表达这些思想的工具。
我个人还是更建议把单任务先跑稳,再考虑批量和接口化。前面有人问“我全都要”是不是太贪心,我的回答是:框架不是信仰,是工具。两个都装上、都跑一遍、都踩过坑,你自然知道在什么场景下该拿哪个出来用。环境搭好之后,剩下的就是多写、多跑、多排查,这条路没有任何捷径。
最后留几个我自己排查时会优先看的点:安装命令是不是从官方最新页面复制的,虚拟环境有没有激活对,显存是不是被其他进程占着,模型文件路径和权限是否正常。这四件事能覆盖大多数“看起来像框架问题”的实际情况。