PaliGemma – 谷歌尖端開放視覺語言模型

釋出於 2024 年 5 月 14 日
在 GitHub 上更新

更新於 2024 年 5 月 23 日:我們對 Transformers PaliGemma 的微調實現進行了一些更改,您可以在此 notebook 中找到。

PaliGemma 是谷歌新推出的視覺語言模型系列。PaliGemma 可以接收影像和文字並輸出文字。

谷歌團隊釋出了三種類型的模型:預訓練(pt)模型、混合模型和微調(ft)模型,每種模型都具有不同的解析度,並提供多種精度以方便使用。

所有模型都發布在 Hugging Face Hub 模型倉庫中,並附帶模型卡和許可證,並集成了 Transformers。

什麼是 PaliGemma?

PaliGemma (Github) 是一個視覺語言模型家族,其架構由 SigLIP-So400m 作為影像編碼器,Gemma-2B 作為文字解碼器。SigLIP 是一個能夠理解影像和文字的最新模型。與 CLIP 類似,它由一個影像編碼器和文字編碼器共同訓練而成。類似於 PaLI-3,組合的 PaliGemma 模型在影像-文字資料上進行預訓練,然後可以輕鬆地在下游任務(如影像字幕或指稱分割)上進行微調。Gemma 是一個僅解碼器模型,用於文字生成。將 SigLIP 的影像編碼器與 Gemma 結合使用線性介面卡,使得 PaliGemma 成為一個強大的視覺語言模型。

Architecture

PaliGemma 釋出了三種類型的模型

  • PT 檢查點:可以微調到下游任務的預訓練模型。
  • 混合檢查點:微調到混合任務的 PT 模型。它們適用於自由文字提示的通用推理,並且僅可用於研究目的。
  • FT 檢查點:一組微調模型,每個模型專門針對不同的學術基準。它們提供各種解析度,並且僅可用於研究目的。

這些模型有三種不同的解析度(`224x224`、`448x448`、`896x896`)和三種不同的精度(`bfloat16`、`float16` 和 `float32`)。每個倉庫都包含給定解析度和任務的檢查點,每個可用精度有三個修訂版本。每個倉庫的 `main` 分支包含 `float32` 檢查點,而 `bfloat16` 和 `float16` 修訂版本包含相應的精度。模型相容 🤗 Transformers 和原始 JAX 實現的倉庫是分開的。

正如後面詳細解釋的,高解析度模型需要更多的記憶體才能執行,因為輸入序列更長。它們可能有助於 OCR 等精細任務,但對於大多數任務而言,質量提升很小。224 版本對於大多數用途來說已經足夠了。

您可以在此 集合 中找到所有模型和空間。

模型能力

PaliGemma 是一個單輪視覺語言模型,不適用於對話式使用,並且在微調到特定用例時效果最佳。

您可以透過使用任務字首(如“detect”或“segment”)對模型進行條件化來配置模型將解決的任務。預訓練模型就是以這種方式訓練的,以使其具備豐富的R能力集(問答、字幕、分割等)。然而,它們並非設計用於直接使用,而是透過(微調)轉移到使用類似提示結構特定任務。對於互動式測試,您可以使用已在混合任務上進行微調的“mix”模型家族。

以下示例使用混合檢查點來演示一些功能。

影像字幕

PaliGemma 可以在被提示時為影像新增字幕。您可以使用混合檢查點嘗試各種字幕提示,以檢視它們如何響應。

Captioning

視覺問答

PaliGemma 可以回答關於影像的問題,只需將您的問題和影像一起傳遞即可。

VQA

檢測

PaliGemma 可以使用 `detect [entity]` 提示來檢測影像中的實體。它將以特殊 `` 標記的形式輸出邊界框座標的位置,其中 `value` 是表示歸一化座標的數字。每次檢測都由四個位置座標表示,順序為 *y_min, x_min, y_max, x_max*,後面是被檢測到的標籤。要將值轉換為座標,首先需要將數字除以 1024,然後將 `y` 乘以影像高度,將 `x` 乘以影像寬度。這將為您提供邊界框相對於原始影像大小的座標。

Detection

指稱表示式分割

PaliGemma 混合檢查點在給定 `segment [entity]` 提示時,也可以分割影像中的實體。這被稱為指稱表示式分割,因為我們使用自然語言描述來指代感興趣的實體。輸出是位置和分割標記的序列。位置標記表示如上所述的邊界框。分割標記可以進一步處理以生成分割掩碼。

Segmentation

文件理解

PaliGemma 混合檢查點具有出色的文件理解和推理能力。

ocrqa

混合基準

您可以在下方找到混合檢查點的分數。

模型 MMVP 準確率 POPE 準確率 (隨機/流行/對抗)
mix-224 46.00 88.00 86.63 85.67
mix-448 45.33 89.37 88.40 87.47

微調檢查點

除了預訓練模型和混合模型,谷歌還發布了已經轉移到各種任務的模型。它們對應於學術基準,研究界可以使用它們來比較它們的效能。下面,您可以找到一些精選的模型。這些模型也提供不同的解析度。您可以檢視任何模型的模型卡以獲取所有指標。

模型名稱 資料集/任務 在轉移任務中的得分
paligemma-3b-ft-vqav2-448 圖表理解 VQAV2 上的準確率 85.64%
paligemma-3b-ft-cococap-448 COCO 影像標題 144.6 CIDEr
paligemma-3b-ft-science-qa-448 科學問答 ScienceQA Img 子集(無 CoT)準確率 95.93%
paligemma-3b-ft-refcoco-seg-896 理解影像中特定物件的引用 refcoco 上的平均 IoU 為 76.94,refcoco+ 上的平均 IoU 為 72.18,refcocog 上的平均 IoU 為 72.22
paligemma-3b-ft-rsvqa-hr-224 遙感視覺問答 測試準確率 92.61%,測試 2 準確率 90.58%

演示

作為此次釋出的一部分,我們提供了一個 演示,它封裝了 big_vision 倉庫中的參考實現,並提供了一種簡單的方式來試用混合模型。

我們還提供了 相容 Transformers 的演示版本,以展示如何使用 PaliGemma Transformers API。

如何執行推理

要訪問 PaliGemma 模型,您需要接受 Gemma 的許可條款和條件。如果您已經擁有 Hugging Face 中其他 Gemma 模型的訪問許可權,則無需額外操作。否則,請訪問任何 PaliGemma 模型,如果您同意,請接受許可證。獲得訪問許可權後,您需要透過 notebook_loginhuggingface-cli login 進行身份驗證。登入後,即可開始使用!

您也可以立即 在此筆記本中 嘗試推理。

使用 Transformers

您可以使用 `PaliGemmaForConditionalGeneration` 類對任何已釋出的模型進行推理。只需使用內建處理器預處理提示和影像,然後將預處理後的輸入傳遞給生成器即可。

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 生態系統中的其他工具,例如

詳細推理過程

如果您想編寫自己的預處理或訓練程式碼,或者想更詳細地瞭解 PaliGemma 的工作原理,以下是輸入影像和文字所經歷的步驟。

輸入文字照常進行分詞。在開頭新增一個 `` 標記,並附加一個換行符 (`\n`)。這個換行符是模型訓練時輸入提示的重要組成部分,因此明確新增它可以確保它始終存在。分詞後的文字還會加上固定數量的 `` 標記。有多少個?這取決於輸入影像解析度和 SigLIP 模型使用的補丁大小。PaliGemma 模型預訓練時使用三種方形大小之一(224x224、448x448 或 896x896),並且始終使用 14 的補丁大小。因此,對於 224 模型,要預先新增的 `` 標記數量為 256 (`224/14 * 224/14`),對於 448 模型為 1024,對於 896 模型為 4096。

請注意,更大的影像會導致更長的輸入序列,因此需要更多的記憶體來處理模型的語言部分。在考慮使用哪種模型時請牢記這一點。對於 OCR 等更精細的任務,更大的影像可能有助於獲得更好的結果,但對於絕大多數任務而言,質量增益很小。在決定使用更大解析度之前,請務必在您的任務上進行測試!

這個完整的“提示”透過語言模型的文字嵌入層,並生成每個標記 2048 維的標記嵌入。

與此同時,輸入影像使用雙三次插值法調整大小到所需的輸入尺寸(對於解析度最小的模型是 224x224)。然後它透過 SigLIP 影像編碼器生成每個補丁 1152 維的影像嵌入。線性投影器在此發揮作用:影像嵌入被投影以獲得每個補丁 2048 維的表示,與從文字標記獲得的表示相同。最終的影像嵌入與 `` 文字嵌入合併,這是用於自迴歸文字生成的最終輸入。生成以自迴歸模式正常工作。它對完整輸入(`image + bos + prompt + \n`)使用全塊注意力,並對生成的文字使用因果注意力掩碼。

所有這些細節都在處理器和模型類中自動處理,因此可以使用前面示例中所示的熟悉的高階 Transformers API 執行推理。

微調

使用 big_vision

PaliGemma 在 big_vision 程式碼庫中進行了訓練。該程式碼庫已用於開發 BiT、原始 ViT、LiT、CapPa、SigLIP 等眾多模型。

專案配置資料夾 configs/proj/paligemma/ 包含一個 `README.md` 檔案。預訓練模型可以透過執行 transfers/ 子資料夾中的配置檔案進行遷移,我們所有的遷移結果都是透過執行其中提供的配置獲得的。如果您想遷移自己的模型,請複製示例配置 transfers/forkme.py 並按照註釋中的說明進行修改以適應您的用例。

還有一個 Colab `finetune_paligemma.ipynb`,它運行了一個可以在免費 T4 GPU 執行時上執行的*簡化微調*。為了適應有限的主機和 GPU 記憶體,Colab 中的程式碼只更新注意力層(1.7 億引數)中的權重,並使用 SGD(而不是 Adam)。

使用 Transformers

PaliGemma 的微調非常容易,這得益於 Transformers。還可以進行 QLoRA 或 LoRA 微調。在此示例中,我們將簡要微調解碼器,然後展示如何切換到 QLoRA 微調。我們將安裝最新版本的 Transformers 庫。

pip install transformers

就像在推理部分一樣,我們將使用 `notebook_login()` 進行身份驗證以訪問模型。

from huggingface_hub import notebook_login
notebook_login()

在此示例中,我們將使用 VQAv2 資料集,並微調模型以回答有關影像的問題。讓我們載入資料集。我們只使用 question、multiple_choice_answer 和 image 列,因此我們也將刪除其餘列。我們還將拆分資料集。

from datasets import load_dataset 
ds = load_dataset('HuggingFaceM4/VQAv2', 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.from_pretrained(model_id)

我們將建立一個提示模板,以 PliGemma 條件化以回答視覺問題。由於分詞器會填充輸入,我們需要將標籤中的填充設定為分詞器中填充標記之外的其他內容,以及影像標記。

import torch
device = "cuda"

image_token = processor.tokenizer.convert_tokens_to_ids("<image>")
def collate_fn(examples):
  texts = ["answer " + example["question"] for example in examples]
  labels= [example['multiple_choice_answer'] for example in examples]
  images = [example["image"].convert("RGB") for example in examples]
  tokens = processor(text=texts, images=images, suffix=labels,
                    return_tensors="pt", padding="longest")

  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

如果您想以 4 位載入模型進行 QLoRA,可以新增以下更改。

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",
            save_strategy="steps",
            save_steps=1000,
            push_to_hub=True,
            save_total_limit=1,
            bf16=True,
            report_to=["tensorboard"],
            dataloader_pin_memory=False
        )

初始化 `Trainer`,傳入資料集、資料整理函式和訓練引數,然後呼叫 `train()` 開始訓練。

trainer = Trainer(
        model=model,
        train_dataset=train_ds,
        eval_dataset=val_ds,
        data_collator=collate_fn,
        args=args
        )
trainer.train()

額外資源

我們衷心感謝 Omar SansevieroLucas BeyerXiaohua ZhaiMatthias Minderer 對本部落格文章的詳細審閱。我們感謝 Peter Robicheaux 在 Transformers 微調更改方面的幫助。

社群

image_23.jpg

註冊登入 發表評論

© . This site is unofficial and not affiliated with Hugging Face, Inc.