从 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为基础把PULocationID、DOLocationID、payment_type三个类别列强转为STRING构建了 ML 特征表yellow_tripdata_ml然后用model_typelinear_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_typelinear_reg, input_label_cols[tip_amount], DATA_SPLIT_METHODAUTO_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 MLSQLtaxi-rides-ny.nytaxi.tip_model模型导出bq extract -mCloud Storage 桶中的tip_model目录本地获取gsutil cp -r本地/tmp/model/tip_modelSavedModel 结构容器托管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指定模型所在的项目 IDextractbq的导出子命令此处针对的是模型-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/modelgsutil cp -r的复制输出恰好揭示了导出的 BigQuery 模型到底是什么一个标准的 TensorFlow 模型——包含assets、variables两个目录以及若干元数据文件如saved_model.pb、fingerprint.pb等.pb结尾的协议缓冲文件。这正是 TensorFlow SavedModel 的约定布局variables存放训练得到的权重assets存放模型附带的资源saved_model.pb描述模型的计算图与签名signature。理解这一点很关键BigQuery ML 的线性回归模型在导出时被序列化为 TensorFlow 生态通用的 SavedModel 格式这意味着后续任何兼容 TensorFlow 的服务框架包括 TensorFlow Serving都能无缝加载它。用 Docker 运行 TensorFlow ServingTensorFlow 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 typebind,sourcepwd/serving_dir/tip_model,target/models/tip_model \ -e MODEL_NAMEtip_model -t tensorflow/serving 逐步拆解这条docker run-p 8501:8501把容器内 TensorFlow Serving 的 REST API 端口默认8501映射到宿主机的同名端口官方镜像通常同时开放8500供 gRPC 调用本示例走 REST故只需映射8501--mount typebind,source$(pwd)/serving_dir/tip_model,target/models/tip_model把本地 serving 目录绑定挂载到容器内的/models/tip_model。注意 TensorFlow Serving 默认在/models/模型名下加载模型因此挂载目标路径的末段必须与MODEL_NAME一致-e MODEL_NAMEtip_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 完成。请求体为 JSONinstances数组中携带与训练时完全一致的列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/模型名:predictinstances是推理负载的容器可一次传入多条样本类别特征以字符串形式传入如PULocationID:193、payment_type:1与训练阶段强转为STRING的特征类型保持一致——模型在训练时对这三个类别列做了自动 one-hot 编码推理请求也必须按类别语义传值。对这一笔行程1 名乘客、12.2 英里、车费 20.4 美元模型预测小费约为 3.2 美元更有说服力的验证是「扰动输入、观察输出」把payment_type从1卡片支付改为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 以「版本号目录」区分模型的多版本加载1、2这样的数字目录会被识别为版本若目录名不是纯数字模型无法被正确加载。3. 端口映射只暴露了 REST。官方镜像默认同时开放8500gRPC与8501HTTP/REST。本示例只映射了8501若需要使用 gRPC 客户端需额外映射8500。4. 推理请求的特征类型要与训练一致。模型训练时把PULocationID、DOLocationID、payment_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),仅供参考