pip install ydf -U
关于本教程¶
本教程展示了如何训练一个YDF模型,将其导出为TensorFlow SavedModel格式,并在Vertex AI中运行该模型。此外,本教程还展示了如何手动运行TensorFlow Serving二进制文件,以使用该模型进行推断。
什么是TF Serving?¶
TensorFlow Serving是一个用于运行机器学习模型的生产环境。TensorFlow Serving可以运行YDF模型。
什么是Vertex AI?¶
Vertex AI是谷歌云提供的解决方案,用于管理和服务机器学习模型。Vertex AI依赖TensorFlow Serving来运行存储在TensorFlow SavedModel格式中的TensorFlow模型。YDF模型可以通过model.to_tensorflow_saved_model方法导出为TensorFlow SavedModel,并在TensorFlow Serving和Vertex AI上运行。
关于TensorFlow Saved Model输入的重要说明¶
TensorFlow Saved Model可以被视为一个通用函数,它接受数据作为输入并产生预测作为输出。TensorFlow Serving和Vertex AI定义了三种输入格式用于提供输入特征,以及三种输出格式用于获取预测。使用不正确的格式可能会导致隐晦的错误消息。了解这些格式并不是使用TensorFlow Serving和Vertex AI所必需的,但对于调试管道可能会很有帮助。本节提供了这些格式的概述。
YDF允许你通过to_tensorflow_saved_model
函数的servo_api: bool
和feed_example_proto: bool
参数选择模型的格式类型。
输入格式 #1: 输入实例
在这种格式中,数据按示例分组,每个示例是一个包含特征的字典,存放在列表中。该格式简单明了但效率不高。此格式可以与所有API(REST、Python、C++)轻松配合使用。此格式用于Vertex AI的在线预测和Vertex AI批量预测的jsonl。
这是一个示例列表,每个示例都有三个特征"f1"、"f2"和"f3":
[ {"f1": 1, "f2": 5.9, "f3": "red" }, {"f1": 3, "f2": 2.1, "f3": "blue" } ]
这是to_tensorflow_saved_model
函数的默认输入格式,即feed_example_proto=False
。
输入格式 #2: 输入特征
在这种格式中,数据按特征分组,每个特征是一个字典中的值列表。该格式相对简单且效率最高。此格式可以与所有API(REST、Python、C++)轻松配合使用。当可能时,这是推荐使用的格式。
这是相同示例的此格式:
{"f1": [1, 3], "f2": [5.9, 2.1], "f3": ["red", "blue"] }
这也是to_tensorflow_saved_model
函数的默认输入格式,即feed_example_proto=False
。
输入格式 #3: 序列化的TensorFlow示例
在最后一种格式中,数据编码为TensorFlow示例原语的Google Protobuf,这也是用于训练大型TensorFlow管道的格式。此格式在服务时效率不高且相对复杂。在可能的情况下,尽量避免在推断时使用此格式。此格式是Vertex AI Batch预测中需要的TensorFlow记录文件的要求。
通过feed_example_proto=True
在to_tensorflow_saved_model
函数中启用此格式。
输出格式 #1: 预测
此格式是最简单和最有效的。模型直接输出预测值。预测的意义由模型决定。例如,分类模型将输出概率,而回归模型将输出值。这是to_tensorflow_saved_model
函数的默认输出格式,即servo_api=False
。
这是一个二元分类模型的预测示例:
{ "prediction": [0.2, 0.7] }
这是一个多分类模型的预测示例:
{ "prediction": [[0.2, 0.1, 0.7],
[0.8, 0.1, 0.1]] }
此格式适用于Vertex AI的在线预测。
输出格式 #2 和 #3: 分类和回归
在这些格式中,模型输出一个值的字典。值依赖于模型类型。例如,分类模型将输出一个"score"和一个"labels"值。此输出格式在to_tensorflow_saved_model
函数中通过servo_api=True
启用。
此格式适用于Vertex AI的在线预测,并且是Vertex AI批量预测所必需的。
这是一个二元分类模型的预测示例:
{ "scores": [[0.2, 0.8],
[0.1, 0.9]],
"classes": [["v1", "v2"],
["v1", "v2"]]}
# 加载库
import ydf # Yggdrasil决策森林
import pandas as pd # 我们使用Pandas来加载小型数据集。
# 下载一个分类数据集,并将其加载为Pandas DataFrame。
ds_path = "https://raw.githubusercontent.com/google/yggdrasil-decision-forests/main/yggdrasil_decision_forests/test_data/dataset"
train_ds = pd.read_csv(f"{ds_path}/adult_train.csv")
test_ds = pd.read_csv(f"{ds_path}/adult_test.csv")
# 打印前5个训练样本
train_ds.head(5)
age | workclass | fnlwgt | education | education_num | marital_status | occupation | relationship | race | sex | capital_gain | capital_loss | hours_per_week | native_country | income | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 44 | Private | 228057 | 7th-8th | 4 | Married-civ-spouse | Machine-op-inspct | Wife | White | Female | 0 | 0 | 40 | Dominican-Republic | <=50K |
1 | 20 | Private | 299047 | Some-college | 10 | Never-married | Other-service | Not-in-family | White | Female | 0 | 0 | 20 | United-States | <=50K |
2 | 40 | Private | 342164 | HS-grad | 9 | Separated | Adm-clerical | Unmarried | White | Female | 0 | 0 | 37 | United-States | <=50K |
3 | 30 | Private | 361742 | Some-college | 10 | Married-civ-spouse | Exec-managerial | Husband | White | Male | 0 | 0 | 50 | United-States | <=50K |
4 | 67 | Self-emp-inc | 171564 | HS-grad | 9 | Married-civ-spouse | Prof-specialty | Wife | White | Female | 20051 | 0 | 30 | England | >50K |
我们训练模型:
model = ydf.GradientBoostedTreesLearner(label="income").train(train_ds)
Train model on 22792 examples Model trained in 0:00:02.335818
注意: 尽管这里没有演示,但建议在使用模型之前查看并评估模型。使用 model.describe()
方法检查模型的结构和特征,并使用 model.evaluate(...)
方法评估其性能和准确性。有关详细信息,请参见入门教程。
将模型导出为 TF Saved Model 格式¶
TensorFlow Serving 只能读取 TensorFlow SavedModel 格式的模型。因此,我们将 YDF 模型导出为 TensorFlow SavedModel 格式。
此步骤需要安装 TensorFlow 决策森林 库。
信息: TensorFlow 决策森林是基于 YDF 构建的 Keras 2 封装,由 YDF 团队开发。对于大多数使用案例,直接使用 YDF 是更可取的,因为它更快,更易于使用,并且与 Keras 2 和 Keras 3 兼容。了解 更多。
!pip install tensorflow_decision_forests -qq
# 将模型导出为 TensorFlow SavedModel 格式。
# 对于Vertex AI在线推理。
# 该模型消耗原始特征值,并输出原始模型预测结果。
model.to_tensorflow_saved_model("/tmp/ydf/tf_model", mode="tf")
# 对于Vertex AI批量推理。
# 该模型会消耗TensorFlow Example协议缓冲区,并返回一个字典。
# model.to_tensorflow_saved_model("/tmp/ydf/tf_model", mode="tf", servo_api=True, feed_example_proto=True)
[INFO 24-04-12 14:12:24.7037 CEST kernel.cc:1233] Loading model from path /tmp/tmp5siwullh/tmppvtwaq00/ with prefix 18bdf8d5_ [INFO 24-04-12 14:12:24.7308 CEST quick_scorer_extended.cc:911] The binary was compiled without AVX2 support, but your CPU supports it. Enable it for faster model inference. [INFO 24-04-12 14:12:24.7316 CEST abstract_model.cc:1344] Engine "GradientBoostedTreesQuickScorerExtended" built [INFO 24-04-12 14:12:24.7316 CEST kernel.cc:1061] Use fast generic engine
在 Vertex AI 中导入模型¶
要在 Vertex AI 中导入模型,请按照以下步骤操作:
1. 将 TensorFlow 保存的模型导入 Google Cloud 存储桶
- 打开 Cloud Storage 页面。
- 创建一个新的存储桶或选择一个现有的存储桶。
- 点击 "上传文件夹",选择之前导出的模型,示例中是
/tmp/ydf/tf_model
。
模型存储桶中应该包含一个名为 saved_model.pb
的文件。例如,如果将模型上传到 gs://my_bucket
存储桶,应该存在文件 gs://ydf_model_2/tf_model/saved_model.pb
。
2. 在 Vertex AI 中注册模型
- 打开 Vertex AI 模型注册页面。
- 点击 "导入",并从云存储桶中选择模型。
- 在 "导入模型" 对话框中,配置以下选项:
- 名称: 输入模型的名称。
- 模型框架: 选择 TensorFlow。
- 模型框架版本: 选择最新版本,截至本文写作时为 2.13。
- 加速器: 选择 None。
- 模型工件位置: 指定模型工件的 Google Cloud Storage (GCS) 路径,例如
gs://my_bucket/tf_model/
。 - 使用优化的 TensorFlow 运行时: 禁用此选项。决策森林不支持此神经网络特定优化。
- 保持其他选项为默认值,点击 "继续"。
- 当询问关于可解释性时,选择 "无可解释性",然后点击 "导入"。
模型将在几分钟内导入完成。您可以在模型注册页面的右上角监控进度。导入后,模型将出现在注册模型的列表中。
模型现在已经准备好进行推理。
在线预测¶
模型可以部署到“端点”并通过云REST API远程查询。
- 打开 云模型注册页。
- 选择模型,打开“部署和测试”标签,点击“部署到端点”。
- 按如下配置端点:
- 端点名称: 输入端点的名称。
- 机器类型: 选择尽可能小的机器,例如
n1-standard-2
。
- 点击“部署”
端点正在部署中。
在“测试你的模型”部分,用以下JSON请求查询模型:
{
"instances":[
{
"age":39,
"workclass":"State-gov",
"fnlwgt":77516,
"education":"Bachelors",
"education_num":13,
"marital_status":"Never-married",
"occupation":"Adm-clerical",
"relationship":"Not-in-family",
"race":"White",
"sex":"Male",
"capital_gain":2174,
"capital_loss":0,
"hours_per_week":40,
"native_country":"United-States"
}
]
}
结果将会是:
{
"predictions": [
0.0186043456
],
"deployedModelId": "2255069761266253824",
"model": "projects/734980258708/locations/us-central1/models/8572427068350922752",
"modelDisplayName": "tf_model_servoF_protoF",
"modelVersionId": "1"
}
该预测结果表明模型对正类的真实可能性为1.66%。换句话说,模型预测为负类。
print("The positive and negative classes are:", model.label_classes())
The positive and negative classes are: ['<=50K', '>50K']
批量预测¶
现在,让我们使用模型进行批量预测。这涉及到上传一个包含实例的文件,生成预测,并以 JSON 文件的格式获取结果。
我们从 CSV 文件 中加载了训练数据集。然而,使用 CSV 文件与 TensorFlow SavedModel 可能会导致错误。为了避免问题,我们将使用 TensorFlow 官方的数据集格式,一个 tf.train.Example protobuf 的 TFRecord 文件。幸运的是,测试数据集以这种格式现成可用 here。
- 在您的计算机上下载 "adult_test.recordio.gz"。
- 打开 Cloud Storage 页面。
- 在您已经创建的存储桶中,点击 "上传文件" 并选择文件
adult_test.recordio.gz
。 - 在 Cloud Storage 页面中,选择该文件并将其重命名为
adult_test.tfrecord.gz
。- Vertex AI 通过扩展名检测文件格式。
- 打开 Cloud Model Registry 页面。
- 选择模型,打开 "批量预测" 标签,然后点击 "创建批量预测"。
- 按如下配置批量预测:
- 批量预测名称: 输入预测的名称。
- Cloud Storage 上的文件(JSONL、CSV、TFRecord 和 TFRecord(GZIP)): 选择
adult_test.tfrecord.gz
文件。 - 目标路径: 选择包含模型和数据集的存储桶。
- 计算节点数量: 输入 "1"。这是一个小数据集,不需要太多算力。
- 机器类型: 选择尽可能小的机器,例如
n1-standard-2
。
- 点击 "创建"
预测正在计算中。当计算完成后,您将在您的存储桶中找到一个新创建的 JSON 文件。
以下是生成文件的前五行:
{"prediction": {"scores": [0.981395662, 0.0186043456], "classes": ["<=50K", ">50K"]}}
{"prediction": {"scores": [0.638690472, 0.361309558], "classes": ["<=50K", ">50K"]}}
{"prediction": {"scores": [0.161411345, 0.838588655], "classes": ["<=50K", ">50K"]}}
{"prediction": {"scores": [0.956144333, 0.0438556746], "classes": ["<=50K", ">50K"]}}
{"prediction": {"scores": [0.970823526, 0.0291764941], "classes": ["<=50K", ">50K"]}}
您可以看到每个示例和每个类别的预测概率。例如,在第一个示例中,模型以 98.14% 的概率预测类别 "<=50K"。
在本地 TensorFlow Serving 中运行模型 [高级]¶
可以在本地或远程机器上启动 TensorFlow Serving 二进制文件,并通过 TensorFlow Serving REST API 发送请求。我们来展示一下如何实现:
为了测试我们的模型,我们按照 tf serving 设置说明 启动一个本地版本的 TF Serving。
在一个单独的终端中,输入:
cd /tmp/ydf
docker run -t --rm -p 8501:8501 \
-v /tmp/tf/tf_model:/models/my_saved_model/1 \
-e MODEL_NAME=my_saved_model \
tensorflow/serving
注意: TensorFlow Serving 期望模型路径遵循结构:models/<MODEL_NAME>/<VERSION>
一旦 TensorFlow Serving 服务器启动并运行,您可以发送预测请求。以下是每个请求的示例:
使用输入实例格式进行预测:
!curl http://localhost:8501/v1/models/my_saved_model:predict -X POST \
-d '{"instances": [{"age":39,"workclass":"State-gov","fnlwgt":77516,"education":"Bachelors","education_num":13,"marital_status":"Never-married","occupation":"Adm-clerical","relationship":"Not-in-family","race":"White","sex":"Male","capital_gain":2174,"capital_loss":0,"hours_per_week":40,"native_country":"United-States"}]}'
使用输入特征格式进行预测:
!curl http://localhost:8501/v1/models/my_saved_model:predict -X POST \
-d '{"inputs": {"age":[39],"workclass":["State-gov"],"fnlwgt":[77516],"education":["Bachelors"],"education_num":[13],"marital_status":["Never-married"],"occupation":["Adm-clerical"],"relationship":["Not-in-family"],"race":["White"],"sex":["Male"],"capital_gain":[2174],"capital_loss":[0],"hours_per_week":[40],"native_country":["United-States"]} }'