跳到主要内容

使用 Transformer 和 MLflow 进行翻译简介

下载此 Notebook

在本教程中,我们将深入探讨语言翻译的世界,利用 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 可确保模型有效处理较长的句子,这对于在翻译中保持上下文至关重要。

推断签名的重要性

签名定义了模型的输入和输出模式,对于 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 运行来启动记录过程。这将所有模型信息(包括artifact和参数)封装在一个唯一的运行 ID 中。

使用 mlflow.transformers.log_model

此函数是使用 MLflow 记录模型的关键。它记录了模型的各个方面:

  • 模型流水线:完整的翻译模型流水线,包括模型和分词器。
  • Artifact 路径:MLflow 运行中存储模型 artifact 的目录路径。
  • 模型签名:预定义的签名,指示模型的预期输入-输出格式。
  • 模型参数:模型的关键参数,如 max_length,提供对模型行为的洞察。

模型记录结果

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

with mlflow.start_run():
model_info = mlflow.transformers.log_model(
transformers_model=translation_pipeline,
artifact_path="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 中的模型风格(Flavor)

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

MLflow 中的风格(Flavor)代表了模型可以被利用和部署的不同方式。关键方面包括:

  • Python 函数风格(Python Function Flavor):表明模型兼容作为通用 Python 函数使用,包括模型二进制文件、加载器模块、Python 版本和环境规范。
  • Transformers 风格(Transformers Flavor):专为 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 与 Transformer 等先进语言模型的结合提供了一种强大的方法来部署复杂的 AI 解决方案。本教程旨在帮助您在机器学习之旅中取得成功,无论是在翻译任务还是其他 ML 应用中。