1. 六年TensorFlow使用史:这个框架到底经历了什么
我从2018年开始接触TensorFlow,当时还是1.x时代,写个简单的线性回归要理解Graph、Session、placeholder,一个模型跑起来要折腾半天。那会儿的TensorFlow就像一台手动挡的老爷车,动力猛但操作繁琐,初学者十有八九在搭环境阶段就放弃了。后来2.x发布,Keras合入主流程,Eager Execution成为默认模式,整个使用体验才算回到正常人能理解的范畴。
之所以2024年还想认真聊聊TensorFlow,是因为这个框架正处在一个微妙的节点:一方面,PyTorch在论文复现和学术圈子里几乎成了默认选择,各种顶会代码十篇里有八篇是PyTorch写的;另一方面,TensorFlow在企业生产环境、移动端部署、大规模分布式训练这些"硬骨头"场景里依然有不可替代的位置。我在过去几年里用TensorFlow做过推荐系统、图像分类、文本分类、语音特征提取,也帮团队做过好多次从PyTorch模型转到TensorFlow Serving的部署改造,对它的优势和别扭之处都有切身体会。
这篇文章不是教程文档的搬运,而是我想把这几年实际使用TensorFlow积累下来的经验、踩过的坑、工序层面的选择逻辑一次性说清楚。从环境安装的版本匹配,到核心工作流的完整链路,再到2024年TensorFlow和PyTorch的选型决策,最后是我在生产环境里遇到的那些"文档不告诉你"的细节。无论你是刚开始接触TensorFlow的新手,还是已经在用但偶尔被版本问题折磨的开发者,应该都能在这里找到点东西。
需要先说明一点:我接下来讲的安装步骤和框架用法,都是我基于自己实践过的稳定方案整理出来的,不同操作系统、不同硬件环境下细节会略有差异,但核心逻辑是通用的。
2. 环境搭建全流程:从裸机到GPU训练跑通
2.1 版本匹配:Cuda、cuDNN、TensorFlow三者之间的"三角关系"
安装TensorFlow最让人头疼的不是框架本身,而是它和底层硬件驱动之间的版本匹配。TensorFlow通过CUDA调用NVIDIA显卡做并行计算,CUDA版本、cuDNN版本、TensorFlow版本这三者必须严格对应,差一个小版本都可能让你在训练时碰到莫名其妙的CUDA_ERROR_NO_DEVICE或者cudnn_status_internal_error。
我踩过最狠一次的坑是:系统里装了CUDA 12.1,TensorFlow换到2.15版本,结果加载GPU时直接报错。查了半天才发现TensorFlow 2.15官方支持的是CUDA 11.8,而CUDA 12.1需要TensorFlow 2.16以上版本才支持。这个对应关系官方文档里有详细列表,但我猜大多数人下载的时候并不会仔细看,我也是被折磨了一个下午才学乖。
这里给出一张我整理的对应表,覆盖目前主流的稳定组合:
| TensorFlow版本 | Python版本 | CUDA版本 | cuDNN版本 | 适合场景 |
|---|---|---|---|---|
| 2.10 | 3.7~3.10 | 11.2 | 8.1 | 老项目、稳定优先 |
| 2.13 | 3.8~3.11 | 11.8 | 8.6 | 性价比高、兼容性好 |
| 2.15 | 3.9~3.12 | 11.8 | 8.6 | 当前最常见的企业选择 |
| 2.16+ | 3.9~3.12 | 12.3 | 8.9 | 需要最新特性的新项目 |
一个非常实用的技巧:如果你不确定该装哪个版本,直接用Anaconda创建一个干净的Python环境,然后跑pip install tensorflow(不加版本号),pip会自动拉取与当前Python版本兼容的最新版TensorFlow。然后我去NVIDIA官网查这个TensorFlow版本对应需要哪个CUDA,再安装指定版本的CUDA Toolkit和cuDNN。顺序必须是这样:先定TensorFlow版本,再倒推CUDA版本,而不是反过来先装最新的CUDA。
2.2 CPU版安装:三十秒跑起来的最小方案
如果你的机器没有NVIDIA显卡,或者只是想做点小实验、跑通流程,CPU版TensorFlow完全够用。安装命令很简单:
# 创建虚拟环境,避免污染系统Python conda create -n tf python=3.10 conda activate tf # 安装CPU版TensorFlow pip install tensorflow-cpu注意要用tensorflow-cpu这个包而不是tensorflow,后者会连CUDA相关依赖一起装,体积大很多。CPU版安装结束以后,用一行代码验证是否成功:
import tensorflow as tf print(tf.__version__) print(tf.config.list_physical_devices())如果输出TensorFlow版本号和CPU设备列表,说明安装成功。CPU版训练速度确实慢,但用来学习API、理解框架机制、调试代码逻辑,完全够用。我建议新手一开始就用CPU版跑小模型,等真正要训练大模型的时候再上GPU,省去环境配置的初期打击。
2.3 GPU版安装:这是多数人卡得最久的一步
GPU版安装成功的标志不是pip能装上,而是TensorFlow能真正识别到GPU。我见过太多人装了GPU版,训练时却仍然默默用CPU跑,速度慢得让人怀疑人生。
安装步骤四步走:
第一步,检查显卡驱动。在终端执行:
nvidia-smi这个命令会显示显卡型号和驱动版本,同时会在右上角显示该驱动支持的最高CUDA版本。注意,nvidia-smi显示的CUDA版本是驱动的兼容上限,不代表你必须装这个版本的CUDA Toolkit。
第二步,安装CUDA Toolkit和cuDNN。推荐直接用conda安装,避免手动配置系统环境变量的麻烦:
conda install -c conda-forge cudatoolkit=11.8 conda install -c conda-forge cudnn=8.6第三步,安装TensorFlow GPU版:
pip install tensorflow==2.15这里有个要点:从TensorFlow 2.11开始,GPU版的安装包不再区分tensorflow-gpu和tensorflow,直接装tensorflow就能包含GPU支持。老教程里让你装tensorflow-gpu的写法,对2.11以上版本已经失效了。
第四步,也是最容易被忽略的一步:验证GPU是否真的被识别。在Python里执行:
import tensorflow as tf gpus = tf.config.list_physical_devices('GPU') print(gpus)如果输出[PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')],恭喜,GPU支持打通了。如果输出的列表是空的,常见原因有三个:CUDA版本不匹配、cuDNN没有装到对应位置、TensorFlow版本和CUDA版本对应不上。排查顺序也是按这个来,效率最高。
还有个细节想提醒:如果你用Anaconda,尽量不要把CUDA Toolkit装到base环境,而是装到项目对应的虚拟环境里。这样不同项目可以切换不同CUDA版本,互不干扰。
3. 核心工作流:从数据管道到模型部署一次说清
3.1 tf.data:这个框架最被低估的模块
很多时候大家学TensorFlow只盯着模型结构,却忽略了数据管道的设计。在我看来,tf.data是TensorFlow生态里最被低估的模块之一,它在处理大数据集时的优雅程度,直到现在我仍然觉得比PyTorch的DataLoader要顺滑。
tf.data的核心逻辑是构建一个数据管道,你可以把看成一整条流水线:数据从源头读出来,经过预处理、打乱、分批,然后直接喂给模型。用代码说话:
import tensorflow as tf def preprocess(feature, label): # 假装这里做了图像增强、归一化等操作 feature = tf.cast(feature, tf.float32) / 255.0 return feature, label # 从文件列表创建数据集 dataset = tf.data.Dataset.from_tensor_slices((features, labels)) dataset = dataset.map(preprocess, num_parallel_calls=tf.data.AUTOTUNE) dataset = dataset.shuffle(buffer_size=10000) dataset = dataset.batch(32) dataset = dataset.prefetch(tf.data.AUTOTUNE)这里面的prefetch是性能关键,它让CPU在GPU计算的同时提前准备下一批数据,把数据加载和模型训练重叠起来。我见过不少新手忽略这一行,结果GPU利用率一直上不去,训练时显卡风扇都不转,问题往往就出在这。
另一个经验是:能不用生成器就不要用生成器。from_generator虽然用起来方便,但性能比from_tensor_slices和TFRecord差一到两个量级。如果数据集大到内存放不下的程度,优先考虑把数据转成TFRecord格式,再用tf.data.TFRecordDataset读取。TFRecord是TensorFlow原生的二进制格式,读取速度快、可压缩,还能天然支持分布式训练的切分逻辑。
我做个类比:数据管道就像餐厅的后厨流程——菜(数据)从仓库(磁盘)拿出来,洗好切好(预处理),按顺序配菜(shuffle),装盘(batch),然后提前把下一桌菜备好(prefetch)。哪一环断了,出菜速度就受影响,放到训练里就是GPU空转。
3.2 Keras API:从快速实验到模型构建的默认选择
TensorFlow 2.x把Keras列为默认高层API,这意味着大多数常规模型用Sequential和Functional两套接口就够了。两者区别不用记太多:
Sequential适合线性堆叠的网络结构,一层接一层,写起来最直观。Functional适合有分支、有多输入、有跳连的结构,灵活度更高。
我常用的写法是Functional,因为实际项目里很少遇到纯粹的线性结构。举个例子,一个同时处理文本和数值特征的模型:
import tensorflow as tf from tensorflow import keras from tensorflow.keras import layers # 输入层 text_input = keras.Input(shape=(128,), name='text_input') num_input = keras.Input(shape=(10,), name='num_input') # 文本分支 x = layers.Embedding(10000, 64)(text_input) x = layers.LSTM(32)(x) # 数值分支 y = layers.Dense(16, activation='relu')(num_input) # 合并 combined = layers.concatenate([x, y]) output = layers.Dense(1, activation='sigmoid')(combined) model = keras.Model(inputs=[text_input, num_input], outputs=output) model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])这种多输入结构在真实项目里出镜率极高。Keras的好处是抽象层做得干净,你不需要手动管理权重初始化和梯度传播的细节,可以在十分钟内搭出一个能跑的原型。
不过Keras也有个老问题:高度封装的API让很多使用者对底层机制完全无感。一旦遇到模型输出NaN、梯度爆炸这类问题,如果不懂GradientTape的工作方式,排查起来就比较吃力。所以我的建议是:用Keras入门没问题,但一定要抽时间弄懂下面要说的自定义训练循环。
3.3 自定义训练循环:当你需要掌控每一步
Keras的model.fit()虽然方便,但在某些场景里不够用——比如你需要在训练过程中动态调整loss权重、需要自定义梯度裁剪、需要跑GAN这类对抗训练,这时候就得自己写训练循环。很多人以为自定义训练很难,其实只要理解了GradientTape,一切就通了。
GradientTape可以把前向传播过程的所有计算全部记录下来,然后自动计算梯度。这一句解释可能比较抽象,我换个说法:GradientTape就像一个监控摄像头,把网络每一层的计算过程都录了像,反向传播时只需要回放录像就能知道每个参数应该怎么调整。
一个完整的自定义训练循环大概长这样:
import tensorflow as tf optimizer = tf.keras.optimizers.Adam(learning_rate=1e-3) loss_fn = tf.keras.losses.MeanSquaredError() train_loss = tf.keras.metrics.Mean(name='train_loss') train_acc = tf.keras.metrics.CategoricalAccuracy(name='train_acc') @tf.function def train_step(x, y): with tf.GradientTape() as tape: predictions = model(x, training=True) loss = loss_fn(y, predictions) gradients = tape.gradient(loss, model.trainable_variables) optimizer.apply_gradients(zip(gradients, model.trainable_variables)) train_loss(loss) train_acc(y, predictions) for epoch in range(100): for x_batch, y_batch in train_dataset: train_step(x_batch, y_batch)注意我给train_step加了@tf.function装饰器,它会把Python函数编译成TensorFlow计算图,从而大幅提升执行速度。这是TensorFlow静态图机制的现代形态:平时像动态图一样写代码,关键时刻用装饰器"冻结"性能。
实际使用中,我一般遵循这个原则:先不用@tf.function把逻辑跑通,再逐步加上装饰器,并用model.summary()和tf.profiler确认性能瓶颈。一上来就加装饰器,遇到报错很难定位。
3.4 模型导出与部署:TensorFlow的看家本事
如果说PyTorch在训练阶段占优,那TensorFlow的护城河一定在部署环节。SavedModel是TensorFlow统一的模型格式,一次导出,到处运行——不管是Python服务、TensorFlow Serving、移动端还是嵌入式设备,都能跑同一个模型。
训练完的模型导出代码只有几行:
model.save('my_model_savedmodel', save_format='tf')导出后,目录里会有saved_model.pb文件和variables文件夹。这个格式可以被打包成TensorFlow Serving的服务,也可以用tensorflow.js跑在浏览器里,还可以用tflite转换工具压缩后跑在手机上。
我做过一个实际项目:训练好的推荐模型导出为SavedModel以后,用TensorFlow Serving部署成gRPC接口,配合Docker放到Linux服务器上,整个服务占用不到200MB内存,单机QPS能做到3000以上。这个部署链路成熟度相当高,说白了就是"训练环境多乱都能部署,模型格式是唯一标准"。
值得一提的是,TensorFlow同时提供了TF-TRT(TensorRT集成)和XLA两种加速手段,前者利用NVIDIA的推理加速引擎,后者做算子融合优化。生产环境里跑推理,这两个插件的加速效果非常可观,有时能把单次推理时间从8毫秒压到3毫秒,如果你做的是高并发在线服务,这个差距就是质变。
4. TensorFlow与PyTorch的2024对决:流行趋势与选型逻辑
4.1 学术界和工业界的明显分化
2024年聊深度学习框架,绕不开TensorFlow和PyTorch的对比。先说结论:学术论文代码基本被PyTorch垄断,企业生产线上TensorFlow依然占据相当大的比例。为什么会这样?
PyTorch的走红很大程度源于它的"Python原生感"。它的张量操作和NumPy风格高度一致,动态图机制让调试像写普通Python一样直接,没有编译、没有session、没有计算图预定义的概念。研究人员需要频繁改动模型结构做实验,PyTorch这种"改完立刻跑"的体验非常契合。
TensorFlow则走了另一条路:2.x之后虽然默认了Eager模式,但它的设计重心在生产工程化——分布式训练、模型版本管理、在线推理性能、跨平台部署。这些恰恰是学术研究里不太需要、但工业落地绕不开的环节。学术界要的是"快",工业界要的是"稳",两个框架分别踩中了两边的需求点。
4.2 各大主流模型的适配现状
我做了一个粗略统计,2024年主流的预训练模型和开源项目里,PyTorch占比在七成以上,尤其是HuggingFace生态,几乎完全建立在PyTorch之上。如果你要跑BERT、GPT系列的微调,社区开源代码绝大多数直接给你PyTorch版本,转成TensorFlow还得自己处理权重转换和算子兼容问题,浪费不少精力。
但反过来,如果看企业级AI平台的底层架构,很多推荐系统、广告系统、搜索排序模型仍然跑在TensorFlow生态里。原因有两个:
一是在线推理的成熟度。TensorFlow Serving很早就解决了模型热加载、版本路由、批处理优化这些工程问题,而PyTorch的TorchServe虽然也在进步,但目前在大规模和稳定性方面还有差距。
二是历史包袱。很多企业在2018到2020年间就已经用TensorFlow建好了完整的训练和部署基础设施,模型、数据管道、监控体系全都绑定在上面。迁移到PyTorch意味着重写训练代码、重做部署链路,这个成本不是性能上的一点点优势能抵消的。
我听过一个很形象的比喻:TensorFlow是"造车工厂",模型训练只是其中一道工序,工件怎么流转、怎么质检、怎么组装都有完整体系;PyTorch是"手工作坊",单件生产灵活精巧,但批量交付就得自己想办法。这个比喻虽然粗糙,但基本反映了两个框架的气质差异。
4.3 具体场景下我的选型建议
说实话,发展到今天,两个框架的底层能力已经没有本质差异了,选哪个更多取决于你所在的"环境生态"。我按照实际场景给出参考:
如果你主要做学术研究、论文复现、比赛调参,无脑选PyTorch。不是因为TensorFlow做不了,而是因为你的同行和参考代码全在PyTorch生态里,跟大部队走效率最高。
如果你做的是企业在线推理服务、大规模分布式训练、移动端/嵌入式部署,TensorFlow依然是稳妥之选。SavedModel格式、TFLite转换器、TF Serving的成熟度,目前仍然是行业里最完整的。
如果你做的是通用产品原型验证,那就无所谓,哪个顺手用哪个。我从2022年之后的新项目开始,基本都是PyTorch做训练、ONNX导出中间格式、再转成TensorFlow部署链路,两边优势都占。这个流程确实折腾,但对工程化和灵活性要求都高的项目,值得这个成本。
补充一点:不要因为网上讨论热度高低来决定选型。热度的背后是研究者的偏好,不是工程需求的全部。2024年TensorFlow的社区活跃度和生态健康度没有问题,只是它在"被讨论的声音"上被PyTorch压过了,这并不等于它的生产价值下降了。
5. 生产环境踩坑实录:那些文档不会告诉你的细节
5.1 分布式的坑:参数服务器策略的选用
把训练从单机搬到多机时,TensorFlow的分布式策略有好几种:MirroredStrategy、MultiWorkerMirroredStrategy、ParameterServerStrategy和TPUStrategy。很多人一上来就上最复杂的ParameterServer,其实大多数场景都用不上。
我的经验是:单机多卡用MirroredStrategy,多机多卡数据并行用MultiWorkerMirroredStrategy,只有模型大到单卡显存放不下、需要把不同层分布到不同机器的时候,才需要考虑ParameterServerStrategy。
分布式训练最大的坑不是性能而是调试。当训练进程分散在多台机器上,错误信息往往只显示在某一个worker的日志里,另一个worker可能直接hang住不动。我处理这种问题的方法很简单:先在单机多卡上跑通,再加分布式,最后上线前用少量数据做一次完整演练。
还有一个特别容易被忽略的点:使用分布式策略时,batch大小的设置需要乘以worker数量。比如单卡用32的batch,8卡并行就应该设置为256,这样等效batch保持一致,学习率也要相应调整——按照new_lr = old_lr * sqrt(num_gpus)这样放大。这个规则不遵守,模型虽然能训练,但收敛效果和单卡跑出来会对不上。
5.2 模型训练时的显存管理的N种姿势
显存溢出(OOM)是训练过程中最令人抓狂的问题之一。最聪明的地方在于:同样的模型、同样的batch,有时候能跑,有时候就OOM,因为显存占用是个动态过程。
我总结了几条有效的排查路径:
第一条,检查是不是tf.GradientTape在保留不必要的中间变量。自定义训练循环里,默认情况下GradientTape会记录前向传播的所有中间张量,用于反向传播计算梯度。如果网络很深或者输入分辨率很高,这些中间变量会占掉大量显存。可以在不需要梯度的代码段外用tf.stop_gradient()把某些分支剥离开来。
第二条,调小batch是最省事的应急方案。不用追求一次跑完所有数据,小batch多走几步对训练效果影响不大,反而可能因为梯度更稳定而收敛更好。
第三条,如果你用的是tf.keras的fit,可以显式指定steps_per_epoch,配合tf.data管道的batch把小数据集循环多次,避免数据不足导致的OOM误判。
还有一个容易被忽略的:TensorFlow默认会占据几乎全部GPU显存。这在本地调试时很烦,因为开两个实验就互相挤爆。可以通过设置显存按需增长来解决:
gpus = tf.config.list_physical_devices('GPU') if gpus: try: for gpu in gpus: tf.config.experimental.set_memory_growth(gpu, True) except RuntimeError as e: print(e)这段代码放到程序入口处,TensorFlow就会变成"用多少显存占多少",而不是一开始就全部占满。代价是频繁申请显存会有一点性能损失,但在本地开发时这点损失换来的便利很值。
5.3 静态图与动态图的思维方式差异
虽然TensorFlow 2.x默认是动态图模式(Eager Execution),但你的程序里一旦用了@tf.function装饰器,代码就会被编译成静态图执行。这个转变带来的思维差异,是很多从PyTorch转过来的人不适应的地方。
静态图环境下,Python的if语句、for循环不一定会按你熟悉的方式执行。TensorFlow会把循环展开成tf.while_loop,条件是张量时只能在运行时判断,这就导致你在写代码时不能依赖Python层的逻辑分支来做流程控制。
我自己遇到过一个很经典的坑:在@tf.function里用Python的print调试,结果发现打印只执行了一次,因为静态图编译器把print优化掉了。想要在静态图里打印张量的值,必须用tf.print。这个细节说大不大,但如果你不知道,排查起来会浪费不少时间。
所以我的建议是:如果代码逻辑里有大量基于Python条件的动态分支,比如形状判断、动态维度操作,那就坚持用Eager模式,不要加@tf.function;如果代码主要是固定形状的矩阵运算,加装饰器提速明显,但要严格遵循TensorFlow的静态图规范来写。
这里给个参考判断标准:单卡训练时,@tf.function对速度的提升一般在20%到40%之间;多卡分布式训练时,静态图几乎是必须的,否则通信和同步的开销会大到训练速度反而下降。
5.4 版本升级的兼容性:为什么我建议固定版本
TensorFlow的版本升级在2024年这个时间点依然不能大意。从2.13升到2.15,API层面的变化不算翻天覆地,但底层算子的实现和Keras的默认行为会有细微差异,充分测试前不要在生产环境直接升级。
我见过一个真实的翻车案例:同事把TensorFlow从2.10升级到2.13,所有模型结构代码不用改,训练也能正常跑,但线上推理请求的平均延迟从18毫秒涨到30毫秒。追查后发现是2.13默认启用了新版op的融合策略,和某个自定义算子构建的模式不匹配,被迫回滚到2.10才算恢复。
基于这些经验,我给自己定了几个原则,分享出来供参考:
- 生产环境的TensorFlow版本锁定,不要追新,除非有明确需要的新特性。
- 升级之前,先把训练脚本、推理脚本、模型导出脚本全部跑一遍回归测试。
- 关注TensorFlow官方的release notes和breaking changes,不要只看博客教程的推荐。
- 用
pip freeze > requirements.txt固定依赖版本,确保每次重建环境结果一致。
6. 给新手的落地路线图:从零到一的学习建议
如果你是一个完全没接触过TensorFlow的新手,长时间泡在文档里不是最有效率的方式。结合我自己带新人走过的路径,我更推荐"项目驱动、边做边学"的方式。这里给一条我认为比较顺畅的学习路线。
第一阶段,装好环境后,跑通一个图像分类的入门项目。不要用现成的数据集,自己拍一组照片或者从网上下载小规模公开数据,用Keras的Sequential搭一个简单的CNN,训练出来、保存模型、加载测试。这个过程会让你把环境配置、数据加载、模型构建、训练、评估、保存这一整条链摸一遍。
第二阶段,把项目升级为多输入特征的实际场景。比如做一个结合文本和数值数据的分类模型,理解Functional API的价值,同时尝试写自定义训练循环并用@tf.function加速。这一阶段的重点不是追求准确率,而是理解框架的运行机制和调试方式。
第三阶段,把训练好的模型用SavedModel导出,部署到本地TensorFlow Serving,写一个Python客户端调用。这个过程会把"训练"和"部署"打通,让你看到TensorFlow在生产场景里是怎么运作的。
每次遇到问题时,先用最关键的最小复现来定位:是版本问题还是代码问题?是数据管道问题还是模型结构问题?把问题缩小到最小可复现范围,解决效率会高非常多。
我在实际带人的过程中发现,新人最容易卡住的点往往不是模型结构,而是在环境配置和数据管道上。尤其是Windows用户,安装GPU版TensorFlow时经常因为CUDA路径配置不对而失败。如果你用的是Windows,建议优先用WSL2装Linux环境,或者直接用Docker镜像,我这些年没少在Windows原生环境里被折腾,后来切换到WSL2以后才彻底告别环境问题。
还有一个容易被忽略的细节:TensorFlow官方提供的Docker镜像其实是新手友好的起点,tensorflow/tensorflow:latest-gpu这个镜像已经把CUDA和cuDNN都配好了,你只需要安装NVIDIA Container Toolkit让Docker能访问GPU就行。用Docker能省掉的环境坑,恐怕能装一箩筐。
选择学习资料时也要注意时效性。TensorFlow的很多老教程还是1.x的写法,代码跑在当前版本上全是报错。我的判断标准是:看教程里有没有出现tf.compat.v1或Session这样的字眼,有的话直接跳过,那是上个时代的遗产。
TensorFlow这套东西,说到底是个偏工程的框架,它比PyTorch多了些约束,也多了些成熟。从2018年到现在,我看着它从繁杂走向收敛,从被迫手动管理一切到一步步贴近Python生态的人性化体验。那些曾经让人崩溃的Session和Graph已经被扫进历史,2.x之后的TensorFlow,尤其是在部署和生产场景里的表现,我觉得依然值得认真对待。
如果你正要开始一个实际项目,先别急着跟风选框架,问自己三个问题:模型要跑在哪里?团队现有的工程基础是什么?需要多快的迭代速度?把自己的实际需求摸清楚,选型答案自然就有了。TensorFlow不是万能的,但在需要它的地方,它依然是那个最可靠的选择。