大规模训练和部署TensorFlow模型
在机器学习领域,训练出一个能做出出色预测的模型只是第一步,将模型投入生产使用才是关键。本文将详细介绍如何使用TF Serving和Vertex AI来部署TensorFlow模型,以及如何加速模型训练等内容。
1. 模型部署的重要性和挑战
当你拥有一个训练好的TensorFlow模型后,将其投入生产使用是必不可少的步骤。这可能只是简单地在一批数据上运行模型,或者编写一个脚本每晚运行该模型。但实际情况往往更为复杂,基础设施的各个部分可能需要在实时数据上使用该模型,这时就需要将模型封装在一个Web服务中,以便基础设施的任何部分都能通过简单的REST API(或其他协议)随时查询模型。
随着时间的推移,你需要定期使用新数据重新训练模型,并将更新后的版本推送到生产环境。这就需要处理模型版本控制,确保从一个模型版本平稳过渡到下一个版本,在出现问题时可能需要回滚到上一个版本,甚至可能需要并行运行多个不同的模型进行A/B测试。
此外,如果你的产品取得成功,服务可能会每秒收到大量查询(QPS),因此服务必须能够扩展以支持负载。同时,如果训练数据量大且模型计算密集,训练时间可能会过长,这会影响产品对变化的快速适应能力,也会阻碍你尝试新想法。
2. 使用TF Serving部署模型
TF Serving是一个高效且经过实战检验的模型服务器,用C++编写。它可以承受高负载,服务多个版本的模型,并监控模型仓库以自动部署最新版本。下面将详细介绍使用TF Serving部署模型的步骤。
2.1 导出SavedModels
假设你使用Keras训练了一个MNIST模型,要将其部署到TF Serving,首先需要将模型导出为SavedModel格式。以下是具体代码:
from pathlib import Path
import tensorflow as tf
X_train, X_valid, X_test = [...] # 加载并拆分MNIST数据集
model = [...] # 构建并训练MNIST模型(也处理图像预处理)
model_name = "my_mnist_model"
model_version = "0001"
model_path = Path(model_name) / model_version
model.save(model_path, save_format="tf")
通常,将所有预处理层包含在导出的最终模型中是个好主意,这样模型在部署到生产环境后可以直接处理自然形式的数据,避免在使用模型的应用程序中单独处理预处理步骤。
需要注意的是,SavedModel保存的是计算图,因此只能用于完全基于TensorFlow操作的模型,不包括
tf.py_function()
操作,因为它封装了任意Python代码。
可以使用TensorFlow自带的
saved_model_cli
命令行界面来检查导出的模型:
$ saved_model_cli show --dir my_mnist_model/0001
输出结果如下:
The given SavedModel contains the following tag-sets:
'serve'
SavedModel包含一个或多个元图(metagraph),元图是一个计算图加上一些函数签名定义,包括其输入和输出的名称、类型和形状。每个元图由一组标签标识。当使用Keras模型的
save()
方法保存模型时,它会保存一个标记为
"serve"
的单个元图。
进一步检查
"serve"
标签集:
$ saved_model_cli show --dir 0001/my_mnist_model --tag_set serve
输出结果如下:
The given SavedModel MetaGraphDef contains SignatureDefs with these keys:
SignatureDef key: "__saved_model_init_op"
SignatureDef key: "serving_default"
这个元图包含两个签名定义:一个初始化函数
"__saved_model_init_op"
,以及一个默认的服务函数
"serving_default"
。当保存Keras模型时,默认的服务函数是模型的
call()
方法,用于进行预测。
再进一步获取服务函数的详细信息:
$ saved_model_cli show --dir 0001/my_mnist_model --tag_set serve \
--signature_def serving_default
输出结果如下:
The given SavedModel SignatureDef contains the following input(s):
inputs['flatten_input'] tensor_info:
dtype: DT_UINT8
shape: (-1, 28, 28)
name: serving_default_flatten_input:0
The given SavedModel SignatureDef contains the following output(s):
outputs['dense_1'] tensor_info:
dtype: DT_FLOAT
shape: (-1, 10)
name: StatefulPartitionedCall:0
Method name is: tensorflow/serving/predict
可以看到,函数的输入名为
"flatten_input"
,输出名为
"dense_1"
,这对应于Keras模型的输入和输出层名称,同时还能看到输入和输出数据的类型和形状。
2.2 安装和启动TensorFlow Serving
有多种方法可以安装TF Serving,例如使用系统的包管理器、使用Docker镜像、从源代码安装等。由于Colab运行在Ubuntu上,可以使用Ubuntu的
apt
包管理器进行安装:
url = "https://storage.googleapis.com/tensorflow-serving-apt"
src = "stable tensorflow-model-server tensorflow-model-server-universal"
!echo 'deb {url} {src}' > /etc/apt/sources.list.d/tensorflow-serving.list
!curl '{url}/tensorflow-serving.release.pub.gpg' | apt-key add -
!apt update -q && apt-get install -y tensorflow-model-server
%pip install -q -U tensorflow-serving-api
上述代码首先将TensorFlow的包仓库添加到Ubuntu的包源列表中,然后下载TensorFlow的公共GPG密钥并添加到包管理器的密钥列表中,以便验证TensorFlow包的签名。接着使用
apt
安装
tensorflow-model-server
包,最后安装
tensorflow-serving-api
库,用于与服务器通信。
接下来启动服务器,启动命令需要基模型目录的绝对路径,将其保存到
MODEL_DIR
环境变量中:
import os
os.environ["MODEL_DIR"] = str(model_path.parent.absolute())
然后启动服务器:
%%bash --bg
tensorflow_model_server \
--port=8500 \
--rest_api_port=8501 \
--model_name=my_mnist_model \
--model_base_path="${MODEL_DIR}" >my_server.log 2>&1
在Jupyter或Colab中,
%%bash --bg
魔法命令将单元格作为bash脚本在后台运行,
>my_server.log 2>&1
将标准输出和标准错误重定向到
my_server.log
文件。
2.3 在Docker容器中运行TF Serving
如果你在自己的机器上运行笔记本并且已经安装了Docker,可以在终端中运行以下命令下载TF Serving镜像:
$ docker pull tensorflow/serving
在Docker容器中启动服务器的命令如下:
$ docker run -it --rm -v "/path/to/my_mnist_model:/models/my_mnist_model" \
-p 8500:8500 -p 8501:8501 -e MODEL_NAME=my_mnist_model tensorflow/serving
以下是各命令行选项的含义:
| 选项 | 含义 |
| ---- | ---- |
|
-it
| 使容器具有交互性(可以按
Ctrl-C
停止)并显示服务器的输出 |
|
--rm
| 停止容器时删除容器,避免机器上残留中断的容器,但不删除镜像 |
|
-v "/path/to/my_mnist_model:/models/my_mnist_model"
| 使主机的
my_mnist_model
目录在容器的
/models/mnist_model
路径下可用,需将
/path/to/my_mnist_model
替换为该目录的绝对路径,在Windows上主机路径使用
\
,容器路径使用
/
|
|
-p 8500:8500
| 使Docker引擎将主机的TCP端口8500转发到容器的TCP端口8500,TF Serving默认使用该端口提供gRPC API服务 |
|
-p 8501:8501
| 将主机的TCP端口8501转发到容器的TCP端口8501,Docker镜像默认使用该端口提供REST API服务 |
|
-e MODEL_NAME=my_mnist_model
| 设置容器的
MODEL_NAME
环境变量,让TF Serving知道要服务的模型,默认会在
/models
目录中查找模型并自动服务最新版本 |
|
tensorflow/serving
| 要运行的镜像名称 |
以下是使用TF Serving部署模型的流程图:
graph TD;
A[训练MNIST模型] --> B[导出为SavedModel];
B --> C[安装TF Serving];
C --> D[启动TF Serving];
D --> E[在Docker容器中运行TF Serving];
E --> F[查询TF Serving];
2.4 查询TF Serving
服务器启动并运行后,可以通过REST API和gRPC API查询模型。
2.4.1 通过REST API查询TF Serving
首先创建查询,查询必须包含要调用的函数签名名称和输入数据。由于请求必须使用JSON格式,需要将输入图像从NumPy数组转换为Python列表:
import json
X_new = X_test[:3] # 假设有3个新的数字图像要分类
request_json = json.dumps({
"signature_name": "serving_default",
"instances": X_new.tolist(),
})
然后使用
requests
库通过HTTP POST请求将请求发送到TF Serving:
import requests
server_url = "http://localhost:8501/v1/models/my_mnist_model:predict"
response = requests.post(server_url, data=request_json)
response.raise_for_status() # 出现错误时抛出异常
response = response.json()
如果一切顺利,响应应该是一个包含单个
"predictions"
键的字典,将对应的预测列表转换为NumPy数组并将其中的浮点数四舍五入到小数点后两位:
import numpy as np
y_proba = np.array(response["predictions"])
y_proba.round(2)
REST API简单易用,适用于输入和输出数据量不大的情况。但它基于JSON,文本格式较为冗长,在传输大型NumPy数组时会导致高延迟和高带宽使用。
2.4.2 通过gRPC API查询TF Serving
gRPC API期望输入为序列化的
PredictRequest
协议缓冲区,并输出序列化的
PredictResponse
协议缓冲区。以下是创建请求的代码:
from tensorflow_serving.apis.predict_pb2 import PredictRequest
request = PredictRequest()
request.model_spec.name = model_name
request.model_spec.signature_name = "serving_default"
input_name = model.input_names[0] # == "flatten_input"
request.inputs[input_name].CopyFrom(tf.make_tensor_proto(X_new))
然后发送请求并获取响应:
import grpc
from tensorflow_serving.apis import prediction_service_pb2_grpc
channel = grpc.insecure_channel('localhost:8500')
predict_service = prediction_service_pb2_grpc.PredictionServiceStub(channel)
response = predict_service.Predict(request, timeout=10.0)
最后将
PredictResponse
协议缓冲区转换为张量:
output_name = model.output_names[0] # == "dense_1"
outputs_proto = response.outputs[output_name]
y_proba = tf.make_ndarray(outputs_proto)
运行上述代码并打印
y_proba.round(2)
,将得到与之前相同的估计类概率。当传输大量数据或对延迟要求较高时,gRPC API是更好的选择,因为它使用紧凑的二进制格式和基于HTTP/2帧的高效通信协议。
2.5 部署新模型版本
要部署新的模型版本,只需创建一个新的模型版本并将其导出为SavedModel:
model = [...] # 构建并训练新的MNIST模型版本
model_version = "0002"
model_path = Path(model_name) / model_version
model.save(model_path, save_format="tf")
TF Serving会定期检查模型目录以查找新的模型版本。如果找到新版本,它会自动处理平稳过渡:默认情况下,它会使用上一个模型版本回答未完成的请求(如果有),同时使用新版本处理新请求。当所有未完成的请求都得到回答后,上一个模型版本将被卸载。
如果SavedModel在
assets/extra
目录中包含一些示例实例,可以配置TF Serving在开始使用新模型服务请求之前先在这些实例上运行该模型,这称为模型预热,可以确保一切正确加载,避免第一个请求的响应时间过长。
TF Serving还具有自动批处理功能,可以在启动时使用
--enable_batching
选项激活。当TF Serving在短时间内收到多个请求时,它会自动将它们批量处理,利用GPU的能力显著提高性能。
如果预计每秒会收到大量查询,可能需要在多个服务器上部署TF Serving并进行负载均衡。可以使用Kubernetes等工具简化跨多个服务器的容器编排。如果不想购买、维护和升级硬件基础设施,可以使用云平台上的虚拟机,如Amazon AWS、Microsoft Azure、Google Cloud Platform等。在后续内容中,我们将介绍如何使用Vertex AI在云端服务模型。
3. 使用Vertex AI在云端服务模型
如果不想自己管理硬件基础设施、容器编排、TF Serving配置等繁琐事务,可以选择使用云平台的服务。Vertex AI是一个不错的选择,它是目前唯一支持TPU的平台,支持TensorFlow 2、Scikit - Learn和XGBoost,并且提供了一套不错的AI服务。
以下是使用Vertex AI服务模型的大致步骤:
1.
准备模型
:将训练好的模型导出为SavedModel格式,这一步与前面使用TF Serving时的操作相同。
2.
上传模型到Vertex AI
:在Vertex AI的控制台或使用相应的API将SavedModel上传到指定的存储位置。
3.
创建端点
:在Vertex AI中创建一个端点,用于接收客户端的请求。
4.
部署模型到端点
:将上传的模型部署到创建的端点上。
5.
查询模型
:通过REST API或gRPC API向端点发送请求,获取模型的预测结果。
Vertex AI提供了图形化界面和API两种方式来完成上述操作,对于不熟悉编程的用户,图形化界面更加友好;而对于开发者来说,使用API可以实现自动化部署和管理。
4. 加速模型训练
在机器学习中,如果训练数据量大且模型计算密集,训练时间可能会非常长,这会影响产品的快速迭代和新想法的实验。以下是一些加速模型训练的方法:
4.1 使用硬件加速器
- GPU(图形处理单元) :GPU具有大量的计算核心,适合并行计算,能够显著加速深度学习模型的训练。许多深度学习框架都支持使用GPU进行计算,如TensorFlow、PyTorch等。在TensorFlow中,只需要安装相应的GPU版本,并确保系统中安装了正确的GPU驱动和CUDA库,就可以自动使用GPU进行训练。
- TPU(张量处理单元) :TPU是Google专门为深度学习设计的硬件加速器,具有更高的计算效率和更低的能耗。Vertex AI支持使用TPU进行模型训练,通过简单的配置就可以在TPU上运行模型。
4.2 分布式训练
可以在多个机器上同时训练模型,每个机器配备多个硬件加速器,以进一步加速训练过程。TensorFlow提供了简单而强大的分布式策略API,使得分布式训练变得容易。以下是一个使用
tf.distribute.MirroredStrategy
进行分布式训练的示例代码:
import tensorflow as tf
# 创建分布式策略
strategy = tf.distribute.MirroredStrategy()
# 在策略范围内构建模型
with strategy.scope():
model = tf.keras.Sequential([...])
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
# 加载数据
(X_train, y_train), (X_test, y_test) = tf.keras.datasets.mnist.load_data()
X_train = X_train / 255.0
X_test = X_test / 255.0
# 训练模型
model.fit(X_train, y_train, epochs=10, validation_data=(X_test, y_test))
tf.distribute.MirroredStrategy
会在多个GPU上复制模型,并同步更新模型的参数,从而实现并行训练。
5. 部署模型到其他平台
除了使用TF Serving和Vertex AI服务模型,还可以将模型部署到移动应用、嵌入式设备和Web应用中。
5.1 部署到移动应用
可以使用TensorFlow Lite将TensorFlow模型转换为适合移动设备的格式。TensorFlow Lite是一个轻量级的深度学习框架,专门用于在移动和嵌入式设备上运行模型。以下是将Keras模型转换为TensorFlow Lite模型的示例代码:
import tensorflow as tf
# 加载Keras模型
model = tf.keras.models.load_model('my_mnist_model/0001')
# 创建转换器
converter = tf.lite.TFLiteConverter.from_keras_model(model)
# 转换模型
tflite_model = converter.convert()
# 保存转换后的模型
with open('my_mnist_model.tflite', 'wb') as f:
f.write(tflite_model)
在移动应用中,可以使用TensorFlow Lite的SDK加载和运行转换后的模型。
5.2 部署到嵌入式设备
与部署到移动应用类似,也可以使用TensorFlow Lite将模型部署到嵌入式设备上。嵌入式设备通常资源有限,TensorFlow Lite的轻量级特性可以确保模型在这些设备上高效运行。
5.3 部署到Web应用
可以使用TensorFlow.js将TensorFlow模型部署到Web应用中。TensorFlow.js是一个用于在浏览器和Node.js中运行深度学习模型的JavaScript库。以下是将Keras模型转换为TensorFlow.js格式的示例代码:
import tensorflow as tf
import tensorflowjs as tfjs
# 加载Keras模型
model = tf.keras.models.load_model('my_mnist_model/0001')
# 转换模型
tfjs.converters.save_keras_model(model, 'web_model')
在Web应用中,可以使用TensorFlow.js的API加载和运行转换后的模型。
6. 总结
本文详细介绍了如何大规模训练和部署TensorFlow模型。首先,介绍了使用TF Serving部署模型的完整流程,包括导出SavedModel、安装和启动TF Serving、在Docker容器中运行TF Serving、通过REST API和gRPC API查询模型以及部署新模型版本等内容。然后,介绍了使用Vertex AI在云端服务模型的方法,以及加速模型训练的策略,如使用硬件加速器和分布式训练。最后,探讨了将模型部署到移动应用、嵌入式设备和Web应用的方法。
通过合理选择部署方式和加速训练的方法,可以提高模型的性能和可用性,满足不同场景下的需求。无论是小型项目还是大型企业级应用,都可以根据实际情况选择合适的技术和工具,实现高效的模型训练和部署。
以下是一个总结本文主要内容的表格:
| 内容 | 详细信息 |
| ---- | ---- |
| 模型部署 | 使用TF Serving和Vertex AI,包括导出模型、安装服务、查询模型、部署新版本等步骤 |
| 加速训练 | 使用GPU、TPU等硬件加速器,以及分布式训练策略 |
| 其他部署平台 | 移动应用(TensorFlow Lite)、嵌入式设备(TensorFlow Lite)、Web应用(TensorFlow.js) |
以下是整个模型训练和部署流程的流程图:
graph LR;
A[训练模型] --> B[导出为SavedModel];
B --> C{选择部署方式};
C -->|TF Serving| D[安装和启动TF Serving];
C -->|Vertex AI| E[上传模型到Vertex AI];
D --> F[查询TF Serving];
E --> G[创建端点并部署模型];
G --> H[查询Vertex AI模型];
B --> I[转换为其他格式];
I -->|TensorFlow Lite| J[部署到移动/嵌入式设备];
I -->|TensorFlow.js| K[部署到Web应用];
A --> L[加速训练];
L -->|硬件加速器| M[GPU/TPU];
L -->|分布式训练| N[使用分布式策略];
希望本文能帮助你更好地理解和掌握TensorFlow模型的大规模训练和部署技术,让你的机器学习项目更加高效和成功。
超级会员免费看
2403

被折叠的 条评论
为什么被折叠?



