PaliGemma 是 Google 推出的新一代视觉语言模型家族,能够接收图像与文本输入并生成文本输出。没错,就是那个在图像理解和语言生成上不断刷新的家伙。

这次 Google 一共放出了三种类型的模型:预训练 (PT) 模型、混合模型和微调 (FT) 模型,分辨率有高有低,精度也有多种选择。所有模型都在 Hugging Face Hub 上发布,配备了完备的模型说明和许可证,直接用 transformers 就能跑起来。
PaliGemma 是什么?
简单来说,PaliGemma 是一系列拥有视觉和语言处理能力的模型,核心结构是:图像编码器 + 文本解码器。图像编码器用的是 SigLIP——一个能同时解析图像和文本的顶尖模型,工作方式和 CLIP 类似,通过对图像和文本编码器的联合训练来学习对齐。文本解码器则是 Gemma,专门为文本生成而设计。两者之间通过一个线性适配器连接,最终形成一个强大的视觉语言模型。
发布的三类模型各司其职:
- PT 检查点:预训练模型,供下游任务微调用。
- 混合检查点:已在多种任务上微调过的 PT 模型,适合直接用自由文本提示进行通用推理——不过仅限研究使用。
- FT 检查点:针对不同学术基准微调好的模型,同样提供多种分辨率,也是研究限定。
这些模型共提供三种分辨率(224×224、448×448、896×896)和三种精度(bfloat16、float16、float32)。每个版本的主分支包含 float32 检查点,而 bfloat16 和 float16 版本则对应各自精度的检查点。同时,与 transformers 兼容的版本以及原始 JAX 实现的版本也一应俱全。
这里需要提醒一句:高分辨率模型因为输入序列更长,对内存的需求也更高。虽然它在细粒度任务(比如 OCR)上可能更好,但对大多数任务来说,质量提升其实不大。224 版本已经足够应付绝大多数场景。
所有模型和 Space 应用都可以在 Hugging Face 上找到。
模型功能
PaliGemma 是一个单轮视觉语言模型,不支持多轮对话。它的最佳用法是针对特定用例进行微调。你可以通过设置任务前缀,比如 detect 或 segment,来告诉模型要解决什么问题。预训练模型就是这么训练的,所以它具备丰富的底层能力(问题回答、图像标题生成、图像分割等),但不适合直接开箱即用。要交互式体验,可以直接用已经对多任务微调好的“mix”系列模型。
下面用混合检查点展示几个典型功能。
图像标题生成
当给出图片和提示,PaliGemma 就能生成标题。你可以试试不同的提示词,看看它会怎么发挥。
视觉问题回答
把问题连同图像一起传进去,模型就能给出答案。
检测
使用 detect [entity] 提示,模型可以检测图像中的实体。它会输出以 令牌形式表示的边界框坐标,其中 value 是归一化坐标的数字。每次检测由四个位置坐标代表——ymin, xmin, ymax, xmax,后面跟着检测到的框中的标签。要转换为实际坐标,先把数字除以 1024,再把 y 乘以图像高度,x 乘以宽度,就能得到相对于原始图像大小的边界框。
指代表达分割
给定 segment [entity] 提示,混合检查点可以对图像中的实体进行分割。这称为指代表达分割——用自然语言描述来引用感兴趣的实体。输出是一串位置和分割标记。位置标记代表边界框,分割标记可以进一步处理生成掩膜。
文档理解
混合检查点在文档理解和推理上表现相当出色,可以轻松处理表格、表单等复杂排版。
混合基准
以下是混合检查点的得分数据。
| 模型 | MMVP 准确率 | POPE 准确率 (随机/流行/对抗) |
|---|---|---|
| mix-224 | 46.00 | 88.00 86.63 85.67 |
| mix-448 | 45.33 | 89.37 88.40 87.47 |
微调检查点
除了预训练和混合模型,Google 还放出了针对各种学术基准微调好的模型,方便研究社区直接比较。以下是一些选定的模型(不同分辨率)。你可以查看任意模型的模型卡获取所有指标。
| 模型名称 | 数据集/任务 | 转移任务中的得分 |
|---|---|---|
| 图解理解 | 在 VQA V2 上的准确率为 85.64 | |
| COCO 标题 | CIDEr 为 144.6 | |
| 科学问题回答 | 在没有 CoT 的 ScienceQA Img 子集上的准确率为 95.93 | |
| 图像中特定对象的理解 | 在 refcoco 上的平均 IoU 为 76.94,在 refcoco+ 上为 72.18,在 refcocog 上为 72.22 | |
| 遥感视觉问题回答 | 在 test 上的准确率为 92.61,在 test2 上为 90.58 |
演示
作为发布的一部分,还提供了一个使用参考实现的交互式演示,可以方便地体验混合模型。
同时还有一个与 Transformers 兼容的笔记本,展示了如何使用 PaliGemma transformers API。
如何运行推理
要获取 PaliGemma 模型的访问权限,你需要先接受 Gemma 的许可条款。如果你已经在 Hugging Face 上访问过其他 Gemma 模型,那直接就能用。否则,去任意一个 PaliGemma 模型页面,同意许可即可。认证完成后,就能愉快地使用了。
当然,你也可以立刻在线尝试运行推理。
使用 Transformers
用 PaliGemmaForConditionalGeneration 类就能加载任意已发布的模型。直接用内置的处理器预处理提示和图像,再传给 generate 就能生成结果。
from transformers import AutoProcessor, PaliGemmaForConditionalGeneration
model_id = "google/paligemma-3b-mix-224"
model = PaliGemmaForConditionalGeneration.from_pretrained(model_id)
processor = AutoProcessor.from_pretrained(model_id)
prompt = "What is on the flower?"
image_file = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/bee.jpg?download=true"
raw_image = Image.open(requests.get(image_file, stream=True).raw)
inputs = processor(prompt, raw_image, return_tensors="pt")
output = model.generate(**inputs, max_new_tokens=20)
print(processor.decode(output[0], skip_special_tokens=True)[len(prompt):])
# bee
你也可以按下面这样加载 4 位模型:
from transformers import BitsAndBytesConfig
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16
)
model = PaligemmaForConditionalGeneration.from_pretrained(
model_id,
quantization_config=bnb_config,
device_map={"":0}
)
除了 4 位(或 8 位)加载,transformers 集成还支持 Hugging Face 生态中的其他工具,比如训练和推理脚本、序列化到 safetensors、与 trl 集成、以及用 text-generation-inference 运行模型生成。
详细推理过程
如果想自己编写预处理或训练代码,或者想更深入了解 PaliGemma 的内部机制,下面是输入图像和文本的处理步骤:
输入文本会正常进行标记化,并在开头添加一个 标记,末尾添加一个 \n 换行符。文本中原本的 标记会被替换为 256 个(对于 224×224 分辨率)额外的图像嵌入位置。如果是更大分辨率,图像嵌入数量会成倍增加——比如 448×448 对应 1024 个,896×896 对应 4096 个。
更大的图像意味着更长的输入序列,也就需要更多内存。在选择模型时务必注意这一点。对于细粒度任务(如 OCR),大图像可能更好,但大多数任务提升不明显。所以,在决定升级到更高分辨率之前,最好先在你的任务上测试一下。
整个“提示”会通过语言模型的文本嵌入层,生成每个标记 2048 维的标记嵌入。
与此同时,输入图像会被双三次插值缩放到目标尺寸(最小分辨率模型是 224×224),然后通过 SigLIP 图像编码器,生成每个 patch 1152 维的图像嵌入。接着,线性投影器将图像嵌入投影成 2048 维——和文本标记的维度一致。最终图像嵌入会与 文本嵌入合并,成为自回归文本生成的最终输入。
生成过程采用标准的自回归方式,对整个输入(image + bos + prompt + \n)使用完整块注意力,对生成的文本使用因果注意力掩码。
所有这些细节都被处理器和模型类自动处理了,所以你可以用前面示例中那样熟悉的高级 transformers API 进行推理。
微调
使用 bigvision
PaliGemma 是在 bigvision 代码库中训练的——这个库之前已经用于开发 BiT、原始 ViT、LiT、CapPa、SigLIP 等模型。项目的配置文件夹里有一个 README.md,预训练模型可以通过运行子文件夹中的配置文件进行迁移。如果你想迁移自己的模型,可以复制示例配置,按注释调整即可。
另外还有一个 Colab 笔记本,提供了在免费 T4 GPU 上运行的简化微调版本。为了适配有限的主机和 GPU 内存,Colab 中的代码只更新注意力层的权重(约 170M 参数),优化器使用 SGD 而不是 Adam。
使用 transformers
用 transformers 微调 PaliGemma 非常简单,还支持 QLoRA 或 LoRA 微调。下面我们先快速微调解码器,再展示如何切换到 QLoRA。
首先安装最新版 transformers:
pip install git+https://github.com/huggingface/transformers.git
然后登录认证:
from huggingface_hub import notebook_login
notebook_login()
本例使用 VQA v2 数据集,微调模型回答图像问题。加载数据集,只保留 question、multiple_choice_answer 和 image 列,并拆分为训练集和验证集:
from datasets import load_dataset
ds = load_dataset('HuggingFaceM4/VQA v2', split="train")
cols_remove = ["question_type", "answers", "answer_type", "image_id", "question_id"]
ds = ds.remove_columns(cols_remove)
ds = ds.train_test_split(test_size=0.1)
train_ds = ds["train"]
val_ds = ds["test"]
加载处理器,包含图像处理和标记化部分:
from transformers import PaliGemmaProcessor
model_id = "google/paligemma-3b-pt-224"
processor = PaliGemmaProcessor(model_id)
创建提示模板,让 PaliGemma 学习回答视觉问题。注意需要将标签中的填充设为 -100,并忽略图像标记:
device = "cuda"
image_token = processor.tokenizer.convert_tokens_to_ids("")
def collate_fn(examples):
texts = ["answer " + example["question"] + "\n" + example['multiple_choice_answer'] for example in examples]
images = [example["image"].convert("RGB") for example in examples]
tokens = processor(text=texts, images=images,
return_tensors="pt", padding="longest",
tokenize_newline_separately=False)
labels = tokens["input_ids"].clone()
labels[labels == processor.tokenizer.pad_token_id] = -100
labels[labels == image_token] = -100
tokens["labels"] = labels
tokens = tokens.to(torch.bfloat16).to(device)
return tokens
你可以直接加载模型,或者用 4 位 QLoRA。以下为直接加载并冻结图像编码器、仅微调解码器(如果你的图像属于特定领域,可能需要解冻图像编码器):
model = PaliGemmaForConditionalGeneration.from_pretrained(model_id, torch_dtype=torch.bfloat16).to(device)
for param in model.vision_tower.parameters():
param.requires_grad = False
for param in model.multi_modal_projector.parameters():
param.requires_grad = True
如果要使用 QLoRA 4 位模型,加上以下配置:
from transformers import BitsAndBytesConfig
from peft import get_peft_model, LoraConfig
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_type=torch.bfloat16
)
lora_config = LoraConfig(
r=8,
target_modules=["q_proj", "o_proj", "k_proj", "v_proj", "gate_proj", "up_proj", "down_proj"],
task_type="CAUSAL_LM",
)
model = PaliGemmaForConditionalGeneration.from_pretrained(model_id, quantization_config=bnb_config, device_map={"":0})
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
# trainable params: 11,298,816 || all params: 2,934,634,224 || trainable%: 0.38501616002417344
接下来初始化 Trainer 和 TrainingArguments。如果你做 QLoRA,建议把优化器设为 paged_adamw_8bit:
from transformers import TrainingArguments
args=TrainingArguments(
num_train_epochs=2,
remove_unused_columns=False,
per_device_train_batch_size=16,
gradient_accumulation_steps=4,
warmup_steps=2,
learning_rate=2e-5,
weight_decay=1e-6,
adam_beta2=0.999,
logging_steps=100,
optim="adamw_hf",
sa ve_strategy="steps",
sa ve_steps=1000,
push_to_hub=True,
sa ve_total_limit=1,
bf16=True,
report_to=["tensorboard"],
dataloader_pin_memory=False
)
最后创建 Trainer,传入数据集、数据整理函数和训练参数,调用 train() 开始训练:
from transformers import Trainer
trainer = Trainer(
model=model,
train_dataset=train_ds,
eval_dataset=val_ds,
data_collator=collate_fn,
args=args
)
trainer.train()
