☰
TensorFlow没凉!2024生态解析、环境搭建与PyTorch选型指南
2026/11/3 14:35:13 网站建设 项目流程

最近后台总有人问一个特别扎心的问题:2024年了,TensorFlow是不是已经没人用了?问的人多半是在校学生或者想转行的朋友,看过几篇PyTorch的教程,又看到GitHub上TensorFlow的issue讨论没以前热闹,就觉得这东西是不是该“入土”了。每到这个时候我都想拦一句:别急,先把TensorFlow装起来跑个模型,再下结论也不迟。

这篇就打算从2024年的视角重新把TensorFlow过一遍。先聊它现在到底处于什么生态位,然后讲安装环境怎么搭最省心,再说清楚它的核心API逻辑,最后用一个小项目把整个流程串起来。同时聊透一个绕不开的话题——TensorFlow和PyTorch现在到底怎么选。这篇不是劝你“非要用TensorFlow不可”,而是帮你建立一个足够完整的判断坐标系,知道这东西在什么场景下是刚需,在什么场景下换了更顺手。适合刚开始接触深度学习、想在两个框架之间做选择、或者打算把旧项目从TensorFlow 1.x迁到2.x的读者。

1. 2024年的TensorFlow:看似“冷”了,但实际底盘很稳

1.1 为什么会有“TensorFlow凉了”的错觉

这个错觉的来源很直接。学术界发论文,大家刷Arxiv,会发现PyTorch代码出现的频率越来越高,尤其是Transformer、扩散模型、大语言模型这些东西,几乎默认用PyTorch实现。有的统计里,NeurIPS、ICML这些顶会的论文里PyTorch使用占比能到百分之七八十,TensorFlow反而成了少数派。学生跟着导师做实验,互相传代码,全是.pt后缀的权重文件,那自然觉得全世界都在用PyTorch。

再加上TensorFlow社区确实发生过一些震荡。Google在TensorFlow和JAX之间的资源分配,Keras 3.0又搞了一套多后端,让人感觉方向一直在变。社区讨论热度没有2018年那么疯狂,新手入坑前搜一圈,很容易觉得这框架“不香了”。

但“论文里用得少”和“生产环境没人用”是两个完全不同的概念。我这些年接触过不少做推荐系统、广告CTR预估、风控和工业视觉的团队,他们线上跑的模型很多还是TensorFlow的SavedModel。这些系统往往已经稳定运行了两三年,模型导出一份pb文件扔到TF Serving里,QPS扛得住,服务稳定性有保证,没必要为了追时髦把整个链路推翻。

1.2 为什么生产端依然相信TensorFlow

这里头有几个底层逻辑。第一是部署链路成熟,TF Serving、TensorFlow Lite、TensorFlow.js覆盖了从服务器到移动端再到浏览器的全场景,这在PyTorch那边虽然现在也补上了TorchServe和ExecuTorch,但相比TensorFlow多年沉淀的工具链还是嫩了一些。第二是Keras API的稳定性和易用性在2.x时代大大拉高了开发效率,团队协作成本低。第三是Google内部大量业务跑在TPU上,而TPU的软件栈和TensorFlow/XLA深度绑定。如果你有一天需要把模型跑到TPU上,TensorFlow依然是第一公民。

2024年的节点上还有一个值得注意的变化:Keras 3.0开始支持多后端,同一个模型代码可以在TensorFlow、JAX和PyTorch之间切换。这个动作很微妙,等于官方承认了生态多元,同时把TensorFlow定位成一个底层执行引擎而非唯一入口。也就是说,你完全可以用熟悉的Keras风格写模型,后端选TensorFlow来跑数据管线和部署。

所以结论是:TensorFlow没有凉,它只是从一个“被捧上天的明星”变成了“做基础设施的老实人”。对想进工业界搞模型部署的人,TensorFlow这碗饭是绕不开的。

2. 安装TensorFlow:版本、硬件、环境一次说清

2.1 安装前必须确认的版本策略

很多人安装翻车,不是网络问题,而是不知道TensorFlow和Python、CUDA、cuDNN之间有严格的版本配对表。就以2024年底的状态来说,稳定版已经到2.18,官方推荐的Python版本是3.9到3.12,再往上(比如Python 3.13)经常会出现依赖冲突,因为trition、numba这些库还没跟上。

安装命令看起来简单一行:

pip install tensorflow

但我要多提醒一句:如果你在Linux环境里装,这一步装的是带CUDA支持的GPU版本;如果在Windows上是原生安装,默认也带GPU支持,前提是卡和驱动没问题;如果你在macOS上装,装的是CPU版本,M系列芯片要额外装tensorflow-metal来启用GPU加速。

更稳妥的做法是用虚拟环境隔离。我自己的习惯是:

python -m venv tf_env source tf_env/bin/activate # Windows下用 tf_env\Scripts\activate pip install --upgrade pip pip install tensorflow python -c "import tensorflow as tf; print(tf.__version__)"

这一套下来,如果你只是CPU跑个小模型,基本就能用了。但如果你需要GPU加速,事情要再细一点。

2.2 GPU环境配置:最容易踩坑的死角

GPU加速的安装流程里最大的坑不是TensorFlow本身,而是CUDA和cuDNN的版本对齐。官方在2.18版本里对应的组合大致是:NVIDIA驱动建议525以上,CUDA 12.3,cuDNN 9。这两个东西不是装得越新越好,而是要和TensorFlow的预编译二进制对齐,装太新反而识别不了。

我见过太多人卡在一个现象上:tf.config.list_physical_devices('GPU')输出是空的,但nvidia-smi明明能看到显卡。原因绝大多数是:

  • 装的是CPU版TensorFlow(注意某些pip镜像源会把tensorflow指到tensorflow-cpu);
  • CUDA版本和TF不匹配,加载共享库失败;
  • 在容器里没挂载GPU设备(这个要单独看docker run的--gpus参数)。

排查的时候建议用:

import tensorflow as tf print(tf.config.list_physical_devices('GPU'))

如果输出列表是空的,再查:

print(tf.test.is_gpu_available(cuda_only=True))

这里还要提一个Windows用户的经典误区:在Windows下用WSL2装TensorFlow跑GPU,NVIDIA驱动要装Windows侧的,然后在WSL2里装CUDA toolkit,两边的驱动版本要联动。如果你没搞清楚这个联动,很常见的症状就是“WSL2里看得到GPU,但TF永远用不了”。

2.3 国内镜像源的实际意义

安装的时候用国内镜像能省很多时间,这个不用我说大家也都懂。我常用的是清华的PyPI镜像:

pip install tensorflow -i https://pypi.tuna.tsinghua.edu.cn/simple

另外提一句,如果你要用Keras 3的多后端能力,可以顺手把JAX或者PyTorch也装上,然后通过KERAS_BACKEND环境变量切换。这个功能在2.16之后成了默认行为,Keras已经不在TensorFlow主包里了,是独立安装的keras包,很多老朋友不知道这一点,以为装了tensorflow就会自动带上Keras,其实在2.16版本上装tensorflow会同时拉一个匹配的Keras版本,倒也不用太担心,但二手环境里经常会出现两个Keras版本叠加的混乱情况。

排查这类混乱的办法很简单,输出一下这两个路径看看是不是同一个环境下的版本:

import keras import tensorflow as tf print(keras.__version__) print(tf.__version__)

3. 从“会调用API”到“理解TensorFlow的运行逻辑”

3.1 Eager Execution让2.x彻底友好

TensorFlow 1.x时代劝退新人最狠的一点是计算图模式:你得先把整张图描述清楚,然后放到Session里跑,像写SQL一样,写完整个查询最后execute一下。逻辑没错,但对快速验证想法很不友好。到了2.x,默认开启Eager Execution,就是Python里写一步执行一步,调试的时候能直接看到中间结果——这体验终于和PyTorch一致了。

对于新手来说,你只需要记住一个最大的区别:在2.x里,普通Python代码写出来的张量运算就是动态的,不用手动建图和跑session。当你需要性能的时候再通过@tf.function把一段python代码编译成静态图。“动态的灵活”和“静态的性能”你都可以要,关键要会切换。

3.2 张量、轴和形状:绕不开的底层概念

说句实话,TensorFlow里最抽象的并不是张量本身——它就是多维数组。真正的门槛是维度操作和广播机制。很多刚开始写的人搞不清楚shape=(3, 4)和shape=(4, 3)差在哪里,reshape之后数据到底怎么排列。

这里我建议一个经验:遇到维度问题,先手动算一下输入输出形状,再用小矩阵打印验证。不要凭感觉写。比如tf.matmul要求两个矩阵最后两维匹配,前面维度广播,写错了报出来的维度错误信息是英文长句子,第一次看确实容易懵,但只要你花十分钟把官方那张形状匹配逻辑图过一遍,之后就很难再错。

3.3 Keras是你的“冰箱”,不是玩具

很多教程喜欢把Keras说成“高级API”或者“为小白设计”,这个说法会让人小看它。Keras 3在2.16之后内置了完整的模型构建、训练、评估、导出、分布式策略接口,它更像一台套好保鲜膜的冰箱——你往里面放什么菜都能保鲜,但真正的烹饪还是得你自己做。

极端情况下,你完全不用再写底层的tf.Variable和tf.GradientTape,用keras.Sequential或者keras.Model子类化就能解决95%的建模需求。但如果你要自定义一个特殊的损失函数,或者要按batch做一些默认API做不到的变换,那还是要理解train_step是怎么被子类重写的。我遇到不少人在自定义训练循环这卡住,这里给个最小框架:

import tensorflow as tf from tensorflow import keras class MyModel(keras.Model): def train_step(self, data): x, y = data with tf.GradientTape() as tape: y_pred = self(x, training=True) loss = self.compiled_loss(y, y_pred) grads = tape.gradient(loss, self.trainable_variables) self.optimizer.apply_gradients(zip(grads, self.trainable_variables)) self.compiled_metrics.update_state(y, y_pred) return {m.name: m.result() for m in self.metrics}

这段代码是自定义训练循环的地基。官方文档讲得比我详细,但核心就是:梯度带记录前向过程,反向算梯度,优化器更新变量。

4. 一个完整的入门实战:图像分类从零到SavedModel导出

4.1 数据从哪里来:用内置数据集先跑通

任何框架教程,如果第一步就让你去网上下载几千张图片做清洗标注,那多半是在劝退。我建议新手上手就用tf.keras.datasets里的现成数据,比如Fashion MNIST——它是MNIST的替代品,同样是28×28灰度图,但类别是服装,对新手更友好,训练起来也快。加载只需要一行:

(x_train, y_train), (x_test, y_test) = tf.keras.datasets.fashion_mnist.load_data()

拿到数据先做归一化:x_train = x_train.astype("float32") / 255.0。这个不归一化,训练出来的loss很可能一开始就卡住,因为像素值0~255和模型初始化的权重范围差距太大,梯度更新会很别扭。

4.2 模型构建和训练配置

模型用最简单的多层感知机或者一个小卷积网络都可以。这里选个小型CNN来演示,因为CNN比纯Dense更能体现“网络结构”的威力:

model = keras.Sequential([ keras.layers.Reshape((28, 28, 1), input_shape=(28, 28)), keras.layers.Conv2D(32, 3, activation="relu"), keras.layers.MaxPooling2D(), keras.layers.Conv2D(64, 3, activation="relu"), keras.layers.MaxPooling2D(), keras.layers.Flatten(), keras.layers.Dense(128, activation="relu"), keras.layers.Dense(10, activation="softmax") ]) model.compile( optimizer="adam", loss="sparse_categorical_crossentropy", metrics=["accuracy"] )

为什么用sparse_categorical_crossentropy而不是categorical_crossentropy?因为前者的标签是整数索引,后者需要one-hot编码。Fashion MNIST的标签是0到9的整数,直接用sparse版本省一步。

训练的时候建议加上validation_split和回调:

history = model.fit( x_train, y_train, epochs=10, batch_size=64, validation_split=0.2, callbacks=[keras.callbacks.EarlyStopping(patience=3, restore_best_weights=True)] )

这里EarlyStopping很实用——它能监测验证集指标,连续几个epoch没有提升就自动停止,并且restore_best_weights会把模型恢复到历史上验证集表现最好的那一步。很多时候模型过拟合了还不知道,就是没加这个回调。

4.3 评估、导出和部署前的形态转换

训练完,model.evaluate(x_test, y_test)看一下测试集准确率,正常Fashion MNIST跑到0.9以上是没问题的。然后就是导出:

model.save("mnist_cnn.keras") model.export("saved_model_dir")

在2.16之后的Keras 3里,.keras格式是官方推荐的保存格式,一个文件搞定架构和权重,清清楚楚。而export则导出完整SavedModel,可以直接给TF Serving用。

到这里,你的第一个完整闭环就打通了:数据加载、模型定义、训练、回调、评估、导出。后续要上线服务,只需要用tensorflow/serving镜像里的tensorflow_model_server把saved_model_dir卷进去跑起来就行了。

5. TensorFlow与PyTorch的流行趋势:选型不是站队

5.1 两边到底差在哪:一句话概括

如果非要用一句话说清两个框架的本质差异,我的理解是:TensorFlow是“先生产后研究”的框架,PyTorch是“先研究后生产”的框架。TensorFlow的图优化、分布式策略、部署工具链一开始就是奔着工业级来的;PyTorch的调试体验、动态图和Python风格从一开始就奔着科研人员的“快速验证”去的。两边这几年疯狂互相学习,你加动态图,我也加静态导出;你有TorchServe,我有TF Serving,但基因里的侧重点还在。

拿2024年的一个典型场景举例:训练一个中小规模的视觉模型,PyTorch的写法更像我平时写Python代码,想打印哪里就打印哪里,断点调试稳如老狗;TensorFlow在Eager Execution下也做得不错,但一旦你加上@tf.function去追性能,中间报错的信息量就会陡增,排查起来确实费力一点。

反过来讲部署:TensorFlow这边导出一个SavedModel目录,里面是pb文件和variable文件夹,用TF Serving时直接通过gRPC或REST接口对外服务,还能用TensorFlow Model Server自带的批量调度和版本管理。PyTorch那边TorchServe也做得相当可以,但你想在移动端跑,TensorFlow Lite和TFLite的优化工具链至今依然更成熟。

5.2 2024年的趋势对普通开发者的影响

从论文总量来看,PyTorch的势头确实很猛,尤其在生成式模型、大模型微调这块,HuggingFace生态从底层就是PyTorch优先的,你拿个Qwen或者Llama来微调,社区的示例代码绝大多数是.py加.pt,TensorFlow虽然也有transformers库的支持,但总有一种“二等公民”的味道,很多新模型发布当天只有PyTorch权重。

这种生态差异带来的一个实际判断是:如果你主要在学术圈做研究,或者主要玩开源预训练模型,那PyTorch的高频场景明显更多;但如果你做的项目要进企业生产环境,团队里要长期运维一套模型服务,或者你的客户对部署有严格的私有化和性能要求,那TensorFlow的成熟工具链会让你省很多事。

我个人的看法是,不要在这个问题上做“信仰绑定”。两边都是开源框架,代码都是公开的,真正值钱的是你对深度学习本身的理解。我带过不少实习生,给他们一个模型结构描述,用TensorFlow写成和PyTorch写成,工作量差异远没有网上说的那么夸张。换个框架就写不出来代码,说明你还是不会建模,而不是框架有问题。

5.3 迁移旧项目的成本意识

如果你手上有个TensorFlow 1.x的老项目,准备迁到2.x,这里有个非常重要的心理预期:别指望搜索替换完成迁移。1.x里的tf.Session()、tf.placeholder、tf.get_variable这些API在2.x里要么被移除,要么只在tf.compat.v1里苟延残喘。完整的迁移路径官方有工具tf_upgrade_v2,但它只能处理机械性的API替换,处理不了需要重构的逻辑——比如把静态图的占位符和feed dict改成函数调用,把变量作用域改成Keras层。

我的建议是:老项目如果还在线上跑得好好的,不要为了技术债强行迁移;等有需求变更时,借机用Keras重写一遍受影响的模块,比整体迁移稳得多。

6. 那些文档里不写、但实战必知的细节

6.1 随机种子:为什么你的结果时好时坏

深度学习模型训练天然有随机性,数据打乱、权重初始化、dropout都会引入随机因子。如果你希望实验可复现,必须在训练前固定随机源:

tf.keras.utils.set_random_seed(42)

这个调用会同时设置Python的random、NumPy和TensorFlow的随机种子。注意,它并不能保证GPU上100%完全可复现,因为某些GPU算子本身是并行的非确定性操作,但至少能让结果不再“每次跑都差一大截”。论文实验要出稳定对比数据的同学,这一步千万不能省。

6.2 OOM之后先别急着骂机器

训练大模型时显存溢出(Out of Memory)几乎人人都会遇到。我第一次在单卡上训练一个比较大的BERT模型时,报错信息刷了一屏英文,只能看到ResourceExhaustedError几个字,第一反应就是“这卡是不是假的”。后来才学到一套排查顺序:先看batch size是不是太大,再看序列长度是不是没必要那么长,然后看混合精度开了没有,最后才考虑模型并行。

混合精度是这两年最值得开的免费午餐:

from tensorflow import keras keras.mixed_precision.set_global_policy("mixed_float16")

打开这行之后,很多模型在训练速度上能提升百分之三四十,显存占用也能降下来。代价是数值稳定性需要观察一下loss曲线,如果出现NaN,再回退到fp32就好。

6.3 模型保存别用“一套流程吃天下”

保存模型时经常有人随手用model.save("final_model.h5"),然后过两天要部署时傻眼了。这里给个清晰的区分:

  • 如果只是想在训练过程中保存checkpoint以便恢复训练,用ModelCheckpoint回调保存.keras或者weights.h5都行;
  • 如果模型要拿去上线提供推理服务,导出SavedModel,也就是model.export()的产物;
  • 如果只是想分享给别人接着做研究,给.keras文件是最省心的。

另外,自定义层里如果写了自定义逻辑,加载时要么把类定义放在模块里能被import到,要么传custom_objects,否则会报反序列化错误。这种坑一般会卡住你一小时以上,提前知道能省很多时间。

7. 我的最终建议:先跑通,再站队

这篇文章从头到尾聊了TensorFlow的生态位置、安装环境、核心API、实战案例、和PyTorch的趋势对比,最后又给了几个实战中省命的细节。如果要我用一句话收束,那就是:框架是工具,不是信仰。

我个人在实际操作中的体会是,如果一个新人只学一个框架,我会建议他先装好TensorFlow,跑通本文第四节那个图像分类的小闭环,感受一下“数据进模型出结果再导出服务”的完整链路。这一步一旦跑通,你对深度学习工程化的理解会扎实很多。之后再去做研究向的探索,用PyTorch自然也不会有太大障碍——因为你真正学会的是建模和排查思路,而不是背某个框架的API。

最后分享一个小技巧:装好TensorFlow之后,直接在测试集上跑一次model.predict,把输出的shape打印出来,再和y_test的shape做对比,亲手看一次预测张量的样子。这个动作看起来不起眼,但它能让你以后遇到任何输入输出维度对不上的报错时,第一时间想到“去打印shape”,而不是上搜索引擎瞎猜。深度学习这座山看起来高,但只要有条好走的路,爬上去只是时间问题。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询