这是来自Scalable Capital的一篇客座文章,Scalable Capital是欧洲领先的金融科技公司,提供数字财富管理和经纪平台以及固定费率交易。
作为一个快速发展的公司,Scalable Capital的目标不仅是构建创新、稳健和可靠的基础设施,还要为我们的客户提供最佳体验,尤其是在客户服务方面。
Scalable每天收到数百封来自客户的电子邮件咨询。通过实施现代自然语言处理(NLP)模型,响应过程变得更加高效,客户的等待时间大大缩短。机器学习(ML)模型将新收到的客户请求分类,并将其重定向到预定义的队列,这样我们专业的客户成功代理人就可以根据他们的技能专注于电子邮件的内容,并提供适当的回复。
在这篇文章中,我们展示了使用Hugging Face transformers在Amazon SageMaker上部署的技术优势,例如大规模的训练和实验,以及提高生产力和成本效益。
问题陈述
Scalable Capital是欧洲增长最快的金融科技公司之一。公司的目标是使投资民主化,为客户提供轻松进入金融市场的途径。Scalable的客户可以通过公司的经纪交易平台积极参与市场,或者使用Scalable财富管理以智能和自动化的方式进行投资。在2021年,Scalable Capital的客户数量增加了十倍,从数万人增加到数十万人。
为了为客户提供一流(且一致)的用户体验,公司正在寻找自动化解决方案,以实现可伸缩的解决方案,并保持运营卓越。Scalable Capital的数据科学和客户服务团队发现,为客户提供电子邮件咨询的响应是最大的瓶颈之一。具体来说,瓶颈是分类步骤,员工每天都必须阅读和标记请求文本。在电子邮件被路由到相应的队列之后,相应的专家迅速参与并解决了这些案例。
为了简化这个分类过程,Scalable的数据科学团队构建并部署了一个多任务NLP模型,使用了基于Hugging Face发布的预训练distilbert-base-german-cased模型的最新转换器架构。distilbert-base-german-cased使用知识蒸馏方法预训练了一个比原始BERT基础模型更小的通用语言表示模型。蒸馏版本在保持性能可比的同时,更小更快。为了简化我们的ML生命周期过程,我们决定采用SageMaker来构建、部署、提供和监控我们的模型。在下一节中,我们介绍我们的项目架构设计。
解决方案概述
Scalable Capital的ML基础设施由两个AWS帐户组成:一个用于开发阶段的环境,另一个用于生产阶段。
下图显示了我们电子邮件分类器项目的工作流程,但也可以推广到其他数据科学项目。

电子邮件分类项目图示
工作流程包括以下组件:
- 模型实验 – 数据科学家使用Amazon SageMaker Studio进行数据科学生命周期的第一步:探索性数据分析(EDA)、数据清理和准备以及构建原型模型。当探索阶段完成时,我们转向由SageMaker笔记本托管的VSCode作为我们的远程开发工具,将代码基础模块化和产品化。为了探索不同类型的模型和模型配置,并同时跟踪我们的实验,我们使用SageMaker Training和SageMaker Experiments。
- 模型构建 – 在我们为我们的生产用例决定了一个模型之后,本例中是一个经过Hugging Face预训练模型微调的多任务distilbert-base-german-cased模型,我们将代码提交和推送到Github的develop分支。Github的合并事件触发我们的Jenkins CI流水线,该流水线又启动一个带有测试数据的SageMaker Pipelines作业。这作为一个测试,以确保代码按预期运行。部署了一个用于测试目的的测试端点。
- 模型部署 – 在确保一切正常运行后,数据科学家将develop分支合并到主分支。此合并事件现在触发了使用生产数据进行训练的SageMaker Pipelines作业。然后,生成模型工件并存储在输出Amazon Simple Storage Service(Amazon S3)存储桶中,并在SageMaker模型注册表中记录新的模型版本。数据科学家检查新模型的性能,然后根据预期进行批准。模型批准事件由Amazon EventBridge捕获,然后在生产环境中部署模型到SageMaker端点。
- MLOps – 由于SageMaker端点是私有的,无法被VPC之外的服务访问,所以需要一个AWS Lambda函数和Amazon API Gateway公共端点来与CRM进行通信。每当CRM收到新的电子邮件时,CRM调用API Gateway公共端点,该端点再触发Lambda函数调用私有的SageMaker端点。然后,该函数通过API Gateway公共端点将分类结果返回给CRM。为了监控我们部署的模型的性能,我们在CRM和数据科学家之间建立了一个反馈循环,以跟踪模型的预测指标。每月,CRM更新用于实验和模型训练的历史数据。我们使用Amazon Managed Workflows for Apache Airflow(Amazon MWAA)作为我们每月重训练的调度程序。
在接下来的几个部分中,我们将详细介绍数据准备、模型实验和模型部署的步骤。
数据准备
Scalable Capital使用CRM工具来管理和存储电子邮件数据。相关的电子邮件内容包括主题、正文和托管银行。每封电子邮件需要分配三个标签:来自哪个业务线、适用于哪个队列以及电子邮件的具体主题。
在开始训练任何自然语言处理模型之前,我们会确保输入数据是干净的,并且标签是按预期分配的。
为了从Scalable的客户端中获取干净的查询内容,我们会从原始的电子邮件数据中删除额外的文本和符号,比如电子邮件签名、法律声明、之前邮件链中的引用、CSS符号等。否则,我们未来训练的模型可能会出现性能下降的情况。
随着Scalable客户服务团队添加新标签、优化或删除现有标签以适应业务需求,电子邮件的标签会随着时间而演变。为了确保训练数据的标签以及预测的分类是最新的,数据科学团队与客户服务团队密切合作,确保标签的正确性。
模型实验
我们从Hugging Face发布的现成的预训练distilbert-base-german-cased模型开始实验。由于预训练模型是一个通用的语言表示模型,我们可以通过将适当的头部附加到神经网络上来适应特定的下游任务,比如分类和问答。在我们的用例中,我们感兴趣的下游任务是序列分类。在不修改现有架构的情况下,我们决定为我们所需的每个类别分别微调三个单独的预训练模型。使用SageMaker Hugging Face Deep Learning Containers(DLCs),使用Hugging Face容器和SageMaker Experiments API可以简化NLP实验的启动和管理。
以下是train.py的代码片段:
config = AutoConfig.from_pretrained("distilbert-base-german-cased") # 加载原始配置
config.num_labels = num_labels # 根据特定的标签数调整原始配置(默认为2)
# 实例化预训练模型
model = DistilBertForSequenceClassification.from_pretrained("distilbert-base-german-cased", config=config)
trainer = Trainer(
model=model, # 要训练的已实例化的Transformers模型
args=training_args, # 训练参数,上面已定义
train_dataset=train_dataset, # 训练数据集
eval_dataset=val_dataset # 评估数据集
)
trainer.train()
以下代码是Hugging Face的估计器:
huggingface_estimator = HuggingFace(
entry_point='train.py',
source_dir='./scripts',
instance_type='ml.p3.2xlarge',
instance_count=1,
role=role,
transformers_version='4.26.0',
pytorch_version='1.13.1',
py_version='py39',
hyperparameters = hyperparameters
)
为了验证微调后的模型,我们使用F1分数,因为我们的电子邮件数据集存在不平衡的特点,同时计算其他指标,如准确率、精确率和召回率。为了让SageMaker Experiments API注册训练作业的指标,我们首先需要将指标记录到训练作业的本地控制台,然后由Amazon CloudWatch捕获。然后我们定义正确的正则表达式格式来捕获CloudWatch日志。指标定义包括指标的名称和从训练作业中提取指标的正则表达式验证:
metric_definitions = [
{"Name": "train:loss", "Regex": "'loss': ([0-9]+(.|e\-)[0-9]+),?"},
{"Name": "learning_rate", "Regex": "'learning_rate': ([0-9]+(.|e\-)[0-9]+),?"},
{"Name": "val:loss", "Regex": "'eval_loss': ([0-9]+(.|e\-)[0-9]+),?"},
{"Name": "train:accuracy", "Regex": "'train_accuracy': ([0-9]+(.|e\-)[0-9]+),?"},
{"Name": "val:accuracy", "Regex": "'eval_accuracy': ([0-9]+(.|e\-)[0-9]+),?"},
{"Name": "train:precision", "Regex": "'train_precision': ([0-9]+(.|e\-)[0-9]+),?"},
{"Name": "val:precision", "Regex": "'eval_precision': ([0-9]+(.|e\-)[0-9]+),?"},
{"Name": "train:recall", "Regex": "'train_recall': ([0-9]+(.|e\-)[0-9]+),?"},
{"Name": "val:recall", "Regex": "'eval_recall': ([0-9]+(.|e\-)[0-9]+),?"},
{"Name": "train:f1", "Regex": "'train_f1': ([0-9]+(.|e\-)[0-9]+),?"},
{"Name": "val:f1", "Regex": "'eval_f1': ([0-9]+(.|e\-)[0-9]+),?"},
{"Name": "val:runtime", "Regex": "'eval_runtime': ([0-9]+(.|e\-)[0-9]+),?"},
{"Name": "val:samples_per_second", "Regex": "'eval_samples_per_second': ([0-9]+(.|e\-)[0-9]+),?"},
{"Name": "epoch", "Regex": "'epoch': ([0-9]+(.|e\-)[0-9]+),?"},
]
作为分类器模型训练迭代的一部分,我们使用混淆矩阵和分类报告来评估结果。下图显示了线上业务预测的混淆矩阵。

混淆矩阵
下图显示了线上业务预测的分类报告示例。

分类报告
作为我们实验的下一个迭代,我们将利用多任务学习来改进我们的模型。多任务学习是一种模型同时学习解决多个任务的训练形式,因为任务之间共享的信息可以提高学习效率。通过在原始distilbert架构上附加两个以上的分类头,我们可以进行多任务微调,从而为我们的客户服务团队获得合理的度量指标。
模型部署
在我们的用例中,电子邮件分类器将被部署到一个端点,我们的CRM管道可以将一批未分类的电子邮件发送到该端点并获取预测结果。由于除了Hugging Face模型推断之外,我们还有其他逻辑,如输入数据清理和多任务预测,因此我们需要编写一个符合SageMaker标准的自定义推断脚本。
以下是inference.py的代码片段:
def model_fn(model_dir):
model = load_from_artifact(model_dir)
return model
def transform_fn(model, input_data, content_type, accept):
if content_type == "application/json":
data = json.loads(input_data)
data = pd.DataFrame(data)
else:
raise ValueError(f"不支持的内容类型:{content_type}")
data = preprocess(data)
# 推断
with torch.no_grad():
predictions = model(data)
predictions = postprocess(predictions)
if content_type == 'application/json':
return json.dumps(predictions.to_dict(orient="records"))
else:
raise NotImplementedError
当一切准备就绪时,我们使用SageMaker Pipelines来管理我们的训练管道,并将其附加到我们的基础架构中,以完成我们的MLOps设置。
为了监控部署模型的性能,我们建立了一个反馈循环,使CRM在关闭案例时向我们提供分类电子邮件的状态。根据这些信息,我们进行调整以改进部署的模型。
结论
在本文中,我们分享了SageMaker如何帮助可扩展的数据科学团队高效地管理数据科学项目的生命周期,即电子邮件分类器项目。生命周期始于使用SageMaker Studio进行数据分析和探索的初始阶段;随后使用SageMaker训练、推断和Hugging Face DLCs进行模型实验和部署;最后使用SageMaker Pipelines与其他AWS服务集成进行训练管道。多亏了这个基础架构,我们能够更高效地迭代和部署新的模型,从而改进可扩展内部和客户体验中的现有流程。
要了解有关Hugging Face和SageMaker的更多信息,请参考以下资源:
- 使用Hugging Face和Amazon SageMaker
- AWS深度学习容器是什么?
- 使用SageMaker Python SDK的2.x版本:框架:Hugging Face