使用 Transformer 和 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 应用中。