首页
/ Transformers 中 ModernVBert 视觉-语言编码器全解析:从 ModernBert + SigLIP 架构到掩码视觉语言推理实践

Transformers 中 ModernVBert 视觉-语言编码器全解析:从 ModernBert + SigLIP 架构到掩码视觉语言推理实践

2026-09-07 13:44:08作者:郜逊炳

导读

ModernVBert 是 Hugging Face Transformers(本仓库)中一款面向视觉文档理解与检索场景的视觉-语言(Vision-Language)编码器模型,它将 ModernBert 文本编码器与 SigLIP 视觉编码器组合为统一的双塔结构,并创新性地通过 pixel shuffle 连接器(Connector) 将图像 patch 特征压缩投影到文本嵌入空间,使文本 token 可以在纯 MLM 式目标下直接"看见"图片内容。本文以 官方模型文档 为核心骨架,结合本仓库 modernvbert 源码目录测试套件 进行源码级展开。读完本文,你将掌握:ModernVBert 的整体架构与运行链路、ModernVBertConfig 全部关键配置项的真实含义与默认值、利用 ModernVBertForMaskedLM 做图文融合掩码预测的完整可运行代码,以及如何将该模型接入文本分类、词元分类等下游任务。


一、模型是什么:为视觉文档检索而生的双编码器

依据 官方模型文档 的 Overview,ModernVBert 是一个 Vision-Language encoder

  • 文本侧:复用 ModernBert 编码器,负责对 OCR/文档文本与视觉占位 token 的融合序列建模;
  • 视觉侧:复用 SigLIP 视觉编码器,负责从原始像素提取图像 patch 表征;
  • 优化目标:视觉文档理解(visual document understanding)与检索(retrieval)任务。

模型出自论文 ModernVBERT: Towards Smaller Visual Document Retrievers。同时,从 源码类注释 可以看到一句关键信息:ModernVBert 是视觉检索器 ColModernVBert 的基础模型——本仓库也确实存在 colmodernvbert 模型模块及其对应的 ColModernVBertForRetrieval 自动映射(见 modeling_auto.py 中相关映射条目)。也就是说,ModernVBert 定位并非生成式多模态大模型,而是可支撑"密集检索 + 后期交互/分块表征"的高效双塔编码底座。

在代码层面,ModernVBert 的实现走的是 Transformers 的 modular 开发管线:唯一可手工编辑的源文件是 modular_modernvbert.py,而 modeling_modernvbert.pyconfiguration_modernvbert.py 均由前者自动生成(文件头部的 CI 提示明确禁止手工编辑生成文件)。从模块头部继承关系可以确认它的实现血统:

  • ModernVBertConfig 继承自 PreTrainedConfig,声明 model_type = "modernvbert"
  • ModernVBertPreTrainedModelModernVBertModel 分别继承自 SmolVLM 的 SmolVLMPreTrainedModel / SmolVLMModel(见 modular_modernvbert.py),因此它天然继承了 SmolVLM 家族"文本+图像多输入、<image> 占位 token 替换、变长多图 batch"的成熟框架,但 inputs_merger 合并逻辑被完全重写以适配 ModernBert 编码器特性。

二、整体架构与数据流:从像素到融合序列的四步流水线

综合 modeling_modernvbert.pyforwardget_image_featuresinputs_merger 三处实现,一次典型的前向过程可分为四个阶段:

2.1 阶段一:文本嵌入与视觉特征提取(可并行)

forward 入口先判断是否提供了 inputs_embeds;若没有,则用文本模型的嵌入层对 input_ids 做查表得到文本嵌入(modeling_modernvbert.py)。同时,只要传入 pixel_values,就调用 get_image_features 走视觉通路。

2.2 阶段二:SigLIP 视觉编码与"真实图像"去冗余

视觉输入 pixel_values 的形状为 (batch_size, num_images, num_channels, height, width),即 batch 内允许每张样本携带任意数量的图片。为了高效处理变长图片数,模型在进入视觉编码器之前会:

  1. (batch_size, num_images, ...) 展平为 (batch_size * num_images, ...)
  2. 检测并剔除全零的 padding 图像real_images_inds,见 modeling_modernvbert.py),保证只把真实图像送进 SigLIP;
  3. 若未提供 pixel_attention_mask,则默认构造全 1 的掩码;否则同步去除 padding 图像对应的掩码行;
  4. 把逐像素注意力掩码按 patch 划分折叠为 patch 级注意力掩码patches_subgrid.unfold(...) 求和后取大于 0),与 SigLIP 视觉模型的 patch_attention_mask 参数对接(modeling_modernvbert.py)。

上述 "padding 图像不进视觉骨干" 的细节同样体现在 forward 的 docstring 中(当 num_images_per_sample=[1, 3, 1, 2] 时只有 7 张真实图进入视觉编码器)。

2.3 阶段三:ModernVBertConnector —— pixel shuffle + 线性投影

这是整个模型最有特色的模块。视觉编码器输出的每个 patch 特征先被 ModernVBertConnector 处理。连接器做两件事:

  1. pixel shuffle 降序列长、升特征维度:假设 SigLIP 把 H×W 图像切为 n 个 patch、每个 patch 特征维度为 dpixel_shuffle 先把 (batch, seq=n, embed=d) 视为 (batch, h, w, d),再按 pixel_shuffle_factor 在宽、高两个方向重排,最终得到 (batch, n/f², d·f²)——序列长度缩减为原来的 1/f²,每个位置的特征维度扩大为原来的 f² 倍modeling_modernvbert.py)。这意味着 16×16 的 patch 网格在 pixel_shuffle_factor=4 时只会产生 16 个视觉 token,token 预算被大幅压缩;
  2. 无偏置线性投影到文本隐藏维度modality_projection 为一个 nn.Linear(d·f², hidden_size, bias=False),把重排后的视觉特征映射到 ModernBert 的隐藏空间(modeling_modernvbert.py)。

image_seq_len 的计算式 ((image_size // patch_size)²) / pixel_shuffle_factor²modeling_modernvbert.py)可见,每个图像最终产生的视觉 token 数量由图像分辨率、patch 尺寸与 pixel shuffle 系数三者共同决定。测试套件中对 image_size=16, patch_size=4, pixel_shuffle_factor=2 的用例得到 (4)²/4 = 4 个视觉 token,可与此公式相互印证(test_modeling_modernvbert.py)。

2.4 阶段四:inputs_merger 融合文本与图像序列

连接器产出的视觉 token 序列通过重写后的 inputs_mergermodeling_modernvbert.py)嵌入文本序列。整个流程为:

  • 文本序列形如 tok_1 tok_2 ... <image> <image> ... <image> ... tok_n,其中每个 <image> 用配置中的 image_token_id(默认 50407)标识;
  • 每个图像的 image_seq_len 个视觉 token 需要替换掉文本中连续的 image_seq_len<image> 占位 token,即把一整块占位 token 换成模型真正"看见"的图像特征块;
  • 实现上通过 torch.where(image_mask.unsqueeze(-1), image_embeds, inputs_embeds) 一次性完成占位替换(modeling_modernvbert.py)。源码中对每个样本执行了"该样本 <image> token 总数必须能被 patch_size(此处指单图视觉 token 数)整除"的合法性校验,若整除失败会直接报错,防止文本中的占位 token 与视觉块错位(modeling_modernvbert.py)。

最后,融合后的完整嵌入序列整体送入 ModernBert 文本编码器做双向编码,输出 ModernVBertBaseModelOutput(其中额外携带 image_hidden_states 字段,见 modeling_modernvbert.py)。因此 ModernBert 的每个 token 都能通过自注意力"看到"整张图像的全部视觉块,这正是它可用于"看图填空/掩码恢复"的能力来源。

三、配置详解:ModernVBertConfig 的全部关键参数

ModernVBertConfig 的权威定义位于 configuration_modernvbert.py,该文档中的 autodoc 指向的正是这个类。它是一个组合式配置(composite config):顶层只暴露少量参数,其余模型规模相关参数被收拢进 text_configvision_config 两个子配置中(sub_configs = {"text_config": AutoConfig, "vision_config": AutoConfig})。

3.1 顶层专属参数

参数 类型 默认值 含义与源码依据
text_config PreTrainedConfig / dict None(自动取 ModernBert 默认配置) 文本编码器 ModernBert 的配置;传入 dict 时在 __post_init__ 中被 CONFIG_MAPPING["modernbert"] 实例化(configuration_modernvbert.py
vision_config PreTrainedConfig / dict None(自动取 siglip_vision_model 默认配置) 视觉编码器 SigLIP Vision 子模型的配置;同上通过 CONFIG_MAPPING["siglip_vision_model"] 实例化(configuration_modernvbert.py
image_token_id int 50407 文本序列中标识"此处应插入图像特征"的占位 token id,inputs_merger 据此定位替换位置
pixel_shuffle_factor int 4 Connector 中 pixel shuffle 重排系数 f:序列长度 /f²、特征维度 ×f²,直接决定每个图像产生的视觉 token 数
initializer_range float 0.02 权重初始化使用的标准差基准值,用于计算各头部的缩放标准差
initializer_cutoff_factor float 2.0 截断正态初始化(truncated normal)的截断范围系数,权重被裁剪在 ±cutoff_factor × std 内(见 modeling_modernvbert.py
classifier_pooling Literal["cls", "mean"] "cls" 序列分类时的池化策略:取 [CLS]/首 token 位置或对全序列按 attention_mask 做均值池化(modeling_modernvbert.py
classifier_dropout float 0.0 分类/词元分类头前的 Dropout 比例
classifier_bias bool False 分类(预测)头是否带偏置项
tie_word_embeddings bool False 是否将 MLM 输出层与词嵌入层权重绑定

3.2 子配置与模块拼接规则

  • text_config 直接驱动 ModernBertConfig 对应的结构字段(如 vocab_sizehidden_sizenum_hidden_layersdecoder_bias 等)。当需要把 ModernBert 替换为更大/更小的主干时,只需改写 text_config,上层代码中诸如 text_config.hidden_sizetext_config.num_hidden_layers 的引用会自动生效;
  • vision_config 必须是 SigLIP Vision Model 兼容配置,代码中实际使用 hidden_size(patch 特征维度)、image_sizepatch_size(决定 patch 网格边长)三个字段,缺一不可(见 modeling_modernvbert.py 与 Connector 构造处的 vision_config.hidden_size);
  • 测试替身配置(text 侧 hidden_size=32、vision 侧 image_size=16/patch_size=4/hidden_size=64)展示了两个子配置如何分别被实例化为 ModernBertConfig 与字典后组合进 ModernVBertConfigtest_modeling_modernvbert.py)。

3.3 用配置实例化模型

依据 configuration_modernvbert.py 官方 docstring,最小用法如下:

from transformers import ModernVBertConfig, ModernVBertModel

# 直接采用默认的 ModernBert + SigLIP 组合
configuration = ModernVBertConfig()
model = ModernVBertModel(configuration)

# 读取回模型实际生效的配置
cfg = model.config

如需精细化自定义,可先构造文本与视觉子配置再合并:

from transformers import ModernVBertConfig

config = ModernVBertConfig(
    text_config={
        "vocab_size": 30528,
        "hidden_size": 768,
        "num_hidden_layers": 12,
    },
    vision_config={
        "image_size": 512,
        "patch_size": 16,
        "hidden_size": 1152,
    },
    pixel_shuffle_factor=4,
    classifier_pooling="mean",
)

四、能力矩阵:四个预训练模型类及其输出结构

官方模型文档 通过 autodoc 列出了 4 个类。下面按源码逐一说明其职责与 forward 差异。

4.1 ModernVBertModel(基础编码器)

  • 职责:完成"图像+文本 → 融合后的双向表征",供下游特征提取、向量化检索使用。
  • 独有的两个方法:
    • get_image_features(pixel_values, pixel_attention_mask=None):单独编码图像并返回 Connector 处理后的视觉特征(被塞进 BaseModelOutputWithPooling.pooler_output 返回,见 modeling_modernvbert.py);
    • inputs_merger(...):上文所述的融合逻辑,可被子类覆写。
  • forward 主要入参:input_idsattention_maskposition_idsinputs_embedspixel_valuespixel_attention_maskimage_hidden_states(支持跳过视觉编码直接喂入预计算视觉特征,便于两阶段缓存/加速)。
  • 返回:ModernVBertBaseModelOutput,除常规 last_hidden_statehidden_statesattentions 外还带 image_hidden_states(形状 (batch_size, num_images, seq_len, hidden_size))。

4.2 ModernVBertForMaskedLM(看图填词,官方示例入口)

结构为 base + ModernVBertPredictionHead + lm_head

  • ModernVBertPredictionHead:继承 ModernBert 的预测头实现(modular 中 class ModernVBertPredictionHead(ModernBertPredictionHead): pass),由 Dense → 激活 → LayerNorm 组成(modeling_modernvbert.py);
  • lm_headnn.Linear(hidden_size, vocab_size, bias=text_config.decoder_bias),负责把表征映射回词表做词元预测;
  • 掩码 token 与图像 token 均不参与 loss 计算:docstring 明确 labels 中值为 image_token_id 的位置会被忽略,loss 只在普通文本标签上计算(modeling_modernvbert.py);
  • 词嵌入可按需与输出层解耦:_tied_weights_keys 记录了 lm_head.weight 与文本嵌入 tok_embeddings.weight 之间的绑定关系(modeling_modernvbert.py)。

4.3 ModernVBertForSequenceClassification(图文序列分类)

  • 在基础模型之上堆叠预测头 + Dropout + nn.Linear(hidden_size, num_labels)
  • 关键差异在池化策略classifier_pooling="cls" 时取序列首位置;"mean" 时用 attention_mask 做加权平均,同时兼容 inputs_embedsinput_ids 两种入口并自动补全缺失的掩码(modeling_modernvbert.py);
  • 自动根据 labels 的形态推断 problem_typeregression / single_label_classification / multi_label_classification)并选择 MSELoss / CrossEntropyLoss / BCEWithLogitsLoss。

4.4 ModernVBertForTokenClassification(词元级标注)

  • 结构同序列分类(head → Dropout → classifier),但对 last_hidden_state每个位置独立做分类,返回 (batch_size, seq_len, num_labels) 的 logits,适合文档版 NER、版面元素标注等视觉词元任务(modeling_modernvbert.py)。

4.5 支持的后端与测试覆盖

ModernVBertPreTrainedModel 声明了完整的高级注意力后端支持:_supports_flash_attn_supports_sdpa_supports_flex_attn_supports_attention_backend 均为 True,同时 supports_gradient_checkpointing = Trueinput_modalities = ("image", "text")modeling_modernvbert.py),与官方文档顶部 FlashAttention/SDPA 徽章呼应。测试套件还注册了如下 pipeline 映射:feature-extractionfill-masktext-classificationimage-classificationtoken-classificationzero-shottest_modeling_modernvbert.py),意味着可直接通过 transformers.pipeline 零配置调用。四个类的前向输出形状均有单元测试断言覆盖(如 logits 形状 (batch, seq, vocab) / (batch, num_labels)),可作为你自行验证实现的对照。

五、端到端实战:加载模型进行"看图填词"推理

以下是 官方模型文档 中的 Python 示例,已按源码补全必要说明,可直接复制运行。它演示的是模型最核心的用法:给定"图 + 带 [MASK] 文本",让模型根据图像内容预测被遮住单词

import torch
from huggingface_hub import hf_hub_download
from PIL import Image

from transformers import AutoModelForMaskedLM, AutoProcessor


processor = AutoProcessor.from_pretrained("./mvb")
model = AutoModelForMaskedLM.from_pretrained("./mvb", device_map="auto")

image = Image.open(
    hf_hub_download("HuggingFaceTB/SmolVLM", "example_images/rococo.jpg", repo_type="space")
)
text = "This [MASK] is on the wall."

# 用对话模板组织多模态消息({"type": "image"} + {"type": "text"})
messages = [
    {
        "role": "user",
        "content": [
            {"type": "image"},
            {"type": "text", "text": text},
        ],
    },
]

# 先套用 chat template 得到含 <image> 占位符的提示词,再统一编码
prompt = processor.apply_chat_template(messages)
inputs = processor(text=prompt, images=[image], return_tensors="pt").to(model.device)

# 推理(编码器模型,无需生成循环)
with torch.no_grad():
    outputs = model(**inputs)

# 定位 [MASK] 位置并取词表上的 argmax
masked_index = inputs["input_ids"][0].tolist().index(processor.tokenizer.mask_token_id)
predicted_token_id = outputs.logits[0, masked_index].argmax(axis=-1)
predicted_token = processor.tokenizer.decode(predicted_token_id)
print("Predicted token:", predicted_token)  # Predicted token: painting

运行要点与源码佐证:

  • 路径说明:官方示例用本地目录 ./mvb 表示已下载好的权重与处理器文件;实际使用也可直接传 Hub 上的模型标识(如 "ModernVBERT/modernvbert")。测试套件在 test_modeling_modernvbert.py 中正是用 AutoProcessor.from_pretrainedAutoTokenizer.from_pretrainedModernVBertForMaskedLM.from_pretrained 三件套加载该模型的真实 checkpoint 做集成验证;
  • Auto API 可用性AutoModelForMaskedLM(映射到 modernvbertModernVBertForMaskedLM)、AutoProcessormodernvbertIdefics3Processor)等 Auto 映射均已注册,见 modeling_auto.pyprocessing_auto.py,因此无需手工 import 具体类;
  • chat template 缺省行为:官方推理示例未显式传 add_generation_prompt,而集成测试中传 add_generation_prompt=Falsetest_modeling_modernvbert.py),说明对编码器 MLM 任务应关闭生成提示(不加 assistant 开场);
  • 交互式核验:上述代码最后用 argmax 输出单一最可能词;测试中则用 softmax + topk 核对了前 5 个候选词的概率分布(test_modeling_modernvbert.py),读者可仿照该写法获取多候选及置信度;
  • 数据精度:模型权重加载时可指定 torch_dtype(集成测试使用 float32),get_image_features 内部也会把 pixel_values 统一到模型 dtype 以保证 fp16 等低精度兼容(modeling_modernvbert.py)。

六、接入下游任务:分类与词元标注示例

在完成预训练/微调后,ModernVBertForSequenceClassificationModernVBertForTokenClassification 可直接用于图文分类与视觉词元标注。二者加载与调用模式相同:

from transformers import AutoModelForSequenceClassification, AutoProcessor
import torch

processor = AutoProcessor.from_pretrained("./mvb")
# 注意分类模型需显式指定标签数(或从模型配置读取 num_labels)
model = AutoModelForSequenceClassification.from_pretrained("./mvb", num_labels=2)
model.eval()

# 组装与前面一致的 messages(image + text)
# ...
inputs = processor(text=prompt, images=[image], return_tensors="pt")

with torch.no_grad():
    outputs = model(**inputs)  # outputs.logits: (batch, num_labels)

label_id = outputs.logits[0].argmax().item()

源码层面的三类 head 差异已在第四节详述,这里再补充两点与训练/微调相关的实现事实:

  • 分类与词元分类头均先经 ModernVBertPredictionHead(Dense → 激活 → LayerNorm)再经 Dropout(config.classifier_dropout) 后进线性分类层(modeling_modernvbert.pymodeling_modernvbert.py);
  • 各新增头部使用截断正态分布初始化,其标准差按部位缩放:MLM 头与 Connector 投影使用 initializer_range / sqrt(2 * text_config.num_hidden_layers),分类头使用 initializer_range / sqrt(text_config.hidden_size)modeling_modernvbert.py),截断边界统一由 initializer_cutoff_factor 控制。

七、典型应用场景与延伸

结合论文定位与仓库结构,ModernVBert 面向的典型应用包括:

  • 视觉文档检索底座:作为 ColModernVBert 检索模型的基础双塔编码器(源码注释明确说明),适合把"文档页面截图/版面图"与"文本查询"统一编码后做向量匹配;
  • 看图填空 / 图文互释:利用 ModernVBertForMaskedLM 让 [MASK] 处的文本 token 通过注意力读取图像上下文完成预测(如官方示例的 rococo 画作中预测出 painting);
  • 版面级理解:序列/词元分类头可支撑文档页分类、区域/实体标注等视觉词元级任务。

如需继续深挖,仓库内可供研读的权威材料有:源码主体 modeling_modernvbert.py、可编辑的模块化定义 modular_modernvbert.py、配置定义 configuration_modernvbert.py 及完整测试与真实 checkpoint 集成验证 test_modeling_modernvbert.py;文本与视觉主干分别参考 ModernBertSigLIP 文档。

结语

ModernVBert 提供了一条"紧凑双塔 + 像素重排压缩视觉 token + 纯掩码目标"的视觉文档编码路径:把 SigLIP 的视觉 patch 通过 pixel shuffle 降到最少 token 数,再以 ModernBert 完成图文联合双向编码,最终以轻量 MLM 头/分类头适配多种检索与理解任务。本文从官方文档出发、以源码为证据,完整还原了它的配置体系、四阶段数据流、四类模型结构与端到端用法。实际落地时,建议结合自身文档分辨率换算 image_seq_len 预算、合理选择 pixel_shuffle_factor,并通过 Auto API 统一加载 checkpoint 与处理器,即可快速复现"看图填词"乃至构建专属的视觉文档检索/理解管线。

登录后查看全文
热门项目推荐
相关项目推荐