跳到主要内容

使用 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 用于模型跟踪和管理,为我们的翻译任务创建了一个全面的环境。

初始化模型

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

设置分词器

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

创建管道

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

python
# 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
python
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 记录之前,我们对其进行初步检查,以确保其正常运行。

模型验证

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

错误预防

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

资源管理

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

管道验证

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

python
# 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."}]

评估翻译结果

在通过管道运行我们的初始翻译后,我们观察到输出虽然总体上是准确的,但存在一些需要改进的地方。

初始翻译输出为

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

此翻译抓住了原始英文句子精髓,但存在轻微的语法错误和词语选择问题。例如,更精炼的翻译可能是

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

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

总而言之,虽然在机器翻译中追求完美是一个持续的过程,但初步结果是实现自然准确翻译的有希望的一步。

设置模型参数并推断签名

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

定义模型参数

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

推断签名的重要性

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

此过程的好处

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

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

python
# 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 命令审查签名使我们能够验证数据格式,并确保模型在部署时的表现符合预期。此步骤对于模型性能的一致性和避免生产环境中的错误至关重要。此外,在签名中包含带有默认值的参数可确保推理期间的任何修改都是有意的且有据可查的,从而提高模型的预测性和透明度。

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

创建实验

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

python
# 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 对象,该对象包含有关已记录模型的所有重要元数据,例如其存储位置。这些元数据对于将来的部署和性能分析至关重要。

python
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 的健壮性和灵活性。

python
# 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 中与模型进行交互,确保使用正确的环境和依赖项进行适当的部署,无论是用于推理还是进一步的模型优化。

python
# 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”替换了英语的文字游戏,保持了句子原有的情感。

语境理解

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

严谨测试的重要性

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

python
# 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 库简化复杂深度学习模型使用的能力。

验证模型完整性

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

python
# 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 字典的键可以揭示我们模型的结构和组件。这包括任务、设备映射、核心模型、分词器和框架信息,这些信息对翻译过程都至关重要。

组件级别控制的好处

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

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

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

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

直接使用模型和分词器组件,而不是更高级别的管道,可以实现

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

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

python
# 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 的元数据(包括模型的签名和风格)如何有助于一致可靠的部署,满足生产需求。

反思翻译输出

最终的翻译输出虽然不完全相同,但却抓住了标志性法国格言的精髓,凸显了模型的有效性以及上下文理解在翻译中的重要性。您可以在其 Wikipedia 页面上找到有关该短语文化意义的进一步探讨。

结论

MLflow 和 Transformers 等高级语言模型的结合为部署复杂的 AI 解决方案提供了强大的方法。本教程旨在为您的机器学习之旅提供动力,无论是在翻译任务还是其他 ML 应用中。