微调 Florence-2 - 微软的尖端视觉语言模型

florence · 浏览次数 : 2

小编点评

总结: 本文介绍了一种针对自定义数据集微调 Florence-2 的方法,以在短时间内在新任务上取得令人眼前一亮的性能。文章首先概述了 Florence-2 模型的特点和应用场景,然后详细介绍了如何在该模型上进行微调,最后提供了一些有用的资源和教程链接。 1. Florence-2 模型简介: Florence-2 是微软于 2024 年发布的一个基础视觉语言模型,具有较小的模型尺寸和出色的性能,适用于多种计算机视觉和视觉语言任务。 2. 微调方法: 文章展示了如何在自定义数据集上对 Florence-2 进行微调,以适应不同的任务。作者提到了一种有效的微调方法,即将任务建模为图像区域描述任务,并在 VQA 任务上进行微调。 3. 数据集和预训练: 为了训练 Florence-2,作者创建了一个新的数据集 FLD-5B,其中包含丰富的图像信息。此外,还使用了大量的预训练数据集,如 WIT 和 SA-1B。 4. 微调过程: 微调过程中,作者冻结了视觉编码器以降低计算成本,并使用不同的批量大小和 GPU 设备进行训练。通过调整学习率和优化器,作者在不同的条件下进行了多组实验。 5. 结果和评估: 经过微调后,作者在 DocVQA 数据集上取得了不错的性能。同时,文章还提供了一个演示链接,供用户亲自试用微调后的模型。 6. 有用资源和教程: 文章最后提供了相关的研究资源、教程和代码库,以便读者进一步学习和探索 Florence-2 在各种新任务中的应用潜力。 7. 模型推理: 为了方便用户使用,文章还提供了一个推理 Notebook,供用户在本地环境中运行 Florence-2 模型。

正文

Florence-2 是微软于 2024 年 6 月发布的一个基础视觉语言模型。该模型极具吸引力,因为它尺寸很小 (0.2B 及 0.7B) 且在各种计算机视觉和视觉语言任务上表现出色。

Florence 开箱即用支持多种类型的任务,包括: 看图说话、目标检测、OCR 等等。虽然覆盖面很广,但仍有可能你的任务或领域不在此列,也有可能你希望针对自己的任务更好地控制模型输出。此时,你就需要微调了!

本文,我们展示了一个在 DocVQA 上微调 Florence 的示例。尽管原文宣称 Florence 2 支持视觉问答 (VQA) 任务,但最终发布的模型并未包含 VQA 功能。因此,我们正好拿这个任务练练手,看看我们能做点什么!

预训练细节与模型架构

Florence-2 架构

Florence-2 架构

无论执行什么样的计算机视觉任务,Florence-2 都会将其建模为序列到序列的任务。Florence-2 以图像和文本作为输入,并输出文本。模型结构比较简单: 用 DaViT 视觉编码器将图像转换为视觉嵌入,并用 BERT 将文本提示转换为文本和位置嵌入; 然后,生成的嵌入由标准编码器 - 解码器 transformer 架构进行处理,最终生成文本和位置词元。Florence-2 的优势并非源自其架构,而是源自海量的预训练数据集。作者指出,市面上领先的计算机视觉数据集通常所含信息有限 - WIT 仅有图文对,SA-1B 仅有图像及相关分割掩码。因此,他们决定构建一个新的 FLD-5B 数据集,其中的每个图像都包含最广泛的信息 - 目标框、掩码、描述文本及标签。在创建数据集时,很大程度采用了自动化的过程,作者使用现成的专门任务模型,并用一组启发式规则及质检过程来清理所获得的结果。最终生成的用于预训练 Florence-2 模型的新数据集中包含了 1.26 亿张图像、超过 50 亿个标注。

VQA 上的原始性能

我们尝试了各种方法来微调模型以使其适配 VQA (视觉问答) 任务的响应方式。迄今为止,我们发现最有效方法将其建模为图像区域描述任务,尽管其并不完全等同于 VQA 任务。看图说话任务虽然可以输出图像的描述性信息,但其不允许直接输入问题。

我们还测试了几个“不支持”的提示,例如 “<VQA>”、“<vqa>” 以及 “<Visual question answering>”。不幸的是,这些尝试的产生的结果都不可用。

微调后在 DocVQA 上的性能

我们使用 DocVQA 数据集的标准指标 Levenshtein 相似度 来测量性能。微调前,模型在验证集上的输出与标注的相似度为 0,因为模型输出与标注差异不小。对训练集进行 7 个 epoch 的微调后,验证集上的相似度得分提高到了 57.0。

我们创建了一个 🤗 空间 以演示微调后的模型。虽然该模型在 DocVQA 上表现良好,但在一般文档理解方面还有改进的空间。但我们仍然认为,它成功地完成了任务,展示了 Florence-2 对下游任务进行微调的潜力。我们建议大家使用 The Cauldron 数据集对 Florence-2 进行微调,大家可以在 我们的 GitHub 页面 上找到必要的代码。

下图给出了微调前后的推理结果对比。你还可以至 此处 亲自试用模型。

微调前后的结果

微调细节

由原文我们可以知道,基础模型在预训练时使用的 batch size 为 2048,大模型在预训练时使用的 batch size 为 3072。另外原文还说: 与冻结图像编码器相比,使用未冻结的图像编码器进行微调能带来性能改进。

我们在低资源的情况下进行了多组实验,以探索模型如何在更受限的条件下进行微调。我们冻结了视觉编码器,并在 Colab 的分别使用单张 A100 GPU (batch size 6) 、单张 T4 (batch size 1) 顺利完成微调。

与此同时,我们还对更多资源的情况进行了实验,以 batch size 64 对整个模型进行了微调。在配备 8 张 H100 GPU 的集群上该训练过程花费了 70 分钟。你可以在 这里 找到我们训得的模型。

我们都发现 1e-6 的小学习率适合上述所有训练情形。如果学习率变大,模型将很快过拟合。

遛代码

如果你想复现我们的结果,可以在 此处 找到我们的 Colab 微调笔记本。下面,我们遛一遍在 DocVQA 上微调 Florence-2-base-ft 模型。

我们从安装依赖项开始。

!pip install -q datasets flash_attn timm einops

接着,从 Hugging Face Hub 加载 DocVQA 数据集。

import torch
from datasets import load_dataset

data = load_dataset("HuggingFaceM4/DocumentVQA")

我们可以使用 transformers 库中的 AutoModelForCausalLMAutoProcessor 类来加载模型和处理器,并设 trust_remote_code=True ,因为该模型尚未原生集成到 transformers 中,因此需要使用自定义代码。我们还会冻结视觉编码器,以降低微调成本。

from transformers import AutoModelForCausalLM, AutoProcessor
import torch

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

model = AutoModelForCausalLM.from_pretrained(
    "microsoft/Florence-2-base-ft",
    trust_remote_code=True,
    revision='refs/pr/6'
).to(device)
processor = AutoProcessor.from_pretrained("microsoft/Florence-2-base-ft",
    trust_remote_code=True, revision='refs/pr/6')

for param in model.vision_tower.parameters():
  param.is_trainable = False

现在开始微调模型!我们构建一个训练 PyTorch 数据集,并为数据集中的每个问题添加 \<DocVQA\> 前缀。

import torch from torch.utils.data import Dataset

class DocVQADataset(Dataset):

    def __init__(self, data):
        self.data = data
        
    def __len__(self):
        return len(self.data)
        
    def __getitem__(self, idx):
        example = self.data[idx]
        question = "<DocVQA>" + example['question']
        first_answer = example['answers'][0]
        image = example['image'].convert("RGB")
        return question, first_answer, image

接着,构建数据整理器,从数据集样本构建训练 batch,以用于训练。在 40GB 内存的 A100 中,batch size 可设至 6。如果你在 T4 上进行训练,batch size 就只能是 1。

import os
from torch.utils.data import DataLoader
from tqdm import tqdm
from transformers import AdamW, get_scheduler

def collate_fn(batch):
    questions, answers, images = zip(*batch)
    inputs = processor(text=list(questions), images=list(images), return_tensors="pt", padding=True).to(device)
    return inputs, answers

train_dataset = DocVQADataset(data['train'])
val_dataset = DocVQADataset(data['validation'])
batch_size = 6
num_workers = 0

train_loader = DataLoader(train_dataset, batch_size=batch_size,
                          collate_fn=collate_fn, num_workers=num_workers, shuffle=True)
val_loader = DataLoader(val_dataset, batch_size=batch_size,
                          collate_fn=collate_fn, num_workers=num_workers)

开始训练模型:

epochs = 7
optimizer = AdamW(model.parameters(), lr=1e-6)
num_training_steps = epochs * len(train_loader)

lr_scheduler = get_scheduler(name="linear", optimizer=optimizer,
                              num_warmup_steps=0, num_training_steps=num_training_steps,)

for epoch in range(epochs):
    model.train()
    train_loss = 0
    i = -1
    for inputs, answers in tqdm(train_loader, desc=f"Training Epoch {epoch + 1}/{epochs}"):
        i += 1
        input_ids = inputs["input_ids"]
        pixel_values = inputs["pixel_values"]
        labels = processor.tokenizer(text=answers, return_tensors="pt", padding=True, return_token_type_ids=False).input_ids.to(device)
        outputs = model(input_ids=input_ids, pixel_values=pixel_values, labels=labels)
        loss = outputs.loss
        loss.backward()
        optimizer.step()
        lr_scheduler.step()
        optimizer.zero_grad()
        train_loss += loss.item()
    avg_train_loss = train_loss / len(train_loader)
    print(f"Average Training Loss: {avg_train_loss}")

    model.eval()
    val_loss = 0
    with torch.no_grad():
        for batch in tqdm(val_loader, desc=f"Validation Epoch {epoch + 1}/{epochs}"):
            inputs, answers = batch
            input_ids = inputs["input_ids"]
            pixel_values = inputs["pixel_values"]
            labels = processor.tokenizer(text=answers, return_tensors="pt", padding=True, return_token_type_ids=False).input_ids.to(device)
            outputs = model(input_ids=input_ids, pixel_values=pixel_values, labels=labels)
            loss = outputs.loss
            val_loss += loss.item()

      print(val_loss / len(val_loader))

你可以分别对模型和处理器调用 save_pretrained() 以保存它们。微调后的模型在 此处,你还可以在 此处 找到其演示。

演示示例

总结

本文,我们展示了如何有效地针对自定义数据集微调 Florence-2,以在短时间内在全新任务上取得令人眼前一亮的性能。对于那些希望在设备上或在生产环境中经济高效地部署小模型的人来说,该做法特别有价值。我们鼓励开源社区利用这个微调教程,探索 Florence-2 在各种新任务中的巨大潜力!我们迫不及待地想在 🤗 Hub 上看到你的模型!

有用资源

我们感谢 Pedro Cuenca 对本文的审阅。


英文原文: https://hf.co/blog/finetune-florence2

原文作者: Andres Marafioti,Merve Noyan,Piotr Skalski

译者: Matrix Yao (姚伟峰),英特尔深度学习工程师,工作方向为 transformer-family 模型在各模态数据上的应用及大规模模型的训练推理。

与微调 Florence-2 - 微软的尖端视觉语言模型相似的内容:

微调 Florence-2 - 微软的尖端视觉语言模型

Florence-2 是微软于 2024 年 6 月发布的一个基础视觉语言模型。该模型极具吸引力,因为它尺寸很小 (0.2B 及 0.7B) 且在各种计算机视觉和视觉语言任务上表现出色。 Florence 开箱即用支持多种类型的任务,包括: 看图说话、目标检测、OCR 等等。虽然覆盖面很广,但仍有可

基于 P-Tuning v2 进行 ChatGLM2-6B 微调实践

微调类型简介 1. SFT监督微调:适用于在源任务中具有较高性能的模型进行微调,学习率较小。常见任务包括中文实体识别、语言模型训练、UIE模型微调。优点是可以快速适应目标任务,但缺点是可能需要较长的训练时间和大量数据。 2. LoRA微调:通过高阶矩阵秩的分解减少微调参数量,不改变预训练模型参数,新

LLM微调方法(Efficient-Tuning)六大主流方法:思路讲解&优缺点对比[P-tuning、Lora、Prefix tuing等]

LLM微调方法(Efficient-Tuning)六大主流方法:思路讲解&优缺点对比[P-tuning、Lora、Prefix tuing等] 由于LLM参数量都是在亿级以上,少则数十亿,多则数千亿。当我们想在用特定领域的数据微调模型时,如果想要full-tuning所有模型参数,看着是不太实际,一

StarCoder2-Instruct: 完全透明和可自我对齐的代码生成

指令微调 是一种技术,它能让大语言模型 (LLMs) 更好地理解和遵循人类的指令。但是,在编程任务中,大多数模型的微调都是基于人类编写的指令 (这需要很高的成本) 或者是由大型专有 LLMs 生成的指令 (可能不允许使用)。 我们推出了一个叫做 StarCoder2-15B-Instruct-v0.

[转帖]指令微调数据集整理

`https://blog.csdn.net/dzysunshine/article/details/130870398` 文章目录 开源指令数据集斯坦福数据链家数据Baize(基于少量种子问题的对话数据) 垂直领域数据集医疗领域的英文数据医疗领域的中文数据法律领域中文数据 COIG数据集(可商用的

煤矿安全大模型:微调internlm2模型实现针对煤矿事故和煤矿安全知识的智能问答

煤矿安全大模型————矿途智护者 使用煤矿历史事故案例,事故处理报告、安全规程规章制度、技术文档、煤矿从业人员入职考试题库等数据,微调internlm2模型实现针对煤矿事故和煤矿安全知识的智能问答。 本项目简介: 近年来,国家对煤矿安全生产的重视程度不断提升。为了确保煤矿作业的安全,提高从业人员的安

大模型高效微调-LoRA原理详解和训练过程深入分析

博客首发于我的知乎,详见:https://zhuanlan.zhihu.com/p/702629428 一、LoRA原理 LoRA(Low-Rank Adaptation of LLMs),即LLMs的低秩适应,是参数高效微调最常用的方法。 LoRA的本质就是用更少的训练参数来近似LLM全参数微调所

LLM实战:LLM微调加速神器-Unsloth + Qwen1.5

本文主要是使用unsloth框架针对Qwen1.5的高效微调实验,提供了详细的对比代码以及不同维度的对比分析结果。

LLM实战:LLM微调加速神器-Unsloth + LLama3

1. 背景 五一结束后,本qiang~又投入了LLM的技术海洋中,本期将给大家带来LLM微调神器:Unsloth。 正如Unsloth官方的对外宣贯:Easily finetune & train LLMs; Get faster with unsloth。微调训练LLM,可以显著提升速度,其次显存

大模型高效微调详解-从Adpter、PrefixTuning到LoRA

一、背景 目前NLP主流范式是在大量通用数据上进行预训练语言模型训练,然后再针对特定下游任务进行微调,达到领域适应(迁移学习)的目的。 指令微调是预训练语言模型微调的主流范式 其目的是尽量让下游任务的形式尽量接近预训练任务,从而减少下游任务和预训练任务之间的Gap, 实现预训练语言模型适应下游任务,