跳到主要内容

使用 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 可确保模型有效处理较长的句子,这对于在翻译中保持上下文至关重要。

推断签名的重要性

签名定义了模型的输入和输出模式,对于 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 应用中)提供支持。