使用 Transformers 构建统一视觉语言模型:BLIP 架构、配置与三大任务实战指南
【免费下载链接】transformers🤗 Transformers: the model-definition framework for state-of-the-art machine learning models in text, vision, audio, and multimodal models, for both inference and training.项目地址: https://gitcode.com/GitHub_Trending/tra/transformers
BLIP(Bootstrapping Language-Image Pre-training)是一个统一的视觉语言预训练框架,在同一套架构内同时支持图像描述生成(Image Captioning)、视觉问答(VQA)与图像-文本检索(ITM)三类任务。本文以 Transformers 仓库中 BLIP 的官方文档为主线,结合 configuration_blip.py、modeling_blip.py 等源码实现与 test_modeling_blip.py 中的集成测试,系统讲解 BLIP 的设计思想、配置体系、处理器管线,以及三类任务的推理与微调实战,帮助你直接上手把 BLIP 用于自己的多模态应用。
BLIP 是什么:一个兼顾理解与生成的视觉语言预训练框架
BLIP 模型由 Junnan Li、Dongxu Li、Caiming Xiong、Steven Hoi 在论文BLIP: Bootstrapping Language-Image Pre-training for Unified Vision-Language Understanding and Generation(论文链接)中提出。与以往大多只在"理解类"或"生成类"任务上表现优异的预训练模型不同,BLIP 是一个能够灵活迁移到视觉语言理解与生成两类任务的统一框架。
BLIP 的核心思想是利用带噪 Web 数据的自举(Bootstrapping)策略:由 Captioner 为网络图片生成合成描述,再由 Filter 过滤掉噪声描述,从而高效利用大规模、弱监督的图文对数据。根据论文摘要,这一方法在多项基准上带来了可观的提升:
- 图像-文本检索:平均召回率(Recall@1)提升 +2.7%;
- 图像描述生成:CIDEr 指标提升 +2.8%;
- 视觉问答:VQA 分数提升 +1.6%;
- 同时,BLIP 在零样本迁移到视频-语言任务时也展现出较强的泛化能力。
BLIP 可以完成的核心多模态任务包括:
- 视觉问答(Visual Question Answering):给定图片与问题,生成答案;
- 图像-文本检索(Image-Text Retrieval / Image-Text Matching):判断图文对是否匹配,或计算图文相似度;
- 图像描述生成(Image Captioning):为图片生成自然语言描述。
在 Transformers 中,该模型的实现由 ybelkada,官方也提供了在自定义数据集上微调 BLIP 做图像描述生成的 Jupyter Notebook 资源。
架构总览:视觉编码器 + 文本编码器/解码器的组合
从 modeling_blip.py 的源码结构可以看出,BLIP 家族由三个基础子模块组成:
BlipVisionModel:基于 Vision Transformer(ViT)的视觉编码器,将图像编码为视觉特征序列。其main_input_name为pixel_values,内部包含BlipVisionEmbeddings(Patch 嵌入 + 位置编码)、BlipEncoder(12 层 Transformer Encoder)与post_layernorm层归一化(见 modeling_blip.py)。BlipTextModel:基于 BERT 结构的文本模型,支持自注意力与交叉注意力(cross-attention),既可充当文本编码器,也可作为解码器的一部分(实现于 modeling_blip_text.py)。BlipTextLMHeadModel:在文本模型之上叠加语言建模输出头(LM Head),用于生成式任务(实现于 modeling_blip_text.py)。
在视觉分支中,BlipVisionEmbeddings采用nn.Conv2d将图像切分为 patch 并线性投影(modeling_blip.py),默认image_size=384、patch_size=16,得到 24×24=576 个 patch 加上 1 个 class token,共 577 个位置。它还实现了interpolate_pos_encoding方法,支持对位置编码做双三次插值,从而在更高分辨率输入下仍可使用预训练权重(modeling_blip.py)。
三个任务模型以不同方式组合这些子模块:
| 任务模型 | 组成 | 用途 |
|---|---|---|
BlipForConditionalGeneration | 视觉编码器 + 文本解码器 | 图像描述生成 |
BlipForQuestionAnswering | 视觉编码器 + 文本编码器 + 文本解码器 | 视觉问答 |
BlipForImageTextRetrieval | 视觉编码器 + 文本编码器 + ITM 分类头 | 图像-文本匹配/检索 |
此外,BlipModel作为双塔(dual-encoder)模型,通过对比学习(contrastive loss)训练图文嵌入的对齐,提供get_text_features、get_image_features、get_multimodal_features与forward(返回logits_per_image、logits_per_text)。需要说明的是,源码中标注BlipModel未来版本将被弃用(deprecated),建议按任务选择上述三个专用模型(modeling_blip.py)。
配置体系:BlipConfig、BlipTextConfig 与 BlipVisionConfig
BLIP 采用"总配置 + 子配置"的设计:BlipConfig是总配置,通过sub_configs = {"text_config": BlipTextConfig, "vision_config": BlipVisionConfig}将文本子配置与视觉子配置组合在一起(见 configuration_blip.py)。
BlipTextConfig:文本子配置
BlipTextConfig的model_type为blip_text_model,默认值如下(configuration_blip.py):
| 参数 | 默认值 | 说明 |
|---|---|---|
vocab_size | 30524 | 词表大小 |
hidden_size | 768 | 隐藏层维度 |
encoder_hidden_size | 768 | 交叉注意力中编码器(视觉)隐藏维度 |
intermediate_size | 3072 | FFN 中间层维度 |
projection_dim | 768 | 投影层输出维度 |
num_hidden_layers | 12 | Transformer 层数 |
num_attention_heads | 8 | 注意力头数 |
max_position_embeddings | 512 | 最大序列长度 |
hidden_act | "gelu" | 激活函数 |
layer_norm_eps | 1e-12 | LayerNorm 精度 |
hidden_dropout_prob/attention_probs_dropout_prob | 0.0 | 各层 Dropout |
bos_token_id | 30522 | 起始符 |
eos_token_id | 2 | 结束符 |
pad_token_id | 0 | 填充符 |
sep_token_id | 102 | 分隔符 |
is_decoder | True | 作为解码器使用 |
use_cache | True | 生成时使用 KV 缓存 |
tie_word_embeddings | True | 输入输出嵌入共享 |
label_smoothing | 0.0 | 损失计算时的标签平滑系数(取值 [0.0, 1.0],0.0 表示不平滑) |
注意:文本子配置的label_smoothing参数来自Rethinking the Inception Architecture for Computer Vision中提出的标签平滑思想,训练时可将目标分布与均匀分布混合。
BlipVisionConfig:视觉子配置
BlipVisionConfig的model_type为blip_vision_model,默认值如下(configuration_blip.py):
| 参数 | 默认值 | 说明 |
|---|---|---|
hidden_size | 768 | 视觉隐藏层维度 |
intermediate_size | 3072 | FFN 中间层维度 |
projection_dim | 512 | 投影层输出维度 |
num_hidden_layers | 12 | Transformer 层数 |
num_attention_heads | 12 | 注意力头数 |
image_size | 384 | 输入图像尺寸 |
patch_size | 16 | Patch 尺寸 |
hidden_act | "gelu" | 激活函数 |
layer_norm_eps | 1e-5 | LayerNorm 精度 |
attention_dropout | 0.0 | 注意力 Dropout |
initializer_range | 1e-10 | 初始化范围 |
BlipConfig:总配置
BlipConfig的model_type为blip,额外提供(configuration_blip.py):
projection_dim(默认 512):图文投影层的目标维度;logit_scale_init_value(默认 2.6592):对比学习相似度 logit 缩放的初始值;image_text_hidden_size(默认 256):图像-文本融合层的隐藏维度;label_smoothing(默认 0.0):总配置级别的标签平滑;tie_word_embeddings(默认 True);initializer_factor(默认 1.0)与initializer_range(默认 0.02):权重初始化相关。
在__post_init__中,若text_config/vision_config为None则自动用默认子配置填充;若传入 dict 则实例化为对应子配置类;同时会强制text_config.encoder_hidden_size = vision_config.hidden_size,保证文本分支交叉注意力与视觉分支维度一致。
配置使用示例
from transformers import BlipConfig, BlipTextConfig, BlipVisionConfig, BlipModel # 方式一:直接使用默认配置初始化 configuration = BlipConfig() model = BlipModel(configuration) # 方式二:分别初始化文本与视觉子配置,再组合成总配置 config_text = BlipTextConfig() config_vision = BlipVisionConfig() config = BlipConfig(text_config=config_text, vision_config=config_vision)数据预处理:BlipProcessor 与图像处理器
BlipProcessor是一个组合处理器(ProcessorMixin),同时封装了图像处理器与分词器(tokenizer),负责把原始图片和文本统一转换成模型输入(实现于 processing_blip.py)。初始化时会强制tokenizer.return_token_type_ids = False,因为 BLIP 输入不需要 token type ids(unused_input_names返回["token_type_ids"])。
文本侧的默认预处理参数(BlipProcessorKwargs._defaults)包括:add_special_tokens=True、padding=False、return_overflowing_tokens=False、return_offsets_mapping=False、return_token_type_ids=False等。
图像侧由BlipImageProcessor负责(实现于 image_processing_blip.py),其默认行为:
- 重采样方式:双三次插值(
BICUBIC); - 归一化均值/方差:使用 OpenAI CLIP 的统计值(
OPENAI_CLIP_MEAN/OPENAI_CLIP_STD); - 目标尺寸:
{"height": 384, "width": 384}; - 预处理流水线:
do_resize(缩放到 384×384)、do_rescale(像素值缩放到 [0,1])、do_normalize(按 CLIP 均值方差归一化)、do_convert_rgb(统一转为 RGB)。
仓库中还有BlipImageProcessorFast(对应快速图像处理器类,文档中同样以preprocess方法导出)与基于 PIL 后端的BlipImageProcessorPil(见 image_processing_pil_blip.py),参数与上述保持一致。
实际使用中,通常直接通过AutoProcessor.from_pretrained(...)加载处理器,例如:
from transformers import AutoProcessor processor = AutoProcessor.from_pretrained("Salesforce/blip-image-captioning-base") inputs = processor(images=image, text="A picture of", return_tensors="pt")实战一:图像描述生成(BlipForConditionalGeneration)
BlipForConditionalGeneration由视觉编码器(BlipVisionModel)与文本解码器(BlipTextLMHeadModel)构成(modeling_blip.py)。其工作方式为:视觉编码器先编码图像得到image_embeds,文本解码器以该视觉特征为交叉注意力的encoder_hidden_states进行自回归生成。
推理示例
from PIL import Image import httpx from io import BytesIO from transformers import AutoProcessor, BlipForConditionalGeneration processor = AutoProcessor.from_pretrained("Salesforce/blip-image-captioning-base") model = BlipForConditionalGeneration.from_pretrained("Salesforce/blip-image-captioning-base") url = "http://images.cocodataset.org/val2017/000000039769.jpg" with httpx.stream("GET", url) as response: image = Image.open(BytesIO(response.read())) # 仅输入图像,解码器从 [BOS] 标记开始生成描述 inputs = processor(images=image, return_tensors="pt") outputs = model.generate(**inputs) print(processor.decode(outputs[0], skip_special_tokens=True)) # 例如输出:two cats sleeping on a couch要点说明:
- 若不传
input_ids,generate内部会构造以bos_token_id(30522)起始、以eos_token_id(2)结尾的初始序列(modeling_blip.py),并以sep_token_id(102)作为生成结束符; - 若要引导生成,可传入前缀文本,例如
processor(images=image, text="A picture of", ...),解码器会延续该提示继续生成; interpolate_pos_encoding=True时允许输入非 384×384 的任意尺寸图像,内部通过位置编码插值实现。
微调训练
与标准语言模型微调类似,传入labels即可计算解码器的语言建模损失(reduction="mean"):
inputs = processor(images=image, text=caption, return_tensors="pt") inputs["labels"] = inputs["input_ids"] outputs = model(**inputs) loss = outputs.loss # 语言建模损失 loss.backward()forward返回的BlipForConditionalGenerationModelOutput包含loss、logits、image_embeds、last_hidden_state、hidden_states与attentions等字段(modeling_blip.py)。
在集成测试 test_modeling_blip.py 中,官方验证了纯图像输入与带上下文输入两种场景下的生成 token 序列,并测试了 fp16 精度下的生成一致性;test_inference_interpolate_pos_encoding则验证了将image_processor.size改为 500×500 并开启位置编码插值后依然能稳定生成描述。
实战二:视觉问答(BlipForQuestionAnswering)
BlipForQuestionAnswering由三部分组成:视觉编码器、文本编码器(BlipTextModel,不使用池化层)与文本解码器(BlipTextLMHeadModel)(modeling_blip.py)。流程为:视觉编码器编码图片 → 文本编码器结合图片特征与问题做交叉注意力编码 → 文本解码器生成答案。
from PIL import Image import httpx from io import BytesIO from transformers import AutoProcessor, BlipForQuestionAnswering model = BlipForQuestionAnswering.from_pretrained("Salesforce/blip-vqa-base") processor = AutoProcessor.from_pretrained("Salesforce/blip-vqa-base") url = "http://images.cocodataset.org/val2017/000000039769.jpg" with httpx.stream("GET", url) as response: image = Image.open(BytesIO(response.read())) # 推理:给定图片 + 问题,生成答案 text = "How many cats are in the picture?" inputs = processor(images=image, text=text, return_tensors="pt") outputs = model.generate(**inputs) print(processor.decode(outputs[0], skip_special_tokens=True)) # 例如输出:2训练时需同时提供问题与答案标签(labels 已右移,无需手动 shift):
text = "How many cats are in the picture?" label = "2" inputs = processor(images=image, text=text, return_tensors="pt") labels = processor(text=label, return_tensors="pt").input_ids inputs["labels"] = labels outputs = model(**inputs) loss = outputs.loss loss.backward()注意:forward要求必须提供decoder_input_ids或labels,否则会抛出ValueError(modeling_blip.py)。generate内部会将问题编码结果作为解码器的交叉注意力输入,并从bos_token_id开始生成,以sep_token_id结束。
实战三:图像-文本检索 / 匹配(BlipForImageTextRetrieval)
BlipForImageTextRetrieval用于判断给定图文对是否匹配,由视觉编码器、文本编码器、视觉/文本投影层(vision_proj、text_proj,输出维度为image_text_hidden_size)以及二分类的 ITM 头(itm_head,输出维度 2)构成(modeling_blip.py)。
from PIL import Image import httpx from io import BytesIO from transformers import AutoProcessor, BlipForImageTextRetrieval model = BlipForImageTextRetrieval.from_pretrained("Salesforce/blip-itm-base-coco") processor = AutoProcessor.from_pretrained("Salesforce/blip-itm-base-coco") url = "http://images.cocodataset.org/val2017/000000039769.jpg" with httpx.stream("GET", url) as response: image = Image.open(BytesIO(response.read())) text = "an image of a cat" inputs = processor(images=image, text=text, return_tensors="pt") outputs = model(**inputs) # outputs.itm_score:图像-文本匹配得分forward的关键参数是use_itm_head(默认True):
- 当
use_itm_head=True时,使用 ITM 二分类头输出图文匹配分数(modeling_blip.py); - 当
use_itm_head=False时,退化为计算图像特征与文本特征的归一化内积(余弦相似度),可用于大规模图文检索排序(modeling_blip.py)。
在集成测试 test_modeling_blip.py 中,官方对 "A woman and her dog sitting in a beach" 与图片的匹配结果做了断言:开启 ITM 头时 softmax 后的得分为[0.0029, 0.9971](即"不匹配/匹配"二分类概率),关闭 ITM 头时相似度分数约为0.5162。
补充:BlipTextModel 与 BlipVisionModel 独立使用
除了三个任务模型,BlipTextModel与BlipVisionModel也可独立使用(如提取图文特征)。BlipTextModel的forward支持input_ids、attention_mask、position_ids、inputs_embeds、encoder_embeds、encoder_hidden_states、encoder_attention_mask、past_key_values、use_cache、is_decoder等参数,返回带池化输出与交叉注意力的BaseModelOutputWithPoolingAndCrossAttentions(实现于 modeling_blip_text.py)。BlipVisionModel的forward接收pixel_values与interpolate_pos_encoding,返回BaseModelOutputWithPooling(modeling_blip.py)。
from transformers import BlipTextConfig, BlipTextModel from transformers import BlipVisionConfig, BlipVisionModel # 使用默认配置初始化(随机权重) text_config = BlipTextConfig() text_model = BlipTextModel(text_config) vision_config = BlipVisionConfig() vision_model = BlipVisionModel(vision_config)模型检查点与转换脚本
本仓库的测试与文档中涉及的官方预训练检查点包括:
Salesforce/blip-image-captioning-base:图像描述生成(用于BlipForConditionalGeneration);Salesforce/blip-vqa-base:视觉问答(用于BlipForQuestionAnswering,也是BlipTextConfig/BlipVisionConfig/BlipConfig文档中@auto_docstring使用的示例检查点);Salesforce/blip-itm-base-coco:图像-文本匹配(用于BlipForImageTextRetrieval)。
此外,仓库提供了 convert_blip_original_pytorch_to_hf.py,包含convert_blip_checkpoint函数与rename_key键名映射逻辑,可将 Salesforce 原始 PyTorch 检查点转换为 Hugging Face 格式;相关测试覆盖见 test_modeling_blip.py 与 test_processing_blip.py。
小结
BLIP 在 Transformers 中的实现提供了完整且统一的多模态能力:通过BlipConfig(内含BlipTextConfig与BlipVisionConfig)灵活配置双塔结构,借助BlipProcessor一键完成图文预处理,并由三个任务模型分别支撑图像描述生成、视觉问答与图文检索。无论你是要快速跑通推理、在自定义数据集上微调,还是提取图文特征做检索排序,都可以从本文给出的示例代码出发,进一步阅读 src/transformers/models/blip 下的源码与 tests/models/blip 下的测试用例,深入理解其内部实现细节。
【免费下载链接】transformers🤗 Transformers: the model-definition framework for state-of-the-art machine learning models in text, vision, audio, and multimodal models, for both inference and training.项目地址: https://gitcode.com/GitHub_Trending/tra/transformers
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考