ILD

siglip2 to onnx
作者:Yuan Jianpeng 邮箱:yuanjp89@163.com
发布时间:2026-10-23 站点:Inside Linux Development

转换脚本如下:

import torch
from transformers import AutoModel, AutoTokenizer
import torch.nn as nn

class ImageEmbedder(nn.Module):
    def __init__(self, model):
        super().__init__()
        self.model = model
    def forward(self, pixel_values):
        out = self.model.get_image_features(pixel_values=pixel_values)
        # 兼容不同 transformers 版本
        if hasattr(out, "pooler_output"):
            return out.pooler_output
        return out

# 加载完整模型
full_model = AutoModel.from_pretrained("./my_local_siglip").eval()
image_embedder = ImageEmbedder(full_model)

dummy = torch.randn(1, 3, 512, 512)
with torch.no_grad():
    torch.onnx.export(
        image_embedder, dummy, "siglip_image_embed.onnx",
        input_names=["pixel_values"], output_names=["image_embeds"],
        opset_version=17, dynamic_axes=None,
    )

class TextEmbedder(nn.Module):
    def __init__(self, model):
        super().__init__()
        self.model = model
    def forward(self, input_ids):
        out = self.model.get_text_features(input_ids=input_ids)
        # 兼容不同 transformers 版本
        if hasattr(out, "pooler_output"):
            return out.pooler_output
        return out

text_embedder = TextEmbedder(full_model)
dummy_ids = torch.randint(0, 32000, (1, 64))  # 或用 tokenizer 生成
with torch.no_grad():
    torch.onnx.export(
        text_embedder, dummy_ids, "siglip_text_embed.onnx",
        input_names=["input_ids"], output_names=["text_embeds"],
        opset_version=17, dynamic_axes=None,
    )


这里有两个坑,会导致转换后输出不对,


第一个是,直接使用底层的vison tower或者text tower。

vision_model = model.vision_model

text_model = model.text_model


由于导出的是 model.vision_model 和 model.text_model。

根据 Hugging Face 文档,SiglipVisionModel 是“without any head or projection on top”的纯塔结构。

直接调用它得到的是 last_hidden_state,而不是用于比对的嵌入。

真正的图文嵌入需要经过 get_image_features / get_text_features 内部的处理:先取 pooler_output,

再经过 visual_projection 或 text_projection 映射到统一维度。


第二个坑是:

直接使用get_image_features、get_text_features 的结果,它输出的是一个class。


class ImageEmbedder(nn.Module):

    def __init__(self, model):

        super().__init__()

        self.model = model

    def forward(self, pixel_values):

        return self.model.get_image_features(pixel_values=pixel_values)


一个很可能的原因是:你用的 transformers 版本中,

get_image_features / get_text_features 的返回值不再是纯张量,

而是 BaseModelOutputWithPooling 对象。

如果你在 wrapper 的 forward 里直接 return self.model.get_image_features(...),torch.onnx.export

 追踪到的可能并不是对象内部的 pooler_output,而是某个底层输出,或者导出器对返回对象的处理方式与预期不符。


导出后:

2026/10/23  11:49           205,431 siglip_image_embed.onnx

2026/10/23  11:49     1,266,978,816 siglip_image_embed.onnx.data


2026/10/23  11:49           211,534 siglip_text_embed.onnx

2026/10/23  11:49     2,262,675,968 siglip_text_embed.onnx.data


权重单独保存在一个data文件中。


Copyright © linuxdev.cc 2017-2024. Some Rights Reserved.