跳到主要内容

Sentence Transformers 和 MLflow 高级语义相似度分析简介

下载此笔记本

通过本综合教程,深入了解使用 Sentence Transformers 和 MLflow 进行的高级语义相似度分析。

学习目标

  • 配置 sentence-transformers 以进行语义相似度分析。
  • 探索 MLflow 中的自定义 PythonModel 实现。
  • 使用 MLflow 记录模型并管理配置。
  • 使用 MLflow 的功能部署模型并将其应用于推理。

揭示 Sentence Transformers 在 NLP 中的强大功能

Sentence Transformers 是 Transformer 模型的专门改编版本,擅长生成语义丰富的句子嵌入。 这些模型非常适合语义搜索和相似度分析,为 NLP 任务带来更深层次的语义理解。

MLflow:引领灵活的模型管理和部署

MLflow 与 Sentence Transformers 的集成引入了增强的实验跟踪和灵活的模型管理,这对于 NLP 项目至关重要。 学习在 MLflow 中实现自定义 PythonModel,扩展满足独特需求的功能。

在本教程中,您将获得使用 MLflow 管理和部署复杂 NLP 模型的实践经验,从而提高您在语义相似度分析和模型生命周期管理方面的技能。

# 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

使用 MLflow 实现自定义 SimilarityModel

了解如何使用 MLflow 的 PythonModel 创建自定义 SimilarityModel 类,以评估句子之间的语义相似度。

SimilarityModel 概述

SimilarityModel 是一个定制的 Python 类,它利用 MLflow 灵活的 PythonModel 接口。 它专门用于封装使用复杂的句子嵌入计算句子对之间语义相似度的复杂性。

自定义模型的关键组件

  • 导入库: 从 MLflow、数据处理和 Sentence Transformers 导入必要的库,以方便模型的功能。
  • 自定义 PythonModel - SimilarityModel:
    • load_context 方法侧重于高效且安全的模型加载,这对于处理像 Sentence Transformers 这样的复杂模型至关重要。
    • predict 方法配备了输入类型检查和错误处理功能,可确保模型提供准确的余弦相似度评分,从而反映语义相关性。

自定义 SimilarityModel 的重要性

  • 灵活性和自定义: 模型的设计允许对输入和输出进行专门处理,与语义相似度任务的独特需求完美契合。
  • 强大的错误处理: 详细的输入类型检查可确保用户友好的体验,防止常见的输入错误并确保模型行为的可预测性。
  • 高效的模型加载: 有策略地使用 load_context 方法进行模型初始化可避免序列化挑战,从而确保平稳的运营流程。
  • 目标功能: 自定义 predict 方法直接计算相似度评分,展示了模型提供特定于任务的可操作见解的能力。

这种自定义的 SimilarityModel 例证了 MLflow 的 PythonModel 在创建定制的 NLP 解决方案方面的适应性,为各种机器学习项目中的类似努力树立了先例。

import numpy as np
import pandas as pd
from sentence_transformers import SentenceTransformer, util

import mlflow
from mlflow.models.signature import infer_signature
from mlflow.pyfunc import PythonModel


class SimilarityModel(PythonModel):
def load_context(self, context):
"""Load the model context for inference."""
from sentence_transformers import SentenceTransformer

try:
self.model = SentenceTransformer.load(context.artifacts["model_path"])
except Exception as e:
raise ValueError(f"Error loading model: {e}")

def predict(self, context, model_input, params):
"""Predict method for comparing similarity between two sentences."""
from sentence_transformers import util

if isinstance(model_input, pd.DataFrame):
if model_input.shape[1] != 2:
raise ValueError("DataFrame input must have exactly two columns.")
sentence_1, sentence_2 = model_input.iloc[0, 0], model_input.iloc[0, 1]
elif isinstance(model_input, dict):
sentence_1 = model_input.get("sentence_1")
sentence_2 = model_input.get("sentence_2")
if sentence_1 is None or sentence_2 is None:
raise ValueError(
"Both 'sentence_1' and 'sentence_2' must be provided in the input dictionary."
)
else:
raise TypeError(
f"Unexpected type for model_input: {type(model_input)}. Must be either a Dict or a DataFrame."
)

embedding_1 = self.model.encode(sentence_1)
embedding_2 = self.model.encode(sentence_2)

return np.array(util.cos_sim(embedding_1, embedding_2).tolist())

准备 Sentence Transformer 模型和签名

探索使用 MLflow 设置 Sentence Transformer 模型以进行日志记录和部署的必要步骤。

加载和保存预训练模型

  • 模型初始化: 加载预训练的 Sentence Transformer 模型 "all-MiniLM-L6-v2",因为它在生成适合各种 NLP 任务的高质量嵌入方面效率很高。
  • 模型保存: 该模型保存在本地 /tmp/sbert_model 中,以便 MLflow 轻松访问,这是在该平台中进行模型日志记录的先决条件。

准备输入示例和工件

  • 创建输入示例: 准备包含示例句子的 DataFrame,表示典型的模型输入并有助于定义模型的输入格式。
  • 定义工件: 已保存模型的文件夹路径在 MLflow 中被指定为工件,这是将模型与 MLflow 运行相关联的关键步骤。

生成签名的测试输出

  • 计算测试输出: 计算句子嵌入之间的余弦相似度,从而提供该模型输出的实际示例。
  • 签名推理: MLflow 的 infer_signature 函数用于生成一个签名,该签名封装了预期的输入和输出格式,从而加强了模型的运营架构。

这些步骤的重要性

  • 模型就绪: 这些准备步骤可确保模型已准备好在 MLflow 生态系统中进行高效的日志记录和无缝部署。
  • 输入-输出合同: 建立的签名充当一个明确的合同,定义了模型的输入-输出动态,这对于在部署方案中保持一致性和准确性至关重要。

在精心准备好 Sentence Transformer 模型及其签名后,我们现在已做好充分准备,可以推进其在 MLflow 中的集成和管理。

# Load a pre-trained sentence transformer model
model = SentenceTransformer("all-MiniLM-L6-v2")

# Create an input example DataFrame
input_example = pd.DataFrame([{"sentence_1": "I like apples", "sentence_2": "I like oranges"}])

# Save the model in the /tmp directory
model_directory = "/tmp/sbert_model"
model.save(model_directory)

# Define artifacts with the absolute path
artifacts = {"model_path": model_directory}

# Generate test output for signature
test_output = np.array(
util.cos_sim(
model.encode(input_example["sentence_1"][0]), model.encode(input_example["sentence_2"][0])
).tolist()
)

# Define the signature associated with the model
signature = infer_signature(input_example, test_output)

# Visualize the signature
signature
inputs: 
['sentence_1': string, 'sentence_2': string]
outputs: 
[Tensor('float64', (-1, 1))]
params: 
None

创建实验

我们创建一个新的 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("Semantic Similarity")
<Experiment: artifact_location='file:///Users/benjamin.wilson/repos/mlflow-fork/mlflow/docs/source/llms/sentence-transformers/tutorials/semantic-similarity/mlruns/577235153137414660', creation_time=1701280997564, experiment_id='577235153137414660', last_update_time=1701280997564, lifecycle_stage='active', name='Semantic Similarity', tags={}>

使用 MLflow 记录自定义模型

了解如何使用 MLflow 记录自定义 SimilarityModel,以实现有效的模型管理和部署。

为 PyFunc 模型创建路径

我们建立 pyfunc_path,这是 Python 模型的临时存储位置。 对于 MLflow 有效地序列化和存储模型来说,此路径至关重要。

在 MLflow 中记录模型

  • 启动 MLflow 运行: 启动 MLflow 运行,将所有模型日志记录过程封装在结构化框架内。
  • 模型日志记录详细信息: 该模型被标识为 "similarity",从而为将来的模型检索和分析提供清晰的参考。 记录 SimilarityModel 的一个实例,封装 Sentence Transformer 模型和相似度预测逻辑。 一个说明性的 DataFrame 演示了预期的模型输入格式,有助于用户理解和模型可用性。 推理的签名详细描述了输入-输出模式,从而加强了模型的正确用法。 工件字典指定了序列化的 Sentence Transformer 模型的位置,这对于模型重建至关重要。 列出了像 sentence_transformersnumpy 这样的依赖项,从而确保模型在各种部署环境中的功能完整性。

模型日志记录的重要性

  • 模型跟踪和版本控制: 日志记录有助于全面的跟踪和有效的版本控制,从而增强模型生命周期管理。
  • 可重现性和部署: 记录的模型及其依赖项、输入示例和签名均变得易于重现和部署,从而促进了跨环境的一致应用。

在 MLflow 中记录我们的 SimilarityModel 之后,它已准备好用于高级应用程序,例如比较分析、版本管理和部署以用于实际推理用例。

pyfunc_path = "/tmp/sbert_pyfunc"

with mlflow.start_run() as run:
model_info = mlflow.pyfunc.log_model(
name="similarity",
python_model=SimilarityModel(),
input_example=input_example,
signature=signature,
artifacts=artifacts,
pip_requirements=["sentence_transformers", "numpy"],
)
Downloading artifacts:   0%|          | 0/11 [00:00<?, ?it/s]
2023/11/30 16:10:34 INFO mlflow.store.artifact.artifact_repo: The progress bar can be disabled by setting the environment variable MLFLOW_ENABLE_ARTIFACTS_PROGRESS_BAR to false

模型推理和测试相似度预测

演示在通过 MLflow 记录 SimilarityModel 后,如何使用该模型来计算句子之间的语义相似度。

加载模型进行推理

  • 使用 MLflow 加载: 将 mlflow.pyfunc.load_model 与模型的 URI 一起使用,以加载自定义的 SimilarityModel 进行推理。
  • 模型就绪: 加载的模型(名为 loaded_dynamic)配备了 SimilarityModel 中定义的逻辑,并且已准备好计算相似度。

准备数据以进行相似度预测

  • 创建输入数据: 构建一个 DataFrame similarity_data,其中包含将为其计算相似度的句子对,从而展示模型的输入灵活性。

计算并显示相似度评分

  • 预测相似度: 在 loaded_dynamic 上调用 predict 方法与 similarity_data,以计算句子嵌入之间的余弦相似度。
  • 解释结果: 生成的 similarity_score 在数值上表示语义相似度,从而提供有关模型输出的即时见解。

此测试的重要性

  • 模型验证: 确认自定义模型在预测新数据时的预期行为,确保其有效性。
  • 实际应用: 突出显示模型在现实场景中的实际效用,展示其在语义相似度分析中的能力。
# Load our custom semantic similarity model implementation by providing the uri that the model was logged to
loaded_dynamic = mlflow.pyfunc.load_model(model_info.model_uri)

# Create an evaluation test DataFrame
similarity_data = pd.DataFrame([{"sentence_1": "I like apples", "sentence_2": "I like oranges"}])

# Verify that the model generates a reasonable prediction
similarity_score = loaded_dynamic.predict(similarity_data)

print(f"The similarity between these sentences is: {similarity_score}")
The similarity between these sentences is: [[0.63414472]]

评估具有不同文本对的语义相似度

探索模型区分具有精心选择的文本对的不同程度语义相似度的能力。

文本对的选择

  • 低相似度对: 句子中不同的主题预示着低的相似度评分,展示了模型识别对比语义内容的能力。
  • 高相似度对: 具有相似主题和语气的句子预计会具有高的相似度评分,展示了模型语义并行检测的能力。

sBERT 模型在相似度计算中的作用

  • 语义理解: 利用 sBERT 将语义本质编码为向量。
  • 余弦相似度: 计算相似度评分以量化语义接近度。

计算并显示相似度评分

  • 预测低相似度对: 观察模型对语义距离较远的句子的解释。
  • 预测高相似度对: 评估模型检测上下文中相关句子中语义相似度的能力。

为何重要

  • 模型验证: 这些测试证实了模型对语言的细微理解和语义关系量化。
  • 实际意义: 从模型对语义内容的处理中获得的见解可为内容推荐、信息检索和文本比较中的应用程序提供信息。
low_similarity = {
"sentence_1": "The explorer stood at the edge of the dense rainforest, "
"contemplating the journey ahead. The untamed wilderness was "
"a labyrinth of exotic plants and unknown dangers, a challenge "
"for even the most seasoned adventurer, brimming with the "
"prospect of new discoveries and uncharted territories.",
"sentence_2": "To install the software, begin by downloading the latest "
"version from the official website. Once downloaded, run the "
"installer and follow the on-screen instructions. Ensure that "
"your system meets the minimum requirements and agree to the "
"license terms to complete the installation process successfully.",
}

high_similarity = {
"sentence_1": "Standing in the shadow of the Great Pyramids of Giza, I felt a "
"profound sense of awe. The towering structures, a testament to "
"ancient ingenuity, rose majestically against the clear blue sky. "
"As I walked around the base of the pyramids, the intricate "
"stonework and sheer scale of these wonders of the ancient world "
"left me speechless, enveloped in a deep sense of history.",
"sentence_2": "My visit to the Great Pyramids of Giza was an unforgettable "
"experience. Gazing upon these monumental structures, I was "
"captivated by their grandeur and historical significance. Each "
"step around these ancient marvels filled me with a deep "
"appreciation for the architectural prowess of a civilization long "
"gone, yet still speaking through these timeless monuments.",
}

# Validate that semantically unrelated texts return a low similarity score
low_similarity_score = loaded_dynamic.predict(low_similarity)

print(f"The similarity score for the 'low_similarity' pair is: {low_similarity_score}")

# Validate that semantically similar texts return a high similarity score
high_similarity_score = loaded_dynamic.predict(high_similarity)

print(f"The similarity score for the 'high_similarity' pair is: {high_similarity_score}")
The similarity score for the 'low_similarity' pair is: [[-0.00052751]]
The similarity score for the 'high_similarity' pair is: [[0.83703309]]

结论:利用自定义 MLflow Python 函数在 NLP 中的强大功能

在我们结束本教程时,让我们回顾一下在使用 Sentence Transformers 和 MLflow 理解和应用高级 NLP 技术方面取得的重大进展。

本教程的主要收获

  • 多功能 NLP 建模: 我们探索了如何利用 Sentence Transformers 的高级功能进行语义相似度分析,这是许多 NLP 应用程序中的一项关键任务。
  • 自定义 MLflow Python 函数: 在 MLflow 中实现自定义的 SimilarityModel,展示了使用 Python 函数扩展和调整预训练模型的功能以适应特定项目需求的强大功能和灵活性。
  • 模型管理和部署: 我们深入研究了使用 MLflow 记录、管理和部署这些模型的过程,展示了 MLflow 如何简化机器学习生命周期的这些方面。
  • 实际语义分析: 通过实践示例,我们展示了该模型区分句子对之间不同程度语义相似度的能力,从而验证了其在实际语义分析任务中的有效性。

MLflow Python 函数的强大功能和灵活性

  • 针对特定需求进行自定义: 本教程的重点之一是演示如何自定义 MLflow 的 PythonModel。 这种自定义不仅功能强大,而且对于根据超出标准模型功能的特定 NLP 任务定制模型也是必要的。
  • 适应性和扩展性: MLflow 中的 PythonModel 框架为实现各种 NLP 模型提供了坚实的基础。 其适应性允许扩展基础模型功能,例如将句子嵌入模型转换为语义相似度比较工具。

增强高级 NLP 应用程序

  • 易于修改: 本教程展示了可以相对容易地修改提供的 PythonModel 实现以适应 MLflow 中的不同风格,从而使您能够创建与您的项目要求完全一致的模型。
  • 广泛的适用性: 无论是语义搜索、内容推荐还是自动文本比较,本教程中概述的方法都可以应用于广泛的 NLP 任务,从而为该领域的创新应用打开了大门。

前进

凭借在本教程中获得的知识和技能,您现在已做好充分准备,可以将这些高级 NLP 技术应用于您的项目。 Sentence Transformers 与 MLflow 强大的模型管理和部署功能的无缝集成,为开发复杂、高效且有效的 NLP 解决方案铺平了道路。

感谢您加入我们,与 Sentence Transformers 和 MLflow 一起完成本次高级 NLP 建模之旅。 我们希望本教程能激发您进一步探索并在您的 NLP 工作中进行创新!

快乐建模!