微调 Florence-2 - 微软的尖端视觉语言模型
Florence-2 是微软于 2024 年 6 月发布的一个基础视觉语言模型。该模型极具吸引力,因为它尺寸很小 (0.2B 及 0.7B) 且在各种计算机视觉和视觉语言任务上表现出色。
Florence 开箱即用支持多种类型的任务,包括: 看图说话、目标检测、OCR 等等。虽然覆盖面很广,但仍有可能你的任务或领域不在此列,也有可能你希望针对自己的任务更好地控制模型输出。此时,你就需要微调了!
本文,我们展示了一个在 DocVQA 上微调 Florence 的示例。尽管原文宣称 Florence 2 支持视觉问答 (VQA) 任务,但最终发布的模型并未包含 VQA 功能。因此,我们正好拿这个任务练练手,看看我们能做点什么!
预训练细节与模型架构
Florence-2 架构
无论执行什么样的计算机视觉任务,Florence-2 都会将其建模为序列到序列的任务。Florence-2 以图像和文本作为输入,并输出文本。模型结构比较简单: 用 DaViT 视觉编码器将图像转换为视觉嵌入,并用 BERT 将文本提示转换为文本和位置嵌入; 然后,生成的嵌入由标准编码器 - 解码器 transformer 架构进行处理,最终生成文本和位置词元。Florence-2 的优势并非源自其架构,而是源自海量的预训练数据集。作者指出,市面上领先的计算机视觉数据集通常所含信息有限 - WIT 仅有图文对,
VQA 上的原始性能
我们尝试了各种方法来微调模型以使其适配 VQA (视觉问答) 任务的响应方式。迄今为止,我们发现最有效方法将其建模为图像区域描述任务,尽管其并不完全等同于 VQA 任务。看图说话任务虽然可以输出图像的描述性信息,但其不允许直接输入问题。
我们还测试了几个“不支持”的提示,例如 “<VQA>”、“<vqa>” 以及 “<Visual question answering>”。不幸的是,这些尝试的产生的结果都不可用。
微调后在 DocVQA 上的性能
我们使用 DocVQA 数据集的标准指标
我们创建了一个
-
🤗 空间 https://hf.co/spaces/andito/Florence-2-DocVQA -
The Cauldron https://hf.co/datasets/HuggingFaceM4/the_cauldron -
我们的 GitHub 页面 https://github.com/andimarafioti/florence2-finetuning
下图给出了微调前后的推理结果对比。你还可以至
微调前后的结果
微调细节
由原文我们可以知道,基础模型在预训练时使用的 batch size 为 2048,大模型在预训练时使用的 batch size 为 3072。另外原文还说: 与冻结图像编码器相比,使用未冻结的图像编码器进行微调能带来性能改进。
我们在低资源的情况下进行了多组实验,以探索模型如何在更受限的条件下进行微调。我们冻结了视觉编码器,并在
与此同时,我们还对更多资源的情况进行了实验,以 batch size 64 对整个模型进行了微调。在配备 8 张 H100 GPU 的集群上该训练过程花费了 70 分钟。你可以在
我们都发现 1e-6
的小学习率适合上述所有训练情形。如果学习率变大,模型将很快过拟合。
遛代码
如果你想复现我们的结果,可以在
-
Colab 地址 https://colab.research.google.com/drive/1hKDrJ5AH_o7I95PtZ9__VlCTNAo1Gjpf?usp=sharing -
DocVQA https://hf.co/datasets/HuggingFaceM4/DocumentVQA -
Florence-2-base-ft https://hf.co/microsoft/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 库中的 AutoModelForCausalLM
和 AutoProcessor
类来加载模型和处理器,并设 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()
以保存它们。微调后的模型在
-
模型链接 https://hf.co/HuggingFaceM4/Florence-2-DocVQA -
示例地址 https://hf.co/spaces/andito/Florence-2-DocVQA 演示示例
总结
本文,我们展示了如何有效地针对自定义数据集微调 Florence-2,以在短时间内在全新任务上取得令人眼前一亮的性能。对于那些希望在设备上或在生产环境中经济高效地部署小模型的人来说,该做法特别有价值。我们鼓励开源社区利用这个微调教程,探索 Florence-2 在各种新任务中的巨大潜力!我们迫不及待地想在 🤗 Hub 上看到你的模型!
有用资源
-
视觉语言模型详解 https://hf.co/blog/zh/vlms -
微调 Colab https://colab.research.google.com/drive/1hKDrJ5AH_o7I95PtZ9__VlCTNAo1Gjpf?usp=sharing -
微调 Github 代码库 https://github.com/andimarafioti/florence2-finetuning -
Florence-2 推理 Notebook https://hf.co/microsoft/Florence-2-large/blob/main/sample_inference.ipynb -
Florence-2 DocVQA 演示 https://hf.co/spaces/andito/Florence-2-DocVQA -
Florence-2 演示 https://hf.co/spaces/gokaygo
感谢 Pedro Cuenca 对本文的审阅。
英文原文: https://hf.co/blog/finetune-florence2
原文作者: Andres Marafioti,Merve Noyan,Piotr Skalski
译者: Matrix Yao (姚伟峰),英特尔深度学习工程师,工作方向为 transformer-family 模型在各模态数据上的应用及大规模模型的训练推理。
本文分享自微信公众号 - Hugging Face(gh_504339124f0f)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
图灵奖得主 Stonebraker 带你回顾数据库技术二十年的周期性演进
最近,数据库行业唯一在世的图灵奖得主Michael Stonebraker 和 CMU 知名教授 Andrew Pavlo (Andy) 教授联合发表了数据库论文《What Goes Around Comes Around... And Around》。过去 20 年,数据库领域诞生了众多新技术,这对数据库届的王炸组合对这些技术的看法是怎样的呢? 由图灵奖得主 Michael Stonebraker 和 CMU 知名教授 Andrew Pavlo (Andy)教授创作的最新论文《What Goes Around Comes Around...And Around...》,标题着实特别,“What Goes Around Comes Around”中文翻译过来是「种瓜得瓜,种豆得豆」、「因果报应」。而后面的 Around,暗示着这其实是一篇续作。 早在 2006 年,Stonebraker 教授和他的学生,UC 伯克利的 Joseph M. Hellerstein 合著了一篇《What Goes Around Comes Around》,而 Andy 教授也是这篇文章的粉丝。 这篇 20...
- 下一篇
Databend 开源周报第 153 期
Databend 是一款现代云数仓。专为弹性和高效设计,为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务:https://app.databend.cn 。 What's On In Databend 探索 Databend 本周新进展,遇到更贴近你心意的 Databend。 支持必须更改密码选项 Databend 现在已经支持在创建或修改用户时设置 must_change_password 选项,确保新用户在首次登录后必须更改密码。这一功能有助于提升账户安全性,防止初始密码泄露风险。 示例如下: CREATE USER user1 IDENTIFIED BY 'abc123' WITH MUST_CHANGE_PASSWORD = TRUE; 首次登录后,用户必须更改密码,才能执行其他操作: ALTER USER user() IDENTIFIED BY 'new_password'; 如果您想了解更多信息,欢迎联系 Databend 团队,或查看下面列出的资源。 PR #16031 | feat: support must change password option fo...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- 2048小游戏-低调大师作品
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- SpringBoot2全家桶,快速入门学习开发网站教程
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- CentOS7,8上快速安装Gitea,搭建Git服务器
- CentOS6,CentOS7官方镜像安装Oracle11G