SigLIP 2:一种更优秀的全球化视觉语言编码器

发布日期:2025年2月21日
在 GitHub 上更新

TL;DR

今天,谷歌发布了一个新的、更优秀的**多语言**视觉语言编码器系列:SigLIP 2。作者在SigLIP(*sigmoid损失*)的训练目标基础上,增加了额外的目标,以提高语义理解、定位和密集特征。

Objectives added
附加目标(来源:https://huggingface.ac.cn/papers/2502.14786

SigLIP 2模型在所有模型规模的核心能力上都**优于**旧的SigLIP模型,包括零样本分类、图像-文本检索,以及在为视觉语言模型(VLM)提取视觉表示时的迁移性能。

更棒的是动态分辨率(`naflex`)变体。这对于对长宽比和分辨率敏感的下游任务很有用。

以下是已发布的所有模型列表

引言

视觉编码器很简单——它们接收一张图像,将其编码成一种表示,然后这种表示被用于分类、目标检测、图像分割以及更多视觉任务。研究人员一直在追求**密集**、**局部感知**和**语义丰富**的视觉表示。

CLIPALIGN是图像编码器和文本编码器通过联合训练对齐的最初例子。这种方法开辟了训练视觉模型的新途径。SigLIP更进一步,用*sigmoid损失*取代了CLIP的*对比损失*,以获得更好的编码器。

从中得到的启示是?通过更智能的训练目标,我们不断构建出更结构化、更细粒度、更强大的视觉编码器。SigLIP 2正是如此,它在SigLIP的训练目标基础上,应用了一系列非常有趣和智能的训练目标,以提供更好、更强的视觉语言编码器。

我们将在本博客文章中尝试一些新的东西。我们不直接说明什么是新的以及在哪里可以找到它,而是将一起进行一个小练习。我们从SigLIP开始,然后集思广益一系列问题(以🤔开头)和答案(新的标题),逐步涵盖SigLIP 2中的所有更新。听起来不错吗?

我们将从补丁大小为**16**,图像分辨率为**256**的视觉编码器开始我们的旅程。我们有四种变体可以开始我们的训练

  1. siglip2-base-patch16-256
  2. siglip2-large-patch16-256
  3. siglip2-so400m-patch16-256
  4. siglip2-giant-opt-patch16-256

🤔 问题1:我们可以使用什么(低成本)辅助训练目标来学习更好的视觉表示(在位置感知和局部感知方面)?

添加一个解码器(就是这么简单)

让我们加入一个解码器。现在我们有一个图像编码器、一个文本编码器和一个*文本解码器*。文本解码器将有三个目标:

  1. 预测整体图像标题
  2. 根据描述*特定*图像区域的标题预测边界框坐标
  3. 根据边界框坐标预测区域特定标题

解码器为视觉编码器提供了额外的信号,使其具有位置感知能力。这标志着SigLIP 2训练配方的首次改进。

🤔 问题2:我们如何改进图像表示的细粒度局部语义?

带有全局-局部损失和掩码预测的自蒸馏

为了提高图像表示的细粒度局部语义,我们引入了两个关键的训练目标:全局-局部损失和掩码预测损失。借鉴自监督学习文献的启发,我们使用*自蒸馏*。我们可以将一个模型用作教师模型,同时又将其用作学生模型。每次迭代时,教师模型的参数将是学生模型参数的移动平均。

  1. **全局-局部损失**:学生网络获得训练图像的部分(局部)视图,并被训练以匹配教师模型从完整图像中派生出的表示。
  2. **掩码预测损失**:学生网络中嵌入图像补丁的50%被掩码标记遮蔽。学生需要匹配教师模型在掩码位置的特征。

这些目标使视觉编码器具备空间感知能力并改善其局部语义。作者仅在完成sigmoid和解码器损失训练的**80%**后才添加此损失。这样做是为了节省计算(额外的损失相当昂贵)并且避免对编码器产生负面影响。

🤔 问题3:如何让模型适应不同的分辨率?

适应不同分辨率

众所周知,图像模型对不同的分辨率和长宽比非常敏感。这里我们可以利用两种不同的方法来使这些模型适应不同的分辨率和补丁大小。

  1. **固定分辨率变体**:从95%的训练检查点开始,我们可以调整位置嵌入和补丁嵌入的大小,然后继续训练请求的(可能更大)分辨率。
  2. **动态分辨率变体**:借鉴FlexiViT使用不同序列长度输入和NaViT遵循原始长宽比的启发,我们可以创建**NaFlex**变体。这很有趣,因为我们可以使用一个模型进行OCR(很少有长宽比失真)和文档理解(适当的分辨率)。

带有`-naflex`后缀的模型是动态分辨率变体。虽然固定分辨率模型可以直接使用现有的`SiglipModel`类,但您需要使用`Siglip2Model`才能使用`naflex`变体。当您使用管道API时,我们会自动处理这个问题!

至此,我们完成了从 SigLIP 到 SigLIP 2 的演进。在接下来的部分,我们将探讨 SigLIP 2 的应用。

使用transformers运行推理

在模型上运行推理非常简单。您可以复制下面的代码,并在免费的Colab notebook上运行推理🚀

要对 SigLIP 2 运行推理,请从 `main` 或从这个稳定分支安装 `transformers`:`pip install git+https://github.com/huggingface/transformers@v4.49.0-SigLIP-2`

零样本分类

在这里,我们使用方便的`pipeline` API 来展示 SigLIP 2 的零样本分类能力。

from transformers import pipeline

ckpt = "google/siglip2-so400m-patch14-384"
pipe = pipeline(model=ckpt, task="zero-shot-image-classification")

inputs = {
    "images": [
        "https://huggingface.co/datasets/merve/coco/resolve/main/val2017/000000000285.jpg", # bear
        "https://huggingface.co/datasets/merve/coco/resolve/main/val2017/000000000776.jpg", # teddy bear
    ],
    "texts": [
        "bear looking into the camera",
        "bear looking away from the camera",
        "a bunch of teddy bears",
        "two teddy bears",
        "three teddy bears"
    ],
}

outputs = pipe(inputs["images"], candidate_labels=inputs["texts"])

让我们可视化输出。

output of zero shot classification
可视化零样本分类分数

为下游任务编码图像

您也可以使用以下方法编码图像:

import torch
from transformers import AutoModel, AutoProcessor
from transformers.image_utils import load_image

ckpt = "google/siglip2-so400m-patch14-384"
model = AutoModel.from_pretrained(ckpt, device_map="auto").eval()
processor = AutoProcessor.from_pretrained(ckpt)

image = load_image("https://huggingface.co/datasets/merve/coco/resolve/main/val2017/000000000285.jpg")
inputs = processor(images=[image], return_tensors="pt").to(model.device)

with torch.no_grad():
    image_embeddings = model.get_image_features(**inputs)    

print(image_embeddings.shape) # torch.Size([1, 1152])

SigLIP 1与SigLIP 2的比较

查看所有已发布的 SigLIP 2 模型表格,我们看到与 SigLIP 相比有两个明显的改变:

  1. SigLIP 2 引入了新的动态分辨率变体 (`naflex`)。
  2. SigLIP 2 新增了 `giant` (1B) 系列模型。

SigLIP 2 的评估表证明了其优于 SigLIP 的性能。

evaluation table
SigLIP 2 的评估分数(来源:https://huggingface.ac.cn/papers/2502.14786

这里有一个演示,可以比较 SigLIP 1 和 SigLIP 2 的零样本分类结果。

将编码器用于VLM

与文本信息对齐的视觉编码器在**视觉语言模型** (VLM) 的开发中变得越来越重要。构建 VLM 的常见方法是将预训练的视觉编码器与预训练的 LLM 结合起来,并使用多模态数据在各种视觉语言任务中共同训练它们。

一个利用 SigLIP 视觉编码器系列的杰出 VLM 例子是 **PaliGemma**。您可以在这篇PaliGemma博客文章中深入了解 PaliGemma 的功能。在此基础上,最近推出的PaliGemma 2通过将 SigLIP 与先进的 Gemma 2 LLM 集成,更进一步。在一个类似 PaliGemma 的环境中,将 SigLIP 替换为 SigLIP 2,并观察该模型的表现,将非常令人兴奋。

致谢

我们衷心感谢Michael Tschannen(SigLIP 2的第一作者)、Vaibhav SrivastavSayak Paul对本博客文章的反馈。同时,也要向Google团队致以崇高的敬意,感谢他们发布了这一卓越且开源的模型系列。

我们特别要感谢PavelRossPabloPedroLysandre以及Hugging Face团队的其他成员,感谢他们对该项目的巨大支持和贡献。

社区

可能需要检查一下:底部演示一直停留在“Uploading 1 file...”状态,预设示例均无法加载或执行。抛出6个不同的Javascript控制台错误。(Chrome, Mac)。

·

是的,我也看到了

感谢博客。

Siglip2 不包含像 Siglip 那样的“spiece.model”。这是预期的吗?处理器报错,指出 vocab 文件是 NoneType 对象,这可能表明缺少 spiece 模型。有什么想法吗?

transformers.version : 4.49.0

·
文章作者

你能从main分支安装`transformers`吗?

pip install git+https://github.com/huggingface/transformers@main

如果这解决了问题,请告诉我们。🤗

我尝试运行零样本分类示例,结果出现`ValueError: Unable to create tensor, you should probably activate truncation and/or padding with 'padding=True' 'truncation=True' to have batched tensors with the same length. Perhaps your features (`input_ids` in this case) have excessive nesting (inputs type `list` where type `int` is expected).` transformers 版本=4.49.0.dev0

我尝试添加`padding=True`和`truncation=True`,但都无济于事。我还尝试了`padding="max_length"`

编辑
如果我的标签长度都相同,它似乎可以工作。在调试时,我看到在`zero_shot_image_classification.py`中,提供给tokenizer的padding在这里(L148-149)无论如何都会被强制为`max_length`

padding = "max_length" if self.model.config.model_type == "siglip" else True
text_inputs = self.tokenizer(sequences, return_tensors=self.framework, padding=padding, **tokenizer_kwargs)

然而,如果我的标签长度可变,输出的长度就不同,因此最终导致torch.tensor调用失败
我也在我的终端中发现了这个警告
要求填充到max_length,但未提供最大长度,且模型没有预定义的最大长度。默认不填充。

·

警告告诉你答案:传入 max_length=64

“使用独立的 GemmaTokenizerFast 时,请务必传入 padding="max_length" 和 max_length=64,因为模型就是这样训练的。”Siglip2 是否支持更长的文本输入?如果 max_length 设置为 256 或 512,超过 64 的文本会被截断吗?

·

是的。如果你想要更长的文本,我的做法是将其分成64个token的块(可能甚至重叠),分别嵌入这些块,然后平均它们的结尾或分别与图像嵌入点积,并根据你的用例取最大值或平均分数。

我其实很好奇你正在处理的查询类型会超过64个token吗?我能想到的所有siglip用例几乎都远低于64个。

我收到以下错误:

/lib/python3.10/site-packages/transformers/models/siglip/tokenization_siglip.py", line 139, in get_spm_processor
with open(self.vocab_file, "rb") as f
TypeError: expected str, bytes or os.PathLike object, not NoneType

·
文章作者

你能从主分支安装 transformers 吗?

pip install git+https://github.com/huggingface/transformers@main

如果这解决了问题,请告诉我们。🤗

实际上有3只猫,其中一只怀孕了

有人知道在哪里可以找到naflex变体的基准测试吗?我可能瞎了,但图表中似乎没有它们?
编辑:没事了,去附录找吧

跨模态相似度

当我向模型输入图像和文本时

def get_output(url, text):
    text = "a photo of 2 cats"
    url = "http://images.cocodataset.org/val2017/000000039769.jpg"
    image = load_image(url)
    inputs = processor(text=[text], images=image, padding="max_length", return_tensors="pt").to(model.device)
    with torch.no_grad():
        output = model(**inputs)
    return output

输出的logits是
SiglipOutput(loss=None, logits_per_image=tensor([[-15.5217]], device='cuda:0'), logits_per_text=tensor([[-15.5217]], device='cuda:0')

sigmoid后输出接近于0。

我该如何解决?

·

我也遇到了这个问题。

是否有提供在自定义数据集上进行微调的示例?

·
文章作者

@nielsr 有一个关于微调siglip和类似模型的出色笔记本。

https://github.com/NielsRogge/Transformers-Tutorials/tree/master/SigLIP

注册登录以评论