跳到主要内容

使用 Transformers 和 MLflow 进行翻译简介

下载此笔记本

在本教程中,我们将深入研究语言翻译领域,利用 Transformers 和 MLflow 的强大功能。本指南专为掌握机器学习概念并寻求简化其翻译模型工作流程的从业者而设计。我们将展示如何使用 MLflow 来记录、管理和服务最先进的翻译模型 - 来自 🤗 Hugging Face 库的 google/flan-t5-base

学习目标

在本教程中,您将

  • 使用 Transformers 库中的 flan-t5-base 构建翻译流水线
  • 使用 MLflow 记录翻译模型及其配置。
  • 自动确定翻译模型的输入和输出签名
  • 从 MLflow 检索已记录的翻译模型以进行直接交互。
  • 使用 MLflow 的 pyfunc 模型风味来模拟翻译模型的部署,以用于语言翻译任务。

在本教程结束时,您将深入了解如何使用 MLflow 管理和部署翻译模型,从而增强您用于语言处理的机器学习操作。

为什么选择此模型?

flan-t5-base 提供了一些优势

  • 大小:它是一个相对较小的模型,但具有相对强大的性能。
  • 增强的语言覆盖范围:在原始 T5 模型 的基础上,flan-t5 支持的语言范围更广。

设置翻译环境

首先使用 google/flan-t5-base 模型设置翻译任务的基本组件。

导入库

我们导入 transformers 库以访问翻译模型和分词器。此外,还包括 mlflow 用于模型跟踪和管理,从而为我们的翻译任务创建一个全面的环境。

初始化模型

google/flan-t5-base 模型以其翻译效果而闻名,它从 Hugging Face 存储库加载。此预训练模型是我们设置的关键组件。

设置分词器

我们初始化与我们的模型对应的分词器。分词器在处理文本输入方面起着关键作用,使模型能够理解它。

创建流水线

创建了从英语到法语的翻译流水线。此流水线简化了流程,使我们能够专注于输入文本和接收翻译,而无需直接管理模型和分词器的交互。

# Disable tokenizers warnings when constructing pipelines
%env TOKENIZERS_PARALLELISM=false

import warnings

# Disable a few less-than-useful UserWarnings from setuptools and pydantic
warnings.filterwarnings("ignore", category=UserWarning)
env: TOKENIZERS_PARALLELISM=false
import transformers

import mlflow

model_architecture = "google/flan-t5-base"

translation_pipeline = transformers.pipeline(
task="translation_en_to_fr",
model=transformers.T5ForConditionalGeneration.from_pretrained(
model_architecture, max_length=1000
),
tokenizer=transformers.T5TokenizerFast.from_pretrained(model_architecture, return_tensors="pt"),
)

测试翻译流水线

在通过 MLflow 记录翻译流水线之前,我们对其进行初步检查以确保其正常运行。

模型验证

测试翻译使我们能够验证模型是否准确地翻译文本,在本例中是从英语到法语,从而确保模型的基本功能。

预防错误

在模型记录之前识别潜在问题有助于防止部署或推理期间的未来错误,从而节省时间和资源。

资源管理

测试可以最大限度地减少资源的浪费使用,这对于这些模型的大尺寸以及保存和加载它们所需的资源尤为重要。

流水线验证

此步骤确认流水线中的模型和分词器都已正确配置,并且能够按预期处理输入。

# Evaluate the pipeline on a sample sentence prior to logging
translation_pipeline(
"translate English to French: I enjoyed my slow saunter along the Champs-Élysées."
)
[{'translation_text': "J'ai apprécié mon sajour lente sur les Champs-Élysées."}]

评估翻译结果

在通过流水线运行我们的初始翻译后,我们观察到输出虽然总体上准确,但在某些方面仍有改进的空间。

初始翻译输出为

    `[{'translation_text': "J'ai apprécié mon sajour lente sur les Champs-Élysées."}]`

此翻译捕获了原始英语句子的本质,但显示了细微的语法错误和措辞问题。例如,更精致的翻译可能是

    `"J'ai apprécié ma lente promenade le long des Champs-Élysées."`

此版本更正了语法性别并添加了必要的冠词、重音符号和连字符。这些细微的差别显着提高了翻译质量。基本模型的性能令人鼓舞,表明通过进一步的微调和上下文可以实现更精确的翻译。MLflow 的跟踪和管理功能将有助于监控此类模型的迭代改进。

总而言之,虽然在机器翻译中追求完美仍在继续,但最初的结果是朝着实现自然和准确的翻译迈出的有希望的一步。

设置模型参数和推断签名

我们建立关键的模型参数并推断签名,以确保模型部署的一致性和可靠性。

定义模型参数

设置像 max_length 这样的关键参数对于控制推理期间的模型行为至关重要。例如,max_length 为 1000 可确保模型有效地处理较长的句子,这对于在翻译中维护上下文至关重要。

推断签名 Importance

签名定义了模型的输入和输出模式,对于 MLflow 理解预期的数据结构至关重要。通过推断此签名,我们记录了模型使用的数据类型和结构,从而提高了其可靠性和可移植性。

此过程的优点

  • 增强的可移植性:正确定义的参数和签名使模型更适应不同的环境。
  • 减少错误:此步骤最大限度地降低了部署期间遇到与模式相关的错误的风险。
  • 清晰的文档:它为开发人员和用户提供了清晰的指南,简化了模型与应用程序的集成。

通过建立这些参数和签名,我们为我们的模型通过 MLflow 进行后续跟踪、管理和服务奠定了坚实的基础。

# Define the parameters that we are permitting to be used at inference time, along with their default values if not overridden
model_params = {"max_length": 1000}

# Generate the model signature by providing an input, the expected output, and (optionally), parameters available for overriding at inference time
signature = mlflow.models.infer_signature(
"This is a sample input sentence.",
mlflow.transformers.generate_signature_output(translation_pipeline, "This is another sample."),
params=model_params,
)

查看模型签名

在配置翻译模型并推断其签名后,至关重要的是查看签名以确认其与我们模型的输入和输出结构相匹配。

模型签名是 MLflow 与模型交互的蓝图,包括

  • 输入: 预期的输入类型,例如要翻译的文本的字符串。
  • 输出: 输出数据类型,在本例中是表示翻译文本的字符串。
  • 参数: 其他可配置的设置,例如 max_length,用于确定翻译输出的最大长度。

通过 signature 命令查看签名使我们能够验证数据格式,并确保我们的模型在部署时能够按预期运行。此步骤对于一致的模型性能和避免生产环境中的错误至关重要。此外,在具有默认值的签名中包含参数可确保推理期间的任何修改都是经过深思熟虑且有据可查的,从而有助于提高模型的可预测性和透明度。

# Visualize the model signature
signature
inputs: 
[string]
outputs: 
[string]
params: 
['max_length': long (default: 1000)]

创建实验

我们创建一个新的 MLflow 实验,以便我们要将模型记录到的运行不会记录到默认实验,而是具有其自己的上下文相关条目。

# If you are running this tutorial in local mode, leave the next line commented out.
# Otherwise, uncomment the following line and set your tracking uri to your local or remote tracking server.

# mlflow.set_tracking_uri("http://127.0.0.1:8080")

mlflow.set_experiment("Translation")
<Experiment: artifact_location='file:///Users/benjamin.wilson/repos/mlflow-fork/mlflow/docs/source/llms/transformers/tutorials/translation/mlruns/996217394074032926', creation_time=1701286351921, experiment_id='996217394074032926', last_update_time=1701286351921, lifecycle_stage='active', name='Translation', tags={}>

使用 MLflow 记录模型

我们现在已准备好使用 MLflow 记录我们的翻译模型,以确保其可跟踪性和版本控制。

启动 MLflow 运行

我们通过启动 MLflow 运行来启动日志记录过程。这会将所有模型信息(包括工件和参数)封装在唯一的运行 ID 中。

使用 mlflow.transformers.log_model

此函数对于在 MLflow 中记录我们的模型至关重要。它记录了模型的各个方面

  • 模型流水线:完整的翻译模型流水线,包括模型和分词器。
  • 工件路径:MLflow 运行中存储模型工件的目录路径。
  • 模型签名:预定义的签名,指示模型预期的输入-输出格式。
  • 模型参数:模型的关键参数,例如 max_length,用于深入了解模型行为。

模型记录的结果

记录后,我们获得 model_info 对象,该对象包含有关已记录模型的所有基本元数据,例如其存储位置。此元数据对于未来的部署和性能分析至关重要。

with mlflow.start_run():
model_info = mlflow.transformers.log_model(
transformers_model=translation_pipeline,
name="french_translator",
signature=signature,
model_params=model_params,
)

检查已加载的模型组件

从 MLflow 加载模型后,我们将深入研究其各个组件以验证其设置和功能。

组件细分

加载的模型包含几个关键组件,每个组件在其操作中都起着至关重要的作用

  • 任务:定义模型的特定用例,确认其适用于预期任务。
  • 设备映射:详细说明硬件配置,这对于性能优化非常重要。
  • 模型实例:核心 T5ForConditionalGeneration 模型,是翻译过程的核心。
  • 分词器T5TokenizerFast,负责将文本输入处理成模型可以理解的格式。
  • 框架:指示底层深度学习框架,这对于兼容性考虑至关重要。

确保组件的完整性和功能

检查这些组件可确保

  • 模型符合我们的任务要求。
  • 硬件资源得到优化利用。
  • 文本输入已正确预处理以供模型使用。
  • 确认模型与选定的深度学习框架的兼容性。

此验证步骤对于在实际场景中成功应用模型至关重要,从而增强了 MLflow 的稳健性和灵活性。

# Load our saved model as a dictionary of components, comprising the model itself, the tokenizer, and any other components that were saved
translation_components = mlflow.transformers.load_model(
model_info.model_uri, return_type="components"
)

# Show the components that made up our pipeline that we saved and what type each are
for key, value in translation_components.items():
print(f"{key} -> {type(value).__name__}")
2023/11/30 12:00:44 INFO mlflow.transformers: 'runs:/2357c12ca17a4f328b2f72cbb7d70343/french_translator' resolved as 'file:///Users/benjamin.wilson/repos/mlflow-fork/mlflow/docs/source/llms/transformers/tutorials/translation/mlruns/996217394074032926/2357c12ca17a4f328b2f72cbb7d70343/artifacts/french_translator'
Loading checkpoint shards:   0%|          | 0/2 [00:00<?, ?it/s]
task -> str
device_map -> str
model -> T5ForConditionalGeneration
tokenizer -> T5TokenizerFast
framework -> str

了解 MLflow 中的模型风味

MLflow 中的 model_info.flavors 属性提供了有关模型在各种平台上的功能和部署要求的见解。

MLflow 中的风味表示可以利用和部署模型的不同方式。关键方面包括

  • Python 函数风味: 指示模型作为通用 Python 函数的兼容性,包括模型二进制文件、加载器模块、Python 版本和环境规范。
  • Transformers 风味: 专为 Hugging Face Transformers 库中的模型量身定制,涵盖 transformers 版本、代码依赖项、任务、实例类型、源模型名称、流水线模型类型、框架、分词器类型、组件和模型二进制文件。

此信息指导如何在 MLflow 中与模型交互,确保使用正确的环境和依赖项进行正确部署,无论是用于推理还是进一步的模型优化。

# Show the model parameters that were saved with our model to gain an understanding of what is recorded when saving a transformers pipeline
model_info.flavors
{'python_function': {'model_binary': 'model',
'loader_module': 'mlflow.transformers',
'python_version': '3.8.13',
'env': {'conda': 'conda.yaml', 'virtualenv': 'python_env.yaml'}},
'transformers': {'transformers_version': '4.34.1',
'code': None,
'task': 'translation_en_to_fr',
'instance_type': 'TranslationPipeline',
'source_model_name': 'google/flan-t5-base',
'pipeline_model_type': 'T5ForConditionalGeneration',
'framework': 'pt',
'tokenizer_type': 'T5TokenizerFast',
'components': ['tokenizer'],
'model_binary': 'model'}}

评估翻译输出

在使用具有挑战性的句子测试我们的流水线后,我们评估翻译的准确性。

评估翻译细微差别

该模型令人印象深刻地将“Nice”正确地解释为城市名称,而不是形容词。这表明它能够辨别上下文和专有名词。此外,它巧妙地用法语形容词“bien”代替了英语双关语,从而保持了句子想要表达的情感。

上下文理解

此翻译例证了模型在理解上下文和语言细微差别方面的优势,这对于精度和上下文准确性至关重要的实际应用至关重要。

严格测试的重要性

使用语言复杂的句子进行测试至关重要。它可以确保模型能够处理各种语言挑战,这是在现实世界场景中部署模型的一个重要方面。

# Load our saved model as a transformers pipeline and validate the performance for a simple translation task
translation_pipeline = mlflow.transformers.load_model(model_info.model_uri)
response = translation_pipeline("I have heard that Nice is nice this time of year.")

print(response)
2023/11/30 12:00:45 INFO mlflow.transformers: 'runs:/2357c12ca17a4f328b2f72cbb7d70343/french_translator' resolved as 'file:///Users/benjamin.wilson/repos/mlflow-fork/mlflow/docs/source/llms/transformers/tutorials/translation/mlruns/996217394074032926/2357c12ca17a4f328b2f72cbb7d70343/artifacts/french_translator'
Loading checkpoint shards:   0%|          | 0/2 [00:00<?, ?it/s]
[{'translation_text': "J'ai entendu que Nice est bien cette période de l'année."}]

评估重建的流水线的翻译

我们现在评估从已加载组件重建的流水线的性能。

重建和测试

使用已加载组件的字典,我们成功地重建了一个新的翻译流水线。此步骤对于确认我们已记录和检索的组件在重新组装时是否能协同工作至关重要。

翻译质量

重建的流水线巧妙地将英语翻译成法语,同时保持了原始句子的句法准确性和语义连贯性。这反映了 Transformers 库简化复杂深度学习模型利用的能力。

验证模型完整性

此测试是验证已保存的模型及其组件不仅可检索而且在部署后有效运行的关键。它可以确保模型在实际应用中持续的完整性和性能。

# Verify that the components that we loaded can be constructed into a pipeline manually
reconstructed_pipeline = transformers.pipeline(**translation_components)

reconstructed_response = reconstructed_pipeline(
"transformers makes using Deep Learning models easy and fun!"
)

print(reconstructed_response)
[{'translation_text': "transformers simplifie l'utilisation des modèles de l'apprentissage profonde!"}]

直接利用模型组件

探索对各个模型组件的精细控制,以实现自定义翻译过程。

组件交互

与模型的各个组件进行交互可提供更深层次的自定义。当将模型集成到更大的系统中或需要对输入和输出进行特定操作时,此方法尤其有益。

深入了解模型结构

检查 translation_components 字典的键可以揭示我们模型的结构和组件。这包括任务、设备映射、核心模型、分词器和框架信息,每个信息对于翻译过程都至关重要。

组件级别控制的优点

单独利用组件可以进行精确调整和自定义集成。这是根据特定需求定制翻译过程的有效方法,可确保更好地控制模型的行为和输出。

# View the components that were saved with our model
translation_components.keys()
dict_keys(['task', 'device_map', 'model', 'tokenizer', 'framework'])

高级用法:与模型组件直接交互

与模型的组件直接交互为翻译中的高级用例提供了灵活性和控制。

与更高级别的流水线相比,直接使用模型和分词器组件可以实现

  • 自定义分词过程。
  • 特定的张量处理,包括设备规范(CPU、GPU、MPS 等)。
  • 动态生成和调整预测。
  • 使用后处理选项解码输出。

这种方法提供了精细的控制,可以对模型的操作进行干预,例如动态输入调整或输出后处理。但是,它也增加了复杂性,需要更深入地了解模型和分词器,并管理更多的代码。选择直接交互而不是流水线意味着在易用性与应用程序所需的控制级别之间取得平衡。这是一个至关重要的决定,尤其是在需要精确操作翻译过程的高级场景中。

# Access the individual components from the components dictionary
tokenizer = translation_components["tokenizer"]
model = translation_components["model"]

query = "Translate to French: Liberty, equality, fraternity, or death."

# This notebook was run on a Mac laptop, so we'll send the output tensor to the "mps" device.
# If you're running this on a different system, ensure that you're sending the tensor output to the appropriate device to ensure that
# the model is able to read it from memory.
inputs = tokenizer.encode(query, return_tensors="pt").to("mps")
outputs = model.generate(inputs).to("mps")
result = tokenizer.decode(outputs[0])

# Since we're not using a pipeline here, we need to modify the output slightly to get only the translated text.
print(result.replace("<pad> ", "
").replace("</s>", ""))
La liberté, l'égalité, la fraternité ou la mort.

教程回顾

本教程深入了解了 MLflow 与高级语言翻译模型的结合,强调了简化的模型管理和部署。

我们探讨了几个关键方面

  • 使用 Transformers 设置和测试翻译流水线。
  • 将模型及其配置记录到 MLflow,以实现有效的版本控制和跟踪。
  • 推断和检查模型的签名,以确保输入和输出的一致性。
  • 与已记录的模型组件交互,以增强部署的灵活性。
  • 讨论语言翻译的细微差别以及上下文在实现准确结果中的作用。

MLflow 和模型元数据的强大功能

事实证明,MLflow 的集成有助于管理和部署翻译模型。本教程重点介绍了 MLflow 的元数据(包括模型的签名和风味)如何帮助实现一致且可靠的部署,从而满足生产需求。

对翻译输出的反思

最终的翻译输出虽然不完全精确,但捕获了标志性的法语格言的精髓,突出了模型的有效性以及上下理解在翻译中的重要性。有关该短语的文化意义的更多探索,请参见其 维基百科页面

结论

MLflow 和高级语言模型(如 Transformers)的结合为部署复杂的 AI 解决方案提供了一种强大的方法。本教程旨在帮助您在机器学习领域的学习,无论是在翻译任务还是其他 ML 应用程序中。