ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

TensorFlow 2.x实战指南:从安装到部署的完整路径解析

TensorFlow 2.x实战指南:从安装到部署的完整路径解析 如果你问一个搞机器学习的人2024年哪个深度学习框架最值得学我大概率还会回答TensorFlow。这个答案可能出乎意料毕竟身边越来越多的研究员和算法工程师转投了PyTorchHugging Face上的模型也几乎默认给PyTorch版本。但TensorFlow并没有消失它只是换了一种方式存在Keras变成了官方推荐的前端TensorFlow Serving统治着不少公司的线上推理环节TF Lite依然是移动端部署的老牌选手。这篇内容就围绕TensorFlow本身从安装到上手从核心概念到工程落地再聊聊我对2024年TensorFlow与PyTorch之争的真实观察希望能给你一个相对完整的判断框架。1. 重新认识TensorFlow它到底是什么能解决什么问题1.1 从一个常见场景说起想象这样一个场景你是一家电商公司的算法工程师手里有用户过去一年的购买记录、浏览记录和商品信息老板希望你做一个猜你喜欢的推荐模型。你脑子里马上会浮现几个问题数据怎么处理模型怎么训练训练完怎么部署到线上如果每秒有几千个请求模型推理速度能不能扛住这个场景几乎是TensorFlow最典型的用武之地。TensorFlow不是一个单纯的算法库它更像一整套深度学习的工业流水线数据预处理有tf.data模型搭建有Keras训练过程有内置的Callback机制训练完可以保存成SavedModel格式然后用TensorFlow Serving对外提供高性能的RPC或HTTP推理服务。你不需要东拼西凑一堆乱七八糟的工具链一个框架就能从数据管道一路管到生产上线。很多刚接触TensorFlow的人容易把它理解成一个研究工具这其实是被早期版本误导了。早期TensorFlow 1.x的计算图是静态的写完图再跑会话调试麻烦上手门槛高感觉就像在用C写业务逻辑处处都是约束。但TensorFlow 2.x直接把Keras并入了核心变成默认API还提供了动态图机制Eager Execution用起来和写普通Python脚本无异。现在的TensorFlow本质上是一个既能做研究探索又能做生产部署的完整平台。1.2 TensorFlow的核心组件和设计思路TensorFlow最底层的概念是张量Tensor你可以把它简单理解成多维数组。标量是0维张量向量是1维张量矩阵是2维张量再往上就是3维、4维的批量数据。整个框架做的事情就是定义张量之间的运算关系然后通过自动微分计算梯度来更新模型参数。从设计思路上看TensorFlow 2.x遵循了一个很聪明的分工用Keras构建网络用tf.function控制性能用SavedModel统一导出。Keras负责让人写起来舒服tf.function负责让机器跑得快。tf.function做的事情是把Python函数编译成一个计算图图的执行效率比逐行执行Python代码高很多尤其是在GPU上训练大规模模型时这种编译优化带来的加速相当可观。很多人在学习TensorFlow时会困惑为什么既要懂Keras这种高层API又要理解底层机制因为层与层之间的性能差异、内存分配、数据拷贝往往藏在底层细节里。比如你用tf.data做数据管道如果配置了num_parallel_calls参数可以让多个数据预处理任务并行执行如果你用dataset.prefetch(1)就可以让CPU准备数据的同时GPU在跑上一个batch的训练。这些优化在Keras高层是看不见的但决定了你的训练速度能快多少倍。1.3 到底适合谁学、谁来用如果你是个学生刚入门深度学习TensorFlow Keras其实比直接上PyTorch更友好。Keras的API设计非常规整像搭积木一样——一行代码加一个卷积层一行代码加一个Dropout模型结构一目了然。如果你已经是工业界的工程师手里的任务需要走完整的线上部署流程TensorFlow的生态优势会非常明显。数据流图、SavedModel、TensorFlow Serving、TF Lite、TF.js这条链路几乎是现成的。反过来如果你主要做学术研究经常要复现顶会论文那些代码大多是PyTorch写的这时候TensorFlow可能不是最好的选择。这不是说TensorFlow做不了研究而是研究社区的资源更多集中在PyTorch。所以TensorFlow到底适合谁这个问题答案是适合要做产品、要上线、要持续维护系统的人不适合只看论文代码跑实验的人。2. 环境安装从零到跑通第一个模型的完整实操2.1 安装前的关键决策CPU版还是GPU版TensorFlow安装的第一步不是敲pip命令而是想清楚你要不要用GPU。如果你只是学习API、写写小型实验CPU版本完全够用。MNIST分类这种任务CPU上训练也就几分钟没必要折腾GPU环境。但如果你打算训练稍微像样一点的卷积网络或Transformer最好还是装GPU版本。GPU版本安装最核心的难点是版本对齐。TensorFlow、CUDA、cuDNN三者之间存在严格的版本对应关系。比如TensorFlow 2.10.x对应CUDA 11.2TensorFlow 2.12.x对应CUDA 11.8和cuDNN 8.6。你要是用pip直接把tensorflow装上它并不会帮你检查CUDA是不是匹配装完后运行时大概率会报Could not load dynamic library libcudnn.so.8这种错误。我建议的最稳妥做法先确认显卡驱动版本然后根据驱动支持的CUDA版本来选择TensorFlow版本。如果你不想折磨自己直接用NVIDIA官方容器镜像比如nvcr.io/nvidia/tensorflow里面所有依赖都配好了但那是Docker方案对新手不太友好。本地环境安装的话最好用Anaconda或Miniconda创建独立虚拟环境让conda帮你管理CUDA和cuDNN这样能省掉不少折腾。2.2 基于虚拟环境的安装步骤下面这套步骤是我实测过很多次、基本能一次跑通的流程。假设你用的是Linux系统显卡驱动已经装好了。# 1. 创建虚拟环境指定Python版本 # TensorFlow 2.x 通常支持 Python 3.8~3.11我这里用3.10 conda create -n tf2 python3.10 conda activate tf2 # 2. 安装cudatoolkit和cudnn # conda会自动帮我们匹配版本关系 conda install -c conda-forge cudatoolkit11.8 cudnn8.6 # 3. 安装TensorFlow # 这里用2.12版本带上gpu后缀 pip install tensorflow[and-cuda]2.12注意第3步tensorflow包的GPU版从2.11开始其实已经合并了统一叫tensorflow但2.12仍然提供了tensorflow[and-cuda]这个额外选项用来装配套的CUDA运行库。如果你直接在conda里装了cudatoolkit再安装正式版tensorflow也可以但建议先加上一行# 验证是否装到了conda的lib目录 conda list cudatoolkit如果你不想用conda也可以直接用pip装。但纯pip方案很容易踩坑因为pip不会管CUDA和cuDNN。一个偏方是安装官方推荐的包pip install tensorflow[and-cuda]这个命令会自动安装配套的NVIDIA库前提是你的显卡驱动足够新。我第一次用这个方法时还半信半疑后来在几台不同配置的机器上试过包括RTX 3090和A6000都成功了省了不少事。2.3 验证安装是否成功的三个层级装完之后不要急着跑模型先做三级验证从简单到复杂能帮你快速定位问题。第一级验证包是否导入成功import tensorflow as tf print(tf.__version__)这一步如果报错通常是Python版本不兼容或者TensorFlow包本身损坏。我遇到过最典型的错误是ImportError: libcublas.so.11: cannot open shared object file这多发生在pip安装但CUDA动态库路径没设置的情况下。解决办法是在终端执行export LD_LIBRARY_PATH/usr/local/cuda/lib64:${LD_LIBRARY_PATH}如果是conda环境就确认cudatoolkit是否真的装进去了。第二级验证GPU是否被识别print(tf.config.list_physical_devices(GPU))如果返回一个空的列表说明TensorFlow没找到GPU。这时候先跑一下nvidia-smi看驱动是否正常。如果驱动正常但仍找不到GPU多半是TensorFlow的CUDA运行时和驱动支持的CUDA版本不匹配。可以用tf.test.is_gpu_available()再看一眼但这个API在新版本里被标注了deprecated还是以list_physical_devices为准。第三级跑一个真实的矩阵乘法并确认计算发生在GPU上with tf.device(/GPU:0): a tf.random.normal([1000, 1000]) b tf.random.normal([1000, 1000]) c tf.matmul(a, b) print(c.device)如果看到/job:localhost/replica:0/task:0/device:GPU:0之类的输出就说明GPU计算链路是通的。有一个很容易忽略的点TensorFlow默认会优先占用GPU的全部显存如果你的机器上还需要跑其他程序一定要设定显存增长策略gpus tf.config.experimental.list_physical_devices(GPU) if gpus: try: tf.config.experimental.set_memory_growth(gpus[0], True) except RuntimeError as e: print(e)不然你会遇到CUDA_ERROR_OUT_OF_MEMORY这种报错不是你的卡有问题是TensorFlow把显存全占了。3. 核心细节解析张量、自动微分与Keras的高层封装3.1 张量Tensor到底是什么新手刚接触TensorFlow经常会卡在张量这个概念上原因在于很多教材把它解释得太抽象。其实你完全可以把张量理解成带类型和形状的多维数组。它和NumPy数组最大的区别在于TensorFlow的张量被设计成可以在GPU或TPU上执行运算并且能自动跟踪计算过程以计算梯度。举个例子。你有一张灰度图片长宽都是28像素那么它在内存里就是一个28x28的二维数组也就是2维张量。如果你把一批32张图片叠在一起就变成一个形状为[32, 28, 28]的3维张量。如果图片还有RGB三个通道那就是[32, 28, 28, 3]。张量的形状shape决定了运算的合法性和参数的初始化方式。在实际代码中你经常会和shape打交道。比如x tf.ones([4, 3, 28, 28]) print(x.shape) # (4, 3, 28, 28)这里的语义是4个样本每个样本有3个通道比如RGB每个通道是28x28像素。如果你的模型输入层写成了Input(shape(28, 28, 1))而数据实际是[4, 3, 28, 28]模型不会报错但结果一定是错的因为通道维度和宽高维搞混了。这种错误非常隐蔽训练loss可能始终不下降。检查张量shape要成为肌肉记忆。3.2 自动微分与GradientTape自动微分是深度学习框架的立身之本。所有神经网络训练本质都是在做用梯度更新参数这件事。早期TensorFlow 1.x需要你先定义好计算图再通过会话执行自动微分在后台完成但流程很绕。TensorFlow 2.x提供了tf.GradientTape可以方便地对任意一段代码进行梯度计算。GradientTape的基本用法x tf.Variable(3.0) with tf.GradientTape() as tape: y x ** 2 grad tape.gradient(y, x) print(grad) # tf.Tensor(6.0, shape(), dtypefloat32)这个例子里y对x的导数在x3时是6数学上没问题。关键是GradientTape会记录它在with块内部执行过哪些张量运算然后自动进行反向传播。很多新手会问为什么要用Variable不用普通Tensor因为普通Tensor的值一旦创建就不可变模型参数必须在训练中被更新所以必须是Variable。还有一个小细节默认情况下GradientTape只调用一次gradient方法。如果你要多次计算梯度需要设置persistentTrue并且用完后手动释放资源with tf.GradientTape(persistentTrue) as tape: y x ** 2 3 * x dy_dx tape.gradient(y, x) second_order tape.gradient(dy_dx, x) del tape在训练时每轮迭代的标准动作是把tape.gradient求出的梯度传给optimizer.apply_gradients这一步就会更新模型权重。很多人会写错顺序先apply_gradients再tape.gradient那梯度就是上一次的梯度模型训练效果会非常奇怪。3.3 Keras把复杂网络变成积木Keras在TensorFlow 2.x中扮演了一个官方高层API的角色。你不用再自己写一层层的重复代码Keras已经帮你把全连接层、卷积层、循环层、注意力层都封装成了现成的类。我见过不少开发者在用TensorFlow时还死守着低阶API写几百行初始化代码这完全没有必要。最常用的模型构建方式有三种Sequential顺序模型、Functional函数式模型、Model子类化。Sequential模型适合那种一层接一层的简单结构比如全连接网络model tf.keras.Sequential([ tf.keras.layers.Dense(128, activationrelu), tf.keras.layers.Dropout(0.2), tf.keras.layers.Dense(10, activationsoftmax) ])Functional模型适合有分支、拼接、多输入输出的网络。比如一个同时接收图片和文本特征的模型可以这样定义image_input tf.keras.Input(shape(28, 28), nameimg) text_input tf.keras.Input(shape(100,), nametext) features tf.keras.layers.Concatenate()([image_input, text_input]) output tf.keras.layers.Dense(1, activationsigmoid)(features) model tf.keras.Model(inputs[image_input, text_input], outputsoutput)Model子类化最灵活相当于你完全自定义forward逻辑适合研究场景。但对大部分工程任务Keras的Functional模式是效率和可读性的最佳平衡点也是我线上最推荐的。Keras还提供了非常方便的回调机制比如ModelCheckpoint可以在训练过程中自动保存最优权重EarlyStopping可以在验证集指标不再提升时提前终止训练ReduceLROnPlateau可以在loss停在平台期时自动降低学习率。这三个回调组合起来能让你在长时间训练时几乎不用盯着屏幕。4. 实操过程用TensorFlow训练并部署一个图像分类模型4.1 准备数据从零构建数据集既然要讲实操就从一个最常见的任务——图像分类——入手。为了不依赖外部下载我直接生成一个模拟斜面图像分类的小数据集左侧亮右侧暗的图片归为类别0左侧暗右侧亮的图片归为类别1。这类数据虽然简单但足以走通全流程。首先用NumPy生成数据并转换成TensorFlow数据集import numpy as np import tensorflow as tf def generate_data(num_samples1000, size28): x np.zeros((num_samples, size, size), dtypenp.float32) y np.zeros((num_samples,), dtypenp.int64) for i in range(num_samples): # 随机生成亮暗梯度方向 if np.random.rand() 0.5: x[i] np.tile(np.linspace(0, 1, size), (size, 1)) y[i] 0 else: x[i] np.tile(np.linspace(1, 0, size), (size, 1)) y[i] 1 return x, y x_train, y_train generate_data(2000) x_test, y_test generate_data(500) # 增加通道维度 x_train x_train[..., np.newaxis] x_test x_test[..., np.newaxis]这里有个容易被忽略的点卷积层期望的输入是4维张量[batch, height, width, channel]很多新手忘了加最后的channel维度结果模型输入维度对不上。加上np.newaxis后x_train的形状就变成[2000, 28, 28, 1]了。然后进入tf.data管道train_ds tf.data.Dataset.from_tensor_slices((x_train, y_train)) train_ds train_ds.shuffle(2000).batch(32).prefetch(tf.data.AUTOTUNE) test_ds tf.data.Dataset.from_tensor_slices((x_test, y_test)).batch(32)shuffle用于打乱数据顺序batch用于把数据分成小批量prefetch(tf.data.AUTOTUNE)让数据准备和模型训练并行执行这几个方法几乎是TensorFlow数据处理的标配。如果你的数据量很大建议用map方法提前做归一化、裁剪、增强等操作尽量在进入模型前把数据处理完。4.2 搭建模型并训练我把模型设计成一个两层卷积加一层全连接的小网络。这里需要说明一下为什么这样设计图像分类任务中卷积层负责提取局部特征池化层负责降低特征图尺寸全连接层负责把特征映射到类别。对于这个亮度渐变数据用简单神经网络也能学但卷积网络更能体现TensorFlow的常用套路。model tf.keras.Sequential([ tf.keras.layers.Conv2D(16, 3, activationrelu, input_shape(28, 28, 1)), tf.keras.layers.MaxPooling2D(), tf.keras.layers.Conv2D(32, 3, activationrelu), tf.keras.layers.Flatten(), tf.keras.layers.Dense(2, activationsoftmax) ]) model.compile( optimizeradam, losssparse_categorical_crossentropy, metrics[accuracy] ) history model.fit( train_ds, validation_datatest_ds, epochs10, callbacks[ tf.keras.callbacks.EarlyStopping(patience2, restore_best_weightsTrue), tf.keras.callbacks.ModelCheckpoint(best_model.keras, save_best_onlyTrue) ] )这里我选用了sparse_categorical_crossentropy而不是categorical_crossentropy因为y标签是整数而不是one-hot向量。两者都可以做分类损失但前者省去手动转one-hot的步骤。很多新手在这个地方踩坑如果标签是整数而用了categorical_crossentropy训练时会直接报shape不匹配的错误。4.3 保存、加载与导出训练完之后模型保存有几种形式各有用处。最常用的best_model.keras已经通过回调保存了最优权重。你可以随时加载它来做预测model tf.keras.models.load_model(best_model.keras) test_batch x_test[:10] preds model.predict(test_batch) print(tf.argmax(preds, axis1))但如果你要部署到线上我建议导出成SavedModel格式。SavedModel是TensorFlow官方的通用部署格式里面包含了模型结构和权重最关键的是它附带一份SavedModel协议TensorFlow Serving可以直接读取。model.export(saved_model/my_model)我用的是export方法这是TensorFlow 2.12以后官方推荐的方式它会自动打包一份完整的服务签名。如果你用更早的版本也可以用model.save(saved_model/my_model, save_formattf)。两者区别在于export生成的签名更标准对后续的TF Serving更友好。4.4 用TF Serving做线上推理的初步体验假设你已经安装了Docker用TF Serving跑推理非常方便。先启动一个容器把刚才导出的SavedModel挂载进去docker run -p 8501:8501 \ --mount typebind,source$(pwd)/saved_model/my_model,target/models/my_model \ -e MODEL_NAMEmy_model -t tensorflow/serving启动成功后http://localhost:8501/v1/models/my_model会返回模型状态然后你就可以通过REST API发送预测请求curl -X POST http://localhost:8501/v1/models/my_model:predict \ -d {instances: [输入数组]}TF Serving的最大价值在于它自带请求批处理batching和并发处理能力。你不需要自己写多线程推理服务。只要把模型的输入输出规范好它就能自动处理高并发请求。这是很多公司选择TensorFlow的原因从训练到上线链路非常短运维成本低。5. 2024年的TensorFlow与PyTorch趋势、选型和我的真实感受5.1 流行度数据背后的故事聊到2024年的深度学习框架绕不开一个话题TensorFlow和PyTorch到底谁更流行。从学术论文、开源模型、Kaggle竞赛、各大顶会投稿来看PyTorch确实是当前绝对的主导者。很多论文的开源代码默认就是PyTorchHugging Face上的Transformers库也把PyTorch作为底层主力。趋势这个东西一旦形成会自我强化——研究者用PyTorch发表论文后来者复现论文就也用PyTorch于是论文代码生态越来越偏向PyTorch。但把镜头拉宽一点你会发现TensorFlow在工业界依然非常能打。Google自家的搜索、广告、推荐系统大量业务模型跑在TensorFlow上。很多大厂的线上推理系统尤其是那些需要长期稳定运行的模型服务仍然依赖TensorFlow Serving。PyTorch在学术界热闹但轮到大规模部署和低延迟推理尤其在Android、iOS、浏览器这种边缘设备上TensorFlow还是更有话语权。TF Lite在移动端部署的成熟度比PyTorch Mobile高不少。5.2 什么时候选TensorFlow什么时候选PyTorch作为一个工程师我的选型标准很简单看你的核心场景是研究探索还是产品落地。如果团队的任务是快速验证算法效果需要大量参考社区代码那选PyTorch。PyTorch的动态图和Python风格太自然了写起来顺手调试也直观。模型定义就是一个普通的Python类forward函数里怎么写都行随时可以print中间变量。这种灵活性在研究阶段就是生产力。但如果任务是做一个要上线的推荐系统、图像服务或者IoT端侧应用我建议优先考虑TensorFlow。理由有三点第一SavedModel格式打通了训练到部署的桥梁模型训练完直接导出不需要单独写推理引擎第二TensorFlow Serving已经是经过了大规模验证的高性能推理服务内置监控、批处理、模型热加载第三TF Lite/ TF.js在移动端和浏览器生态里没有对手你几乎找不到比它更成熟的方案。我见过太多团队用PyTorch训练完模型然后发现部署时要重新写一套C推理代码或者要自己搭一个推理服务平白多出一大堆工作量。反观TensorFlow训练时顺手导出SavedModelDocker拉一个image把模型挂上去就能跑这种顺手在工程里价值巨大。5.3 TensorFlow的未来方向Keras成为核心入口2024年TensorFlow最值得关注的一个变化是Keras被定位成所有用户的第一入口。Google在Keras 3.0做了很大的架构调整你不知道它其实是一个支持TensorFlow、JAX和PyTorch三种后端的多框架API。也就是说你现在用Keras写一套代码可以自由切换后端运行。这对用户是好事但同时也意味着TensorFlow本身的通路正在变宽。我个人觉得这个变化传递出一个明确信号框架之争不再是单纯的API之争而是生态和部署链路的竞争。TensorFlow依然做它最擅长的事——把从研究到生产的整个流程标准化。Keras作为前端让更多PyTorch用户也能无痛上手TensorFlow的部署生态。如果你问我接下来几年学什么我会说把Keras学好把TensorFlow的数据管道和部署工具链搞懂这比纠结选哪个框架更有价值。6. 常见问题与排查技巧实录6.1 安装阶段的经典报错我整理了一些在安装和跑通时最容易碰到的报错每条都是实际踩过的坑。第一类是ImportError: DLL load failedWindows或libcudnn.so: cannot open shared object fileLinux。这基本是CUDA/cuDNN路径没有暴露给运行时。Linux下可以先执行echo $LD_LIBRARY_PATH看看有没有包含cuda/lib64。如果是conda环境conda install cudatoolkit以后conda会帮你在激活环境时自动设置LD_LIBRARY_PATH但有时不生效这时就需要手动补上环境变量。第二类是Could not create cudnn handle: CUDNN_STATUS_INVALID_VALUE。这个报错常见于GPU显存不足或者是cuDNN版本和GPU架构不匹配。显存不足就设置set_memory_growth(True)版本问题就检查cuDNN的major.minor版本是否与TensorFlow要求一致。还有一个隐藏点如果你用RTX 4090之类的新卡驱动需要足够的CUDA版本老版本驱动会直接报错。第三类是NotFoundError: No algorithm worked for Convolution。这个报错经常出现在卷积神经网络训练中通常原因是GPU显存不够找不到合适的卷积算法。最简单的处理是把batch size调小或者改用CPU跑一下试试看是不是GPU算法库的问题。6.2 训练阶段的疑难杂症训练过程最常见的诡异问题不是报错而是loss不下降或者直接变成NaN。loss变成NaN大概率是学习率太大模型参数更新过猛导致数值溢出。解决办法是把初始学习率降低一个数量级比如从0.001改成0.0001。还有一个原因是数据中没有归一化像素值在0-255和0-1之间差别巨大建议先除以255。另一个常见坑是训练集loss下降正常但验证集指标完全不动甚至训练和验证准确率相差巨大。这多半是数据泄漏或数据分布不一致。比如你在生成数据时验证集和训练集各自随机生成但如果不小心让部分数据样本同时出现在两个集合里验证指标就会虚高。另一个可能是模型过拟合尤其是数据量小时Dropout和正则化这时候就派上用场了。我还遇到过一件特别诡异的事同一份代码在一台机器上训练很正常换到另一台机器上就报shape不匹配。排查了半天发现是tf.data的batch顺序在不同硬件上产生了不同的尾部批次。如果你的数据量不是32的整数倍最后一个batch会小于32有些操作比如BatchNorm会对batch大小敏感。解决办法是在batch时设置drop_remainderTrue把不完整的尾部batch丢弃。6.3 避坑建议速查表我把上面这些经验整理成一个速查表方便你在开发时直接对照现象可能原因解决方法找不到GPU设备CUDA/cuDNN版本不匹配检查nvidia-smi驱动版本确认TensorFlow对应CUDA版本GPU显存被占满默认占用全部显存设置set_memory_growth(True)动态库加载失败LD_LIBRARY_PATH未配置手动导出CUDA路径loss为NaN学习率太大或数据未归一化降低学习率除以255验证集指标异常数据泄漏或过拟合检查数据切分增加Dropout最后一个batch报错数据量不是batch_size倍数设置drop_remainderTrue模型保存报错使用了旧版save格式使用model.export()或save_formattf6.4 几个亲测有效的调试技巧除了上面的具体问题我想分享三个在工程中很通用的调试习惯。第一个习惯先用小数据跑通代码。把训练样本临时限定在几百条batch size也调小只训练一个epoch。这样可以在几十秒内发现代码里的逻辑错误、shape错误、数据类型错误。不要一上来就用大数据集训练否则你会在等待中发现错误白白浪费数小时。我现在的流程永远是小数据冒烟测试→中等数据验证训练曲线→全量数据正式训练。第二个习惯调试时打印shape和dtype。你在设计数据管道时每隔几步就print(next(iter(train_ds)))看看输出形状。很多shape不匹配的错误根源就是数据管道的输出和模型输入不一致。在TensorFlow里这类的错误提示有时候不直观与其猜不如直接打印中间张量。第三个习惯给回调函数加日志。ModelCheckpoint保存模型时用回调里的logs参数记录每一次epoch的loss和accuracy方便分析训练曲线。我一般会再加一个CSVLogger把日志写到文件里。这样就算训练意外中断你也能从日志里看出是哪一步开始异常的。写在最后的一个小提示实际使用TensorFlow这么久我最深的一点体会是不要被谁更流行困扰。框架只是工具真正决定项目成败的是你对数据、模型和系统链路的理解。TensorFlow可能在某些场景下显得笨重但它的工程成熟度确实无可替代。如果让我给一个具体的行动建议我会说把官方教程里的图像分类例子完整跑一遍然后试着把模型导出成SavedModel再用Docker拉起TensorFlow Serving预测一次。这一圈走下来你对TensorFlow的价值会有一个完全不一样的判断。之后哪怕你日常还是用PyTorch做实验遇到部署问题你依然会感谢自己花了这一小时搞懂了TensorFlow的完整链路。
返回列表