人工智能学习

弗罗伦萨-2微调:图像理解模型

本文主要是介绍弗罗伦萨-2微调:图像理解模型,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

厌倦了回答基于图像的问题了吗?想象一下问一个模型“这张图片上的日期是什么?”,然后得到一个准确的答案。借助微软开发的Florence-2视觉语言模型,您就可以做到这一点。要充分发挥它的潜力,我们还需要对它进行微调!

这篇文章探索了Florence-2微调的奇妙世界,我们将探讨如何训练此强大的模型,使其能够以惊人的准确度理解与分析图像。

为什么微调?

为什么要微调?

想象 Florence-2 就像一个渴望学习的好学生。没有经过微调,就像给学生一本教材却不解释其中的概念一样,它可能连基本问题都难以回答。微调才是发挥 Florence-2 真正潜力的关键。

下面说说微调是啥:

  • 提供了针对性的训练:可以教导Florence-2执行特定任务,比如在图像中识别日期或在医学扫描中检测异常。
  • 提高准确性:微调可以精炼模型的理解能力,从而提供更准确和可靠的答案。
  • 解锁自定义应用:您可以创建符合特定需求和数据集的图像理解模型。
一步步调整Florence-2的攻略

让我们动手操作一下,探索使用“文档视觉问答(DocVQA)”数据集来微调Florence-2的过程。该数据集提供了图像和问题与其答案的配对。我们将使用这些数据来训练Florence-2从图像中提取信息,就像视频里展示的那样!

下面给大家分解一下步骤

  1. 搭建环境:
  • 使用带有GPU加速的平台。
  • 安装必要的库,比如datasetsflash-attention等(具体列表请参见视频描述)。
pip install datasets flash_attn timm einops transformers pillow huggingface_hub
  • 使用您的API令牌登录Hugging Face账号。
    运行 `huggingface-cli login`
    export HF_TOKEN=xxxxxxxxxx
    # 将你的 Hugging Face 令牌设置为 xxxxxxxxxx

2. 准备数据这一步:

  • 加载DocVQA数据集。
  • 创建一个名为collate的函数,将问题、答案和图像组合成适合处理的格式。
  • 使用DataLoader类准备训练和验证加载器,确保数据被转换为数值嵌入,使用processor

3. 优化模型:让模型更符合特定任务:

  • 定义一个 train_model 函数来管理训练过程。
  • 设置优化器、调度器和学习率。
  • 遍历每个 epoch,提供图像和问题数据给模型。
  • 监控训练过程中的损失并将模型保存到名为 Model_Checkpoints 的目录中。

4. 上传到Hugging Face 。

  • 使用 model.push_to_hubprocessor.push_to_hub 将您的训练好的模型和处理器上传到Hugging Face,让其他人也能使用。
    从datasets导入load_dataset()  
    从transformers导入AutoModelForCausalLM, AutoProcessor  
    导入torch  
    导入os  
    从torch.utils.data导入DataLoader  
    从tqdm导入tqdm  
    从transformers导入AdamW, AutoProcessor, get_scheduler  
    从torch.utils.data导入Dataset  

    # 1. 配置  
    data = load_dataset("HuggingFaceM4/DocumentVQA")  
    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')  
    torch.cuda.empty_cache()  

    # 2. 在训练模型之前  
    def run_example(task_prompt, text_input, image):  
        prompt = task_prompt + text_input  

        # 确保图片为RGB模式  
        if image.mode != "RGB":  
            image = image.convert("RGB")  

        inputs = processor(text=prompt, images=image, return_tensors="pt").to(device)  
        generated_ids = model.generate(  
            input_ids=inputs["input_ids"],  
            pixel_values=inputs["pixel_values"],  
            max_new_tokens=1024,  
            num_beams=3  
        )  
        generated_text = processor.batch_decode(generated_ids, skip_special_tokens=False)[0]  
        parsed_answer = processor.post_process_generation(generated_text, task=task_prompt, image_size=(image.width, image.height))  
        return parsed_answer  

    for idx in range(3):  
      print(run_example("DocVQA", 'What do you see in this image?', data['train'][idx]['image']))  

    # 3. 数据集准备  
    """我们需要构建数据集。请注意我们在构建提示时如何在问题前添加了一个新任务前缀 `<DocVQA>`。"""  
    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']  
            if image.mode != "RGB":  
                image = image.convert("RGB")  
            return question, first_answer, image  

    train_dataset = DocVQADataset(data['train'].select(range(1000)))  
    val_dataset = DocVQADataset(data['validation'].select(range(100)))  

    # 转换为Embeddings  
    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  

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

    # 4. 训练模型  
    def train_model(train_loader, val_loader, model, processor, epochs=10, lr=1e-6):  
        optimizer = AdamW(model.parameters(), lr=lr)  
        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 batch in tqdm(train_loader, desc=f"Training Epoch {epoch + 1}/{epochs}"):  
                i += 1  
                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  

                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()  

            avg_val_loss = val_loss / len(val_loader)  
            print(f"Average Validation Loss: {avg_val_loss}")  

            # 保存模型检查点  
            output_dir = f"./model_checkpoints/epoch_{epoch+1}"  
            os.makedirs(output_dir, exist_ok=True)  
            model.save_pretrained(output_dir)  
            processor.save_pretrained(output_dir)  

    # 注意:我们将冻结图像编码器以完成本教程。作者报告在解冻图像编码器时有所改进,但请注意这将导致更多资源消耗。  
    for param in model.vision_tower.parameters():  
      param.requires_grad = False  

    train_model(train_loader, val_loader, model, processor, epochs=1)  

    # 5. 保存到HuggingFace Hub  
    model.push_to_hub("USERNAME/Florence-2-FT-DocVQA")  
    processor.push_to_hub("USERNAME/Florence-2-FT-DocVQA")
测试训练模型

经过微调后,您会看到模型理解图片和正确回答问题的能力会有显著提高。

超越教程的内容

这个示例主要关注DocVQA,不过你可以将这些原则应用于其他各种任务,包括:

  • 医学影像分析:微调 Florence-2 模型以检测 X 光、CT 扫描或 MRI 图像中的异常。
  • 物体识别:训练模型识别图像中的特定对象,如识别不同类型车辆或动物。
  • 根据文本描述生成图像:使用微调后的 Florence-2 模型生成创意图片。
结论

微调 Florence-2 可开启图像理解的新篇章。通过用特定数据集来定制这个强大的模型,您可以创建高度准确的图像分析定制应用。

准备好探索佛罗伦萨2了吗?有任何疑问都可以随时联系,获取更多实用的AI教程。

电子邮件是: gunderichardson@gmail.com

LinkedIn:理查森·贡德

通过您的网络分享这篇博客文章,让更多人了解知识!

并分享您使用这个超赞的视觉语言模型进行调整的经验。让我们一起构建一个未来,在这个未来中,AI将帮助我们更好地理解图像!

这篇关于弗罗伦萨-2微调:图像理解模型的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!