在快速发展的机器学习领域,部署模型到生产环境并高效维护这些模型至关重要。这让我开始探索 MLOps — 结合了机器学习(ML)与 DevOps 的一套实践方法,旨在自动和简化整个机器学习的生命周期。2021 年,在我早期的职业生涯中构建了一个类似但稍微更复杂的管道,这让我非常期待再次审视这一主题,以便跟上最新的发展。
在这篇博客文章中,我将一步步带您了解如何使用Google Cloud的Vertex AI构建一个端到端的MLOps流水线。这个流水线自动化了数据获取、模型训练、评估和模型部署。
不论你是希望将模型投入实际应用的机器学习从业者,还是对MLOps(机器学习运维)感兴趣的人,本文希望提供一个使用Vertex AI构建和部署这些模型的实用说明。
你可以点击这里: https://github.com/whiteking64/mlops-gcp/tree/v1.0 查看完整实现。
MLOps(机器学习运维)是一套旨在可靠且高效地在生产环境中部署和维护机器学习模型的方法。它更专注于解决机器学习系统特有的挑战,例如数据版本管理、模型训练、验证、部署及监控。
MLOps的关键方面有:
Google Vertex AI 是一个集成 Google Cloud 服务的统一平台,用于构建 ML 模型。它通过提供覆盖整个 ML 生命周期的工具和服务,简化了开发和部署 ML 模型的过程。
Vertex AI的关键特性
好处 :
该项目的目标是构建一个完整的MLOps流水线,具体包括从数据预处理到模型部署的各个环节:
注意:此流程展示了一个简化的架构。在实际生产环境中,需要更多额外的组件和更强大的设置。
场景:
使用的技术和工具:
这个管道系统包括几个关键组件。
DistilBERT
模型,并通过评估来检验模型的性能。让我们来看看管道中的每个环节,看看它们是怎么做的。
目标:加载数据,对数据集进行预处理,并将其上传到BigQuery以便在其中存储和查询。
步骤如下:
datasets
库中的AG News数据集。0
映射为World
)。timestamp
字段以模拟实际最近的数据条目。下载和上传数据 (准备数据集的脚本
):
dataset = load_dataset("ag_news") subset = dataset["train"].select(range(size)) df = pd.DataFrame(subset) label_mapping = {0: "世界", 1: "体育", 2: "商业", 3: "科学与技术"} df["label"] = df["label"].map(label_mapping) # 添加时间戳以模拟近期数据 df["timestamp"] = pd.date_range(end=datetime.datetime.now(), periods=size) # 将数据上传到Google的BigQuery数据仓库 df.to_gbq( destination_table=f"{config['dataset_id']}.{config['table_id']}", project_id=project_id, if_exists="replace", # 在表已存在的情况下替换它 )
timestamp
字段在这个流程中非常重要,特别是在多次运行的过程中考虑时间因素时。原因如下:
在后续的管道运行过程中,您可以修改数据获取组件,让它只抓取某个时间戳之后的数据,确保每次训练都能获取最新的数据,不会重复。
执行之后,你就可以看到数据已经被正确地存储了,在BigQuery中。
目标:利用Kubeflow Pipelines来定义和调度ML的工作流程。
定义管道流程(main.py
):
@dsl.pipeline( name="文本分类管道", description="一个训练和部署文本分类模型的管道", ) def text_classification_pipeline(): fetch_data_task = fetch_data_from_bigquery(...) train_task = train_model(input_dataset=fetch_data_task.outputs["output_dataset"]) deploy_task = deploy_model(model=train_task.outputs["output_model"])
编译并运行流程:
compiler.Compiler().compile( pipeline_func=text_classification_pipeline, package_path="text_classification_pipeline.json", ) job = pipeline_jobs.PipelineJob( display_name="文本分类流水线", template_path="text_classification_pipeline.json", pipeline_root=f"gs://{config['bucket_name']}/pipeline_root", # 设置管道根目录,用于保存运行时生成的文件 ) job.run(service_account=config["service_account"]) # 使用指定的服务账户运行流水线作业
在 Vertex AI 的“工作流”页面上,您可以看到所有执行过的管道。
目标:在拿到的数据集上训练一个DistilBERT
模型来并对其性能进行评估。
关键步骤如下:
DistilBERT
分词器和模型。Trainer
API 进行训练。代码片段(训练代码):
tokenizer = AutoTokenizer.from_pretrained("distilbert-base-uncased") model = AutoModelForSequenceClassification.from_pretrained( "distilbert-base-uncased", num_labels=num_labels ) # 准备训练和验证数据集 train_encodings = tokenizer(train_texts, truncation=True, padding=True) val_encodings = tokenizer(val_texts, truncation=True, padding=True) # 初始化 Trainer training_args = TrainingArguments(...) trainer = Trainer( model=model, args=training_args, train_dataset=train_dataset, eval_dataset=val_dataset, ) trainer.train() # 评估模型并保存结果 predictions = trainer.predict(val_dataset) ... model.save_pretrained(output_model.path) tokenizer.save_pretrained(output_model.path)
我们的目标是将这个训练好的模型部署到Vertex AI来提供预测结果。
部署步骤:
代码段(部署流程):
# 上传模型 uploaded_model = aiplatform.Model.upload( display_name=model_display_name, serving_container_image_uri=serving_image_uri, artifact_uri=model.uri, serving_container_ports=[8080], ) # 创建端点 endpoint = aiplatform.Endpoint.create(display_name=endpoint_display_name) # 部署模型到端点 deployed_model = uploaded_model.deploy( endpoint=endpoint, machine_type="n1-standard-4", min_replica_count=1, max_replica_count=1, )
模型部署需要一些时间,完成之后,您就可以在模型注册页面看到模型已经准备就绪。
点击名字,你会发现与模型关联的端点。
在左侧窗格中导航到“在线预测”,你可以看到所有成功或未成功的端点。显然,失败的端点不能被删除。
这是整个工作流!你可以看到DAG,并且所有节点都成功(绿色的勾选)。小图标是组件的输出。在右边,有一个工作流摘要,包括持续时间和指标。就我而言,管道完成耗时1小时。
我们来看一个节点。选择“deploy-model”节点,你就会在右边看到详细信息。按照我们的实现,输入参数已经正确设置。
看看训练节点,你可以看到输出结果。看来是进展顺利!
如果某个节点出了问题,你可以点击页面底部的“日志”来查看详情。
输出文件会被保存到云存储的管道根目录中。
目的:发送一些预测请求样本来测试已部署的模型。
步骤如下:
gcloud
CLI 已通过适当权限的身份进行了认证。示例请求示例 (sample-request.sh
):
curl -X POST \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ -H "Content-Type: application/json" \ "https://us-central1-aiplatform.googleapis.com/v1/projects/$project_id/locations/$location/endpoints/$endpoint_name:predict" \ -d '{ "instances": [ {"text": "示例新闻文章文本……"}, ... ] }'
这应该看起来像下面的链接(我的 GitHub 项目主页,再次说明):
在构建管道时,我遇到了一些挑战。最棘手的一个是模型的部署。
复杂性来自理解多个概念,比如模型、端点、它们的关系以及配置。
我还需要准备一个自定义的容器。有一些预构建的容器,其中包含了PyTorch,其中模型通常是以.mar
格式保存的。然而,我使用的是Hugging Face的模型并用PyTorch保存为.safetensors
格式的模型。将其转换为其他格式证明很棘手,而且我不确定这会对其它伴随文件如编码器造成什么影响。因此,我选择了自定义容器来处理这个问题。Vertex AI的新功能“模型花园”(Model Garden)提供了一种替代方案,您可以在其中指定一个Hugging Face URL来“从Hugging Face上部署”。在这个项目中,这个管道没有将我们微调的模型推送到HF,因此这不是一个选项,但未来值得探索一下。
值得一提的是,你可以通过使用Python Vertex AI SDK中的LocalModel
上传模型。我尝试过这样做,但截至2024年9月似乎存在一个小问题,所以我决定暂时不这样做。
https://github.com/GoogleCloudPlatform/vertex-ai-samples/issues/2833 (这是一个关于Vertex AI样本的问题页面)
另一个小小的挑战是训练部分。如果你看过我的实现,你会注意到我没有使用GPU来进行模型训练。虽然你可以调整机器配置,比如选择不同的加速器等,但遇到了配额限制。作为一个小小的演示,仅用CPU训练模型就已经足够,这实际上不会花太多时间。
基于之前讨论的挑战,我们的 MLOps 管道在改进方面还存在一些局限性。
欢迎在LinkedIn或GitHub上关注我的项目和见解,以了解更多项目和见解.