MLflow 和 Transformers 简介
欢迎来到我们的教程,学习如何利用 Transformers 与 MLflow 的强大功能。本指南专为初学者设计,重点关注机器学习工作流程和模型管理。
您将学到什么?
在本教程中,您将学习如何
- 使用 Transformers 库设置简单的文本生成流水线。
- 使用 MLflow 记录模型及其参数。
- 自动推断模型的输入和输出签名。
- 使用 MLflow 模拟模型服务并进行预测。
Transformers 简介
Transformers 是一种深度学习模型,彻底改变了自然语言处理(NLP)领域。由 🤗 Hugging Face 开发,Transformers 库为 NLP 任务提供了各种最先进的预训练模型。
为什么要将 MLflow 与 Transformers 结合使用?
将 MLflow 与 Transformers 集成具有诸多优势
- 实验跟踪:记录和比较模型参数及指标。
- 模型管理:跟踪不同的模型版本及其性能。
- 可复现性:记录复现预测所需的所有方面。
- 部署:简化将 Transformers 模型部署到生产环境的过程。
现在,让我们深入了解 MLflow 和 Transformers 的世界吧!
# 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
导入和流水线配置
在第一部分中,我们将设置环境并配置用于从大型语言模型(LLM)生成文本响应的 transformers 流水线相关方面。
设置流水线
- 导入:我们导入必要的库:用于构建 NLP 模型的 transformers 和用于模型跟踪及管理的 mlflow。
- 任务定义:然后我们定义流水线的任务,在本例中是
text2text-generation
。此任务涉及基于输入文本生成新文本。 - 流水线声明:接下来,我们使用 Transformers 库中的
pipeline
函数创建一个 generation_pipeline。此流水线配置为使用declare-lab/flan-alpaca-large model
,这是一个适合文本生成的预训练模型。 - 输入示例:为了稍后生成签名,以及在将模型加载为
pyfunc
时有一个模型预期输入数据的视觉指示器,我们接下来设置一个 input_example,其中包含示例提示词。 - 推理参数:最后,我们定义将在模型推理过程中用于控制模型行为的参数,例如生成文本的最大长度以及是否多次采样。
理解流水线
流水线是 Transformers 库提供的一种高级抽象,它简化了使用模型进行推理的过程。它们封装了底层代码的复杂性,为各种任务提供了直接的 API,例如文本分类、问答,以及我们案例中的文本生成。
pipeline()
函数
pipeline() 函数是一个多功能的工具,可用于为任何支持的任务创建流水线。当您指定一个任务时,该函数会返回一个为该任务量身定制的流水线对象,按照完成指定任务所需的顺序构建对子组件(分词器、编码器、生成模型等)的必要调用。这种抽象极大地简化了使用这些模型及其各自组件所需的代码。
任务特定的流水线
除了通用的 pipeline() 函数外,还有针对不同领域(如音频、计算机视觉和自然语言处理)的任务特定流水线。这些专用流水线针对各自的任务进行了优化,并能提供额外的便利性和功能。
使用流水线的好处
使用流水线有几个优点
- 简单性:只需少量代码即可执行复杂任务。
- 灵活性:您可以指定不同的模型和配置,根据您的需求定制流水线。
- 效率:流水线在内部处理批处理和数据集迭代,从而提高性能。
由于其实用性和简单的高级 API,MLflow 的 transformers
实现默认使用 pipeline
抽象(尽管它也支持仅组件模式)。
import transformers
import mlflow
# Define the task that we want to use (required for proper pipeline construction)
task = "text2text-generation"
# Define the pipeline, using the task and a model instance that is applicable for our task.
generation_pipeline = transformers.pipeline(
task=task,
model="declare-lab/flan-alpaca-large",
)
# Define a simple input example that will be recorded with the model in MLflow, giving
# users of the model an indication of the expected input format.
input_example = ["prompt 1", "prompt 2", "prompt 3"]
# Define the parameters (and their defaults) for optional overrides at inference time.
parameters = {"max_length": 512, "do_sample": True, "temperature": 0.4}
MLflow 中的模型签名简介
在机器学习领域,模型签名在确保模型接收和生成预期数据类型和结构方面起着至关重要的作用。MLflow 包含一个用于定义模型签名的功能,有助于标准化和强制执行正确的模型使用。
要点速览
- 模型签名目的:确保模型输入和输出的数据类型和结构一致。
- 可见性和验证:在 MLflow 的 UI 中可见,并由 MLflow 的部署工具验证。
- 签名类型:基于列(用于表格数据)、基于张量(用于张量输入/输出),以及带参数(用于需要额外推理参数的模型)。
理解模型签名
MLflow 中的模型签名描述了机器学习模型输入、输出和参数的 schema。它是一个详细说明预期数据类型和形状的蓝图,有助于为模型使用提供清晰的接口。签名特别有用,因为它们是
- 在 MLflow 的 UI 中显示,方便参考。
- 由 MLflow 的部署工具用于在推理过程中验证输入。
- 与模型的元数据一起以标准化的 JSON 格式存储。
签名在代码中的作用
在下一节中,我们将使用 MLflow 推断机器学习模型的签名。这包括指定一个输入示例、生成一个模型输出示例,以及定义任何额外的推理参数。生成的签名用于验证未来的输入并记录预期的数据格式。
模型签名类型
模型签名可以是
- 基于列:适用于处理表格数据的模型,每列具有指定的数据类型和可选名称。
- 基于张量:专为接受张量作为输入和输出的模型设计,每个张量具有指定的数据类型、形状和可选名称。
- 带参数:某些模型需要额外的推理参数,这些参数也可以包含在签名中。
对于 transformers flavor,所有输入类型都是基于列的类型(在 MLflow 中称为 ColSpec
类型)。
签名强制执行
MLflow 在模型推理时强制执行签名,确保提供的输入和参数与预期的 schema 匹配。如果存在不匹配,MLflow 将根据不匹配的性质抛出异常或发出警告。
# Generate the signature for the model that will be used for inference validation and type checking (as well as validation of parameters being submitted during inference)
signature = mlflow.models.infer_signature(
input_example,
mlflow.transformers.generate_signature_output(generation_pipeline, input_example),
parameters,
)
# Visualize the signature
signature
inputs: [string] outputs: [string] params: ['max_length': long (default: 512), 'do_sample': boolean (default: True), 'temperature': double (default: 0.4)]
创建实验
我们创建一个新的 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("Transformers Introduction")
<Experiment: artifact_location='file:///Users/benjamin.wilson/repos/mlflow-fork/mlflow/docs/source/llms/transformers/tutorials/text-generation/mlruns/528654983476503755', creation_time=1701288466448, experiment_id='528654983476503755', last_update_time=1701288466448, lifecycle_stage='active', name='Transformers Introduction', tags={}>
使用 MLflow 记录 Transformers 模型
我们使用 MLflow 记录模型,以有效地管理其生命周期并跟踪其版本和配置。
在 MLflow 中记录模型是模型生命周期管理中的关键步骤,可以实现高效的跟踪、版本控制和管理。该过程涉及在 MLflow 跟踪系统中注册模型及其必要的元数据。
利用 mlflow.transformers.log_model 函数,该函数专为 transformers
库中的模型和组件定制,简化了此任务。此函数擅长处理该库中模型的各个方面,包括其复杂的流水线和配置。
记录模型时,会包含关键元数据,例如先前建立的模型签名。这些元数据在模型生命周期的后续阶段(从跟踪其演变到促进其在不同环境中的部署)中发挥着重要作用。特别是签名,确保了模型在各种平台上的兼容性和一致性能,从而增强了其在实际应用中的实用性和可靠性。
通过以这种方式记录我们的模型,我们确保它不仅有完善的文档,而且为将来使用做好了准备,无论是用于进一步开发、比较分析还是部署。
节省存储成本的技巧
调用 mlflow.transformers.log_model 时,MLflow 会保存 Transformers 模型权重的完整副本。然而,这可能会占用大量存储空间(对于 flan-alpaca-large
模型为 3GB),而且在您不修改模型权重时可能显得冗余,因为它与您可以从 HuggingFace 模型中心下载的模型权重完全相同。
为避免不必要的复制,您可以使用 MLflow 2.11.0 中引入的“仅引用”保存模式,方法是在记录或保存 Transformer 模型时将 save_pretrained=False
。这会告诉 MLflow 不保存基础模型的权重副本,而只保存对 HuggingFace Hub 仓库和版本的引用,从而更节省存储空间且速度更快。有关此功能的更多详细信息,请参阅存储高效的模型记录。
with mlflow.start_run():
model_info = mlflow.transformers.log_model(
transformers_model=generation_pipeline,
artifact_path="text_generator",
input_example=input_example,
signature=signature,
# Transformer model does not use Pandas Dataframe as input, internal input type conversion should be skipped.
example_no_conversion=True,
# Uncomment the following line to save the model in 'reference-only' mode:
# save_pretrained=False,
)
加载文本生成模型
我们使用 MLflow 的 pyfunc
模块初始化文本生成模型,以便进行无缝的模型加载和交互。
MLflow 中的 pyfunc
模块充当 Python 函数的通用包装器。它在 MLflow 中的应用促进了将机器学习模型作为标准 Python 函数加载。这种方法对于通过 MLflow 记录或注册的模型特别有利,无论其训练或序列化细节如何,都可以简化与模型的交互。
利用 mlflow.pyfunc.load_model,我们可以使用其唯一的模型 URI 加载之前记录的文本生成模型。此 URI 是对存储的模型 artifact 的引用。MLflow 高效地处理模型的反序列化以及任何相关的依赖项,使其可立即使用。
一旦模型(在此称为 sentence_generator
)加载完成,它就像一个常规的 Python 函数一样运行。此功能允许基于给定的提示词生成文本。该模型包含完整的推理过程,无需手动进行输入预处理或输出后处理。这种封装不仅简化了模型交互,还确保了模型适用于在各种平台上部署。
# Load our pipeline as a generic python function
sentence_generator = mlflow.pyfunc.load_model(model_info.model_uri)
Loading checkpoint shards: 0%| | 0/7 [00:00<?, ?it/s]
格式化预测结果以提高教程可读性
请注意,以下函数 format_predictions
仅用于增强此 Jupyter Notebook 环境中模型预测结果的可读性。它不是模型推理流水线的标准组件。
def format_predictions(predictions):
"""
Function for formatting the output for readability in a Jupyter Notebook
"""
formatted_predictions = []
for prediction in predictions:
# Split the output into sentences, ensuring we don't split on abbreviations or initials
sentences = [
sentence.strip() + ("." if not sentence.endswith(".") else "")
for sentence in prediction.split(". ")
if sentence
]
# Join the sentences with a newline character
formatted_text = "
".join(sentences)
# Add the formatted text to the list
formatted_predictions.append(formatted_text)
return formatted_predictions
使用自定义参数生成预测结果
在本节中,我们将演示如何使用带有自定义参数的句子生成器模型生成预测结果。这包括选择周末活动和请求笑话的提示词。
快速概览
- 场景:为不同的提示词生成文本。
- 自定义参数:覆盖
temperature
参数以控制文本随机性。 - 默认值:除非明确覆盖,否则其他参数使用其默认值。
预测过程解释
我们使用 sentence_generator
pyfunc 模型的 predict
方法,传入一个字符串提示词列表,其中包括
- 请求帮助在周末活动中选择徒步或皮划艇。
- 一个关于徒步的笑话提示词。
为了影响生成过程,我们覆盖了 temperature
参数。此参数影响生成文本的随机性
- 较低的温度:导致更可预测和保守的输出。
- 较高的温度:促进多样化和创造性的响应。
利用自定义参数
在此示例中,temperature
参数在预测调用中被显式设置。模型记录期间设置的其他参数将使用其默认值,除非也在预测调用的 params
参数中被覆盖。
输出格式化
predictions
变量捕获模型对每个输入提示词的输出。我们可以在后续步骤中格式化这些输出以增强可读性,以清晰易懂的方式呈现生成的文本。
# Validate that our loaded pipeline, as a generic pyfunc, can produce an output that makes sense
predictions = sentence_generator.predict(
data=[
"I can't decide whether to go hiking or kayaking this weekend. Can you help me decide?",
"Please tell me a joke about hiking.",
],
params={"temperature": 0.7},
)
# Format each prediction for notebook readability
formatted_predictions = format_predictions(predictions)
for i, formatted_text in enumerate(formatted_predictions):
print(f"Response to prompt {i + 1}:
{formatted_text}
")
2023/11/30 14:24:08 WARNING mlflow.transformers: params provided to the `predict` method will override the inference configuration saved with the model. If the params provided are not valid for the pipeline, MlflowException will be raised.
Response to prompt 1: Going hiking can be a great way to explore the outdoors and have fun, while kayaking can be an exciting way to take in the scenery and have a great experience. Response to prompt 2: Q: What did the bird say when he was walking in the woods? a: "Hey, I'm going to get some food!".
结束语
本次演示展示了模型在生成与上下文相关且富有创意的文本响应方面的灵活性和强大功能。通过格式化输出,我们确保结果不仅准确,而且以易于阅读和理解的方式呈现,从而增强了此 Jupyter Notebook 环境中的整体用户体验。