news 2026/9/12 14:32:37

从 BigQuery 导出模型到 REST 服务:data-engineering-zoomcamp 的 TensorFlow Serving + Docker 部署实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从 BigQuery 导出模型到 REST 服务:data-engineering-zoomcamp 的 TensorFlow Serving + Docker 部署实战

从 BigQuery 导出模型到 REST 服务:data-engineering-zoomcamp 的 TensorFlow Serving + Docker 部署实战

【免费下载链接】data-engineering-zoomcampData Engineering Zoomcamp is a free 9-week course on building production-ready data pipelines. Join the course here 👇🏼项目地址: https://gitcode.com/GitHub_Trending/da/data-engineering-zoomcamp

在 Data Engineering Zoomcamp 的「Data Warehousing」模块中,我们不仅用 SQL 在 BigQuery 内部完成了 taxi 小费预测模型的训练、评估与调参,还可以把模型「搬出」数仓:导出到 Cloud Storage、拉取到本地、放进 Docker 容器里用 TensorFlow Serving 提供 REST 预测服务。本篇技术指南以课程文档 06-deploying-a-machine-learning-model.md 为主体,完整拆解「导出 → 复制 → 容器化托管 → HTTP 推理」这条端到端部署链路,并补充仓库内训练脚本与 SQL 文件的源码级佐证。读完你将掌握:如何用bq导出 BigQuery ML 模型、如何按 TensorFlow Serving 的目录约定组织模型文件、如何用一条docker run把模型变成可被curl调用的线上服务。

本篇在课程中的位置:模型从哪里来

在开始部署之前,先明确被部署的对象。本模块的上一单元 05-machine-learning-in-bigquery.md 完成了模型训练:我们以yellow_tripdata_partitioned为基础,把PULocationIDDOLocationIDpayment_type三个类别列强转为STRING,构建了 ML 特征表yellow_tripdata_ml,然后用model_type='linear_reg'创建了预测tip_amount(小费金额)的线性回归模型tip_model。这些 SQL 全部收录在 big_query_ml.sql 中,例如:

-- CREATE MODEL WITH DEFAULT SETTING CREATE OR REPLACE MODEL `taxi-rides-ny.nytaxi.tip_model` OPTIONS (model_type='linear_reg', input_label_cols=['tip_amount'], DATA_SPLIT_METHOD='AUTO_SPLIT') AS SELECT * FROM `taxi-rides-ny.nytaxi.yellow_tripdata_ml` WHERE tip_amount IS NOT NULL;

本单元就是这个训练的「下半场」:把训练好的tip_model从 BigQuery 中导出,脱离数仓环境,作为独立的服务运行。训练数据与建表语句可进一步参考 big_query.sql(外部表、分区表与聚簇表的构建)和本模块总览 README.md。

部署的完整闭环:一条端到端链路

整条部署流程是一条可复现的命令链,每一步都有明确的工具与产物:

阶段工具/载体产物
模型训练BigQuery ML(SQL)taxi-rides-ny.nytaxi.tip_model
模型导出bq extract -mCloud Storage 桶中的tip_model目录
本地获取gsutil cp -r本地/tmp/model/tip_model(SavedModel 结构)
容器托管Docker + TensorFlow Serving监听8501端口的 REST 服务
在线推理curl/ Postman POST每笔行程的predicted_tip_amount

这个闭环的价值在于:模型以 SQL 形式在数仓内训练,却能以标准 TensorFlow SavedModel 格式输出,最终被通用的模型服务框架接管——训练与推理环境解耦,模型生命周期得以延长到生产环境。

导出模型到 Cloud Storage

首先确保已完成gcloud auth login(视频中已执行),接着用 BigQuery 命令行工具bq将模型提取到 Cloud Storage 桶:

bq --project_id taxi-rides-ny extract -m nytaxi.tip_model gs://taxi_ml_model/tip_model

命令要点:

  • --project_id taxi-rides-ny:指定模型所在的项目 ID;
  • extractbq的导出子命令,此处针对的是模型(-m),而非表;
  • nytaxi.tip_model:数据集.模型名,即 big_query_ml.sql 中CREATE OR REPLACE MODEL创建的那个模型;
  • gs://taxi_ml_model/tip_model:目标桶与目录,导出完成后桶内会出现同名tip_model文件夹。

将模型复制到本地

导出到 GCS 后,用gsutil把整个目录拉到本地:

mkdir /tmp/model gsutil cp -r gs://taxi_ml_model/tip_model /tmp/model

gsutil cp -r的复制输出恰好揭示了导出的 BigQuery 模型到底是什么:一个标准的 TensorFlow 模型——包含assetsvariables两个目录,以及若干元数据文件(如saved_model.pbfingerprint.pb.pb结尾的协议缓冲文件)。这正是 TensorFlow SavedModel 的约定布局:variables存放训练得到的权重,assets存放模型附带的资源,saved_model.pb描述模型的计算图与签名(signature)。

理解这一点很关键:BigQuery ML 的线性回归模型在导出时被序列化为 TensorFlow 生态通用的 SavedModel 格式,这意味着后续任何兼容 TensorFlow 的服务框架(包括 TensorFlow Serving)都能无缝加载它。

用 Docker 运行 TensorFlow Serving

TensorFlow Serving 对模型目录有严格的约定:外层目录以「模型名」命名,其下每个子目录对应一个「版本号」,版本号必须是数字。因此我们创建serving_dir/tip_model/1,把模型文件放入版本目录:

mkdir -p serving_dir/tip_model/1 cp -r /tmp/model/tip_model/* serving_dir/tip_model/1 docker pull tensorflow/serving docker run -p 8501:8501 \ --mount type=bind,source=`pwd`/serving_dir/tip_model,target=/models/tip_model \ -e MODEL_NAME=tip_model -t tensorflow/serving &

逐步拆解这条docker run

  • -p 8501:8501:把容器内 TensorFlow Serving 的 REST API 端口(默认8501)映射到宿主机的同名端口;官方镜像通常同时开放8500供 gRPC 调用,本示例走 REST,故只需映射8501
  • --mount type=bind,source=$(pwd)/serving_dir/tip_model,target=/models/tip_model:把本地 serving 目录绑定挂载到容器内的/models/tip_model。注意 TensorFlow Serving 默认在/models/<模型名>下加载模型,因此挂载目标路径的末段必须与MODEL_NAME一致;
  • -e MODEL_NAME=tip_model:通过环境变量告诉 TensorFlow Serving 要服务哪个模型,此值必须与目录名(tip_model)完全对应;
  • -t:分配伪终端,方便观察日志;末尾的&让容器在后台运行。

服务目录的位置很灵活,放在项目目录或临时目录均可——关键是目录结构符合「模型名/版本号」的约定。启动后可用docker ps确认容器状态:

检查模型:REST 元数据接口

TensorFlow Serving 暴露了 REST API,模型元数据位于http://localhost:8501/v1/models/tip_model。用 GET 请求(视频中使用 Postman)即可查询模型状态:

curl http://localhost:8501/v1/models/tip_model

返回的 JSON 中,model_version_status字段会给出每个版本的状态。响应表明tip_model的版本 1 状态为AVAILABLE——模型已成功加载,没有报错。这一步相当于部署后的「健康检查」:在发起任何预测之前,先用元数据接口确认模型已就绪。

通过 HTTP 发起预测

模型就绪后,真正的预测通过 POST 完成。请求体为 JSON,instances数组中携带与训练时完全一致的列:passenger_count(乘客数)、trip_distance(行程距离)、PULocationID(上车地点 ID)、DOLocationID(下车地点 ID)、payment_type(支付方式)、fare_amount(车费)、tolls_amount(过路费)。对照 big_query_ml.sql 中的特征选择语句,可以看到这 7 个字段正是训练时SELECT出的特征(不含标签tip_amount)。

curl -d '{"instances": [{"passenger_count":1, "trip_distance":12.2, "PULocationID":"193", "DOLocationID":"264", "payment_type":"1","fare_amount":20.4,"tolls_amount":0.0}]}' \ -X POST http://localhost:8501/v1/models/tip_model:predict

请求细节说明:

  • 端点:predict是 TensorFlow Serving REST 推理的固定后缀,完整路径为/v1/models/<模型名>:predict
  • instances是推理负载的容器,可一次传入多条样本;
  • 类别特征以字符串形式传入(如"PULocationID":"193""payment_type":"1"),与训练阶段强转为STRING的特征类型保持一致——模型在训练时对这三个类别列做了自动 one-hot 编码,推理请求也必须按类别语义传值。

对这一笔行程(1 名乘客、12.2 英里、车费 20.4 美元),模型预测小费约为 3.2 美元:

更有说服力的验证是「扰动输入、观察输出」:把payment_type1(卡片支付)改为2(现金支付),其余特征不变,再次发送请求,预测小费骤降至约 0.26 美元。这说明模型确实学习到了支付方式对是否给小费的强影响——现金支付场景下小费预测大幅下降,符合直觉,也反向印证了模型在 05-machine-learning-in-bigquery.md 中ML.EXPLAIN_PREDICT的结论:payment_type等类别特征是模型最依赖的信号之一。

部署细节与常见坑

结合仓库代码与上述操作,整理几个容易踩坑、但理解后即可绕过的关键点:

1. 目录命名必须与MODEL_NAME严格一致。容器内默认的模型根目录是/models,挂载目标/models/tip_model的末段、-e MODEL_NAME的值、serving 目录的外层文件夹名三者必须统一为tip_model,否则 TensorFlow Serving 找不到模型。

2. 版本目录必须是数字。TensorFlow Serving 以「版本号目录」区分模型的多版本加载,12这样的数字目录会被识别为版本;若目录名不是纯数字,模型无法被正确加载。

3. 端口映射只暴露了 REST。官方镜像默认同时开放8500(gRPC)与8501(HTTP/REST)。本示例只映射了8501,若需要使用 gRPC 客户端,需额外映射8500

4. 推理请求的特征类型要与训练一致。模型训练时把PULocationIDDOLocationIDpayment_type作为类别特征处理(见 big_query_ml.sql 中的CAST(... AS STRING)),推理请求中这三个字段应传字符串而非裸数字,否则输入语义会与训练分布产生偏差。

5. 健康检查先于推理。部署后先用GET /v1/models/tip_model确认版本状态为AVAILABLE,再执行 POST 推理,能显著减少「服务未就绪导致推理失败」的排查成本。

小结:一个完整的模型生命周期闭环

至此,一条完整的链路走通:用 SQL 在 BigQuery 内训练线性回归模型 →bq extract -m导出到 Cloud Storage →gsutil cp拉取到本地 → 按「模型名/版本号」组织目录 →docker run启动 TensorFlow Serving → 通过curl/Postman 调用 REST 接口获得预测结果

其价值不止于「能跑」:训练环节充分利用数仓内计算(数据无需搬出 BigQuery),推理环节则把模型交付给标准化的容器服务——这正是数据工程中「模型管理」与「模型服务」两个环节的典型衔接方式。若要继续深入,可以查阅本模块 README.md 中的单元列表与作业,把这一部署链路纳入你自己的数据管道练习中。

【免费下载链接】data-engineering-zoomcampData Engineering Zoomcamp is a free 9-week course on building production-ready data pipelines. Join the course here 👇🏼项目地址: https://gitcode.com/GitHub_Trending/da/data-engineering-zoomcamp

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 14:32:22

AI Agent多租户数据库选型:从VM级隔离到Serverless弹性实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 14:31:08

基于Spring Boot和MyBatis的实验教学管理系统设计与实现

简介&#xff1a;一套基于Java核心技术的实验教学管理系统完整源码&#xff0c;面向教育技术开发者、Java初学者及高校实验管理人员&#xff0c;覆盖用户管理、课程安排、实验报告提交等典型场景。资源包总文件131个&#xff0c;约1.95MB&#xff0c;包含73个Java后端源文件、1…

作者头像 李华
网站建设 2026/9/12 14:31:07

深度学习语音情绪识别:从特征工程到CNN模型部署实战

简介&#xff1a;基于深度学习语音情绪识别的完整工程包&#xff0c;面向毕业设计、课程设计及语音情感分析入门者&#xff0c;涵盖从音频特征提取、模型训练到预测推理的完整流程。包内共34个文件&#xff0c;其中17个Python脚本构成核心代码&#xff0c;包含训练/预测脚本、特…

作者头像 李华
网站建设 2026/9/12 14:26:53

POD-DMD实战:从CFD数据压缩到流场模态分析与短期预测

简介&#xff1a;这是一份面向流体力学与CFD研究者的POD-DMD模态分析资源包&#xff0c;聚焦计算流体动力学数据后处理中的降维与动态模式分解。内容围绕POD提取流场主导模态、DMD揭示时序演化特征展开&#xff0c;适用于航空航天、海洋工程、环境流体等方向的流场特征识别与机…

作者头像 李华