使用 Sentence Transformers 训练和微调多模态 Embedding 与 Reranker 模型
摘要
本文提供了使用 Sentence Transformers 库训练和微调多模态 Embedding 与 Reranker 模型的技术指南,展示了在基于 Qwen3-VL 的视觉文档检索任务上的性能提升。
查看缓存全文
缓存时间: 2026/05/08 09:06
使用 Sentence Transformers 训练和微调多模态 Embedding 与 Reranker 模型
来源:https://huggingface.co/blog/train-multimodal-sentence-transformers 返回文章列表 (https://huggingface.co/blog)
Tom Aarsen 的头像 (https://huggingface.co/tomaarsen)
- 目录 (https://huggingface.co/blog/train-multimodal-sentence-transformers#table-of-contents)
- 为什么要微调? (https://huggingface.co/blog/train-multimodal-sentence-transformers#why-finetune)
- 训练组件 (https://huggingface.co/blog/train-multimodal-sentence-transformers#training-components)
- 模型 (https://huggingface.co/blog/train-multimodal-sentence-transformers#model)
- 数据集 (https://huggingface.co/blog/train-multimodal-sentence-transformers#dataset)- 视觉文档检索数据集 (https://huggingface.co/blog/train-multimodal-sentence-transformers#visual-document-retrieval-dataset) - 数据集格式 (https://huggingface.co/blog/train-multimodal-sentence-transformers#dataset-format)
- 损失函数 (https://huggingface.co/blog/train-multimodal-sentence-transformers#loss-function)- CachedMultipleNegativesRankingLoss (https://huggingface.co/blog/train-multimodal-sentence-transformers#cachedmultiplenegativesrankingloss) - MatryoshkaLoss (https://huggingface.co/blog/train-multimodal-sentence-transformers#matryoshkaloss)
- 训练参数 (https://huggingface.co/blog/train-multimodal-sentence-transformers#training-arguments)
- 评估器 (https://huggingface.co/blog/train-multimodal-sentence-transformers#evaluator)
- 训练器 (https://huggingface.co/blog/train-multimodal-sentence-transformers#trainer)
- 结果 (https://huggingface.co/blog/train-multimodal-sentence-transformers#results)- 模型大小 vs NDCG@10 (https://huggingface.co/blog/train-multimodal-sentence-transformers#model-size-vs-ndcg10) - Matryoshka 维度 vs NDCG@10 (https://huggingface.co/blog/train-multimodal-sentence-transformers#matryoshka-dimensions-vs-ndcg10)
- 训练多模态 Reranker 模型 (https://huggingface.co/blog/train-multimodal-sentence-transformers#training-multimodal-reranker-models)
- 其他资源 (https://huggingface.co/blog/train-multimodal-sentence-transformers#additional-resources)- 训练示例 (https://huggingface.co/blog/train-multimodal-sentence-transformers#training-examples) - 文档 (https://huggingface.co/blog/train-multimodal-sentence-transformers#documentation) - 相关博客文章 (https://huggingface.co/blog/train-multimodal-sentence-transformers#companion-blogposts)
Sentence Transformers (https://sbert.net/) 是一个用于使用和训练 embedding 与 reranker 模型的 Python 库,适用于检索增强生成、语义搜索等应用。在我之前的博客文章 (https://huggingface.co/blog/multimodal-sentence-transformers) 中,我介绍了新的多模态功能,展示了如何使用能够处理文本、图像、音频和视频的 embedding 和 reranker 模型。在这篇文章中,我将向你展示如何训练或微调这些多模态模型,使用你自己的数据。
作为一个实际示例,我将演示如何微调 Qwen/Qwen3-VL-Embedding-2B (https://huggingface.co/Qwen/Qwen3-VL-Embedding-2B),用于视觉文档检索(Visual Document Retrieval, VDR)任务——即根据给定的文本查询,从大量文档中检索相关的文档页面(以图像形式保留图表、表格和版面布局)。最终得到的 tomaarsen/Qwen3-VL-Embedding-2B-vdr (https://huggingface.co/tomaarsen/Qwen3-VL-Embedding-2B-vdr) 展示了通过在特定领域数据上微调可以获得多大的性能提升。在我的评估数据上,微调后的模型 NDCG@10 达到 0.947,而基础模型仅为 0.888,并且超过了所有我测试过的现有 VDR 模型,包括那些体积是其 4 倍的模型。
VDR 模型的模型大小与 NDCG 对比 (https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/multimodal-sentence-transformers/vdr_plot.png)
如果你刚接触 Sentence Transformers 中的多模态模型,建议先阅读《使用 Sentence Transformers 的多模态 Embedding 与 Reranker 模型》(https://huggingface.co/blog/multimodal-sentence-transformers)。对于仅文本的 embedding、reranker 或稀疏 embedding 模型的训练,请参阅文末的往期博客文章 (https://huggingface.co/blog/train-multimodal-sentence-transformers#prior-blogposts) 部分。
https://huggingface.co/blog/train-multimodal-sentence-transformers#table-of-contents 目录
- 为什么要微调? (https://huggingface.co/blog/train-multimodal-sentence-transformers#why-finetune)
- 训练组件 (https://huggingface.co/blog/train-multimodal-sentence-transformers#training-components)
- 模型 (https://huggingface.co/blog/train-multimodal-sentence-transformers#model)
- 数据集 (https://huggingface.co/blog/train-multimodal-sentence-transformers#dataset)- 视觉文档检索数据集 (https://huggingface.co/blog/train-multimodal-sentence-transformers#visual-document-retrieval-dataset) - 数据集格式 (https://huggingface.co/blog/train-multimodal-sentence-transformers#dataset-format)
- 损失函数 (https://huggingface.co/blog/train-multimodal-sentence-transformers#loss-function)- CachedMultipleNegativesRankingLoss (https://huggingface.co/blog/train-multimodal-sentence-transformers#cachedmultiplenegativesrankingloss) - MatryoshkaLoss (https://huggingface.co/blog/train-multimodal-sentence-transformers#matryoshkaloss)
- 训练参数 (https://huggingface.co/blog/train-multimodal-sentence-transformers#training-arguments)
- 评估器 (https://huggingface.co/blog/train-multimodal-sentence-transformers#evaluator)
- 训练器 (https://huggingface.co/blog/train-multimodal-sentence-transformers#trainer)
- 结果 (https://huggingface.co/blog/train-multimodal-sentence-transformers#results)- 模型大小 vs NDCG@10 (https://huggingface.co/blog/train-multimodal-sentence-transformers#model-size-vs-ndcg10) - Matryoshka 维度 vs NDCG@10 (https://huggingface.co/blog/train-multimodal-sentence-transformers#matryoshka-dimensions-vs-ndcg10)
- 训练多模态 Reranker 模型 (https://huggingface.co/blog/train-multimodal-sentence-transformers#training-multimodal-reranker-models)
- 其他资源 (https://huggingface.co/blog/train-multimodal-sentence-transformers#additional-resources)- 往期博客文章 (https://huggingface.co/blog/train-multimodal-sentence-transformers#prior-blogposts) - 训练示例 (https://huggingface.co/blog/train-multimodal-sentence-transformers#training-examples) - 文档 (https://huggingface.co/blog/train-multimodal-sentence-transformers#documentation)
https://huggingface.co/blog/train-multimodal-sentence-transformers#why-finetune 为什么要微调?
像 Qwen/Qwen3-VL-Embedding-2B (https://huggingface.co/Qwen/Qwen3-VL-Embedding-2B) 这样的通用多模态 embedding 模型在多样化的数据上进行训练,以在广泛的语言和任务中表现良好:图像-文本匹配、视觉问答、文档理解等。但这种通用性意味着它很少是任何特定任务的最佳选择。
以视觉文档检索为例:给定一个文本查询如“公司第三季度的收入是多少?“,模型必须从成千上万的文档截图中找到最相关的页面。这需要理解文档布局、图表、表格和文本,这与匹配鞋子图片与产品描述等任务所需的技能截然不同。
通过在特定领域的数据上进行微调,模型可以学习这些专门的模式。在我的实验中,微调将 NDCG@10 从 0.888 提升到了 0.947,超过了我测试的每一个近期多模态模型,包括那些体积大 4 倍的模型。
https://huggingface.co/blog/train-multimodal-sentence-transformers#training-components 训练组件
训练多模态 Sentence Transformer 模型涉及与仅文本模型训练相同的组件:
- 模型 (https://huggingface.co/blog/train-multimodal-sentence-transformers#model):要训练或微调的多模态模型。
- 数据集 (https://huggingface.co/blog/train-multimodal-sentence-transformers#dataset):用于训练和评估的数据。
- 损失函数 (https://huggingface.co/blog/train-multimodal-sentence-transformers#loss-function):量化模型表现并指导优化过程的函数。
- 训练参数 (https://huggingface.co/blog/train-multimodal-sentence-transformers#training-arguments)(可选):影响训练性能和跟踪/调试的参数。
- 评估器 (https://huggingface.co/blog/train-multimodal-sentence-transformers#evaluator)(可选):在训练前、中、后评估模型的工具。
- 训练器 (https://huggingface.co/blog/train-multimodal-sentence-transformers#trainer):将模型、数据集、损失函数和其他组件整合起来进行训练。
多模态训练流程使用与仅文本训练相同的 SentenceTransformerTrainer (https://sbert.net/docs/package_reference/sentence_transformer/trainer.html#sentence_transformers.sentence_transformer.trainer.SentenceTransformerTrainer)。关键区别在于你的数据集包含图像(或其他模态)以及文本,并且模型的处理器会自动处理图像预处理。
让我们逐一介绍每个组件,以视觉文档检索(将文本查询与文档截图匹配)作为贯穿示例。
https://huggingface.co/blog/train-multimodal-sentence-transformers#model 模型
最常见的方法是微调现有的多模态 embedding 模型,或从视觉-语言模型(VLM)检查点开始。Transformer (https://sbert.net/docs/package_reference/base/modules.html#sentence_transformers.base.modules.Transformer) 模块会自动从模型的处理器中检测支持的模态。
要微调现有的多模态 embedding 模型(例如已经带有 modules.json 文件的模型),你可以传递 processor_kwargs 和 model_kwargs 来分别控制预处理和模型加载。processor_kwargs 直接传递给 AutoProcessor.from_pretrained(...) (https://huggingface.co/docs/transformers/model_doc/auto#transformers.AutoProcessor.from_pretrained)(例如图像分辨率限制:max_pixels 越高意味着质量越高但内存消耗越大),而 model_kwargs 传递给相应的 AutoModel.from_pretrained(...) (https://huggingface.co/docs/transformers/model_doc/auto#transformers.AutoModel.from_pretrained) 调用(例如精度、注意力实现):
from sentence_transformers import SentenceTransformer
model = SentenceTransformer(
"Qwen/Qwen3-VL-Embedding-2B",
model_kwargs={"attn_implementation": "flash_attention_2", "torch_dtype": "bfloat16"},
processor_kwargs={"min_pixels": 28 * 28, "max_pixels": 600 * 600},
)
你也可以从尚未用于 embedding 任务的全新 VLM 检查点开始。Sentence Transformers 会尝试识别架构,从处理器推断支持的模态,并设置适当的前向方法和池化。如果自动检测对某个特定模型不能完美工作,可以编辑保存的 sentence_bert_config.json 中的配置来调整模态设置、前向方法和输出处理:
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("Qwen/Qwen3-VL-2B")
在这两种情况下,Transformer (https://sbert.net/docs/package_reference/base/modules.html#sentence_transformers.base.modules.Transformer) 模块会检查处理器以确定可用的模态,并在需要时自动添加 Pooling (https://sbert.net/docs/package_reference/sentence_transformer/modules.html#sentence_transformers.sentence_transformer.modules.Pooling)。你可以验证支持的模态:
print(model.modalities)
# ['text', 'image', 'video', 'message']
print(model.supports("image"))
# True
替代方案:使用 Router 构建多模态模型除了使用单个 VLM 骨干网络,你还可以使用 Router (https://sbert.net/docs/package_reference/base/modules.html#sentence_transformers.base.modules.Router) 模块为不同模态组合单独的编码器。这让你可以结合任何现有编码器,并根据检测到的模态将输入路由到适当的编码器:
from sentence_transformers import SentenceTransformer
from sentence_transformers.sentence_transformer.modules import Dense, Pooling, Router, Transformer
# 为不同模态创建单独的编码器
text_encoder = Transformer("sentence-transformers/all-MiniLM-L6-v2")
text_pooling = Pooling(text_encoder.get_embedding_dimension(), pooling_mode="mean")
text_projection = Dense(text_encoder.get_embedding_dimension(), 768)
# SigLIP 直接输出池化后的 embedding,因此不需要单独的 Pooling 模块
image_encoder = Transformer("google/siglip2-base-patch16-224")
# 根据模态路由输入
router = Router(
sub_modules={
"text": [text_encoder, text_pooling, text_projection],
"image": [image_encoder],
},
)
model = SentenceTransformer(modules=[router])
由于基于 Router 的多模态模型使用每个模态的单独编码器,它们的 embedding 空间最初是未对齐的。需要进行训练来对齐空间以实现有意义的跨模态相似度。上面展示的
Dense投影层有助于将来自不同编码器的 embedding 映射到共享空间中。
当你想使用轻量级、专门的编码器而不是大型 VLM 时,这种方法很有用。你还可以将基于 Router 的多模态与基于任务的路由(例如查询与文档使用不同的编码器)结合使用,通过 route_mappings 实现。有关高级路由场景,请参阅 Router (https://sbert.net/docs/package_reference/base/modules.html#sentence_transformers.base.modules.Router) 文档。
https://huggingface.co/blog/train-multimodal-sentence-transformers#dataset 数据集
https://huggingface.co/blog/train-multimodal-sentence-transformers#visual-document-retrieval-dataset 视觉文档检索数据集
对于本示例,我使用 tomaarsen/llamaindex-vdr-en-train-preprocessed (https://huggingface.co/datasets/tomaarsen/llamaindex-vdr-en-train-preprocessed) 数据集,这是 llamaindex/vdr-multilingual-train (https://huggingface.co/datasets/llamaindex/vdr-multilingual-train) 的预处理英文子集。源数据集随 LlamaIndex 的《Visual Document Retrieval Goes Multilingual》(https://huggingface.co/blog/vdr-2b-multilingual) 博客文章一起发布,包含约 50 万条多语言查询-图像样本,收集自公共互联网 PDF,查询使用 VLM(gemini-1.5-pro 和 Qwen2-VL-72B)合成生成。我的预处理版本过滤出 53,512 条英文样本,并将每条样本中 16 个基于 ID 的难负例中的 4 个解析为实际的文档截图图像,因此可以直接用于训练而无需进一步预处理:
from datasets import load_dataset
train_dataset = load_dataset("tomaarsen/llamaindex-vdr-en-train-preprocessed", "train", split="train")
train_dataset = train_dataset.select_columns(["query", "image", "negative_0"])
eval_dataset = load_dataset("tomaarsen/llamaindex-vdr-en-train-preprocessed", "eval", split="train")
train 配置包含前 10,000 条样本,eval 配置包含接下来的 300 条样本(还有包含全部 53,512 条样本的 full 配置可用)。对于训练,我选择 query、image 和 negative_0 来构成(锚点、正例、难负例)三元组。包含额外的难负例可能会改善训练信号,但每个额外的负例也会增加内存使用和训练时间,因此我只使用一个。对于评估,我保留每个查询的所有四个难负例,以构建更具挑战性的检索场景。
相似文章
使用 Sentence Transformers 的多模态 Embedding 与 Reranker 模型
Sentence Transformers v5.4 引入了对多模态嵌入和重排序的支持,允许用户使用统一的 API 对文本、图像、音频和视频进行编码和比较。
Caraman 在 SemEval-2026 任务 8 中的表现:采用查询重写、混合检索和交叉编码器重排的多轮检索三阶段方法
本文介绍了一个用于 SemEval-2026 任务 8 的系统,该系统采用三阶段流水线,包括使用微调后的 Qwen 模型进行查询重写、混合检索以及交叉编码器重排,以提升多轮检索的性能。
针对《古兰经》语音识别的预训练Transformer模型比较研究:语音表示、标签格式与数据集构成
本文系统性地实证研究了针对《古兰经》自动语音识别(ASR)的预训练Transformer模型(Wav2Vec2.0、HuBERT、XLS-R)微调,在EveryAyah子集上实现了0.08的词错误率(WER),并将训练时间从140小时减少到40小时,其中Wav2Vec2-XLSR-53提供了最佳表示。
Qwen-Image-2.0-RL 技术报告
本技术报告介绍了 Qwen-Image-2.0-RL,这是一个基于强化学习与人类反馈及在策略蒸馏的后训练流程,旨在提升图像生成与编辑任务中的视觉质量和指令遵循能力。
利用自监督指南提升视觉指令调优
本文提出通过将自监督任务表达为自然语言指令,增强多模态语言模型中的视觉指令调优,从而在不增加架构或标注的情况下提升以视觉为中心的推理能力。通过将经典的自监督预文本任务(如旋转预测、颜色匹配和跨视角对应)重构为图像-指令-响应对,该方法仅需在训练数据中注入3%-10%的视觉化指令,便能在多个基准测试中实现一致的性能提升。