MoonDream2微调指南【最小VLM】

2024-05-24 09:28

本文主要是介绍MoonDream2微调指南【最小VLM】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在本指南中,我们将探讨如何使用计算机视觉数据集对完全开源的小型视觉语言模型 Moondream2 进行微调,以计数项目(这是 GPT-4V 一直表现不一致的任务),并以一种可以依赖输出用于生产应用程序的方式进行微调。

视觉语言模型 (VLM),有时也称为多模态模型,越来越受欢迎。随着 CLIP、GPT-4 with Vision 等技术的出现以及其他进步,从视觉输入中查询问题的能力变得比以往任何时候都更容易获得。

VLM 是机器学习的新前沿,随着新突破的出现,其性能也在不断提高。正如我们在 GPT-4 with Vision 和最近的 GPT-4o 中发现的那样,有些任务(例如计数)是 VLM 难以完成的。虽然可以理解,但由于训练成本和推理速度的限制,在每一项任务上都表现出色很困难,缺乏专家能力使得很难在生产用例中使用和依赖 VLM。

虽然有些多模态模型比其他模型更好,但许多模型在输出一致、可解析的格式方面存在问题。这给将 VLM 整合到应用程序和系统中带来了挑战。

NSDT工具推荐: Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 - REVIT导出3D模型插件 - 3D模型语义搜索引擎 - Three.js虚拟轴心开发包 - 3D模型在线减面 - STL模型在线切割 

1、什么是 Moondream2

Moondream2 是一个开源小型视觉语言模型,源代码位于 GitHub 上,vikhyatk制作。虽然它不是最先进的模型,但它能够以合理的速度和准确性在设备上本地运行,这使它成为 VLM 的一个引人注目的选择,值得尝试进行微调,看看它是否适合您的用例。与其他 VLM 相比,它的得分相对较高。它甚至在 VQAv2 上击败了最近发布的 GPT-4o,考虑到 Moondream2 的本地、开源和小得多的模型,这令人印象深刻。

Benchmark

Moondream2 (5/8/2024)

GPT-4o

Gemini 1.5 Pro

PaliGemma

VQAv2

79.0%

77.2%

73.2%

85.6%*

TextVQA

53.1%

78.0%

73.5%

73.15%*

与谷歌最近发布的另一款多模态开放 VLM PaliGemma 相比,该模型的规模要小得多,只有 18.6 亿,而 PaliGemma 的规模则为 80 亿。GPT-4o 和 Gemini 1.5 Pro 被怀疑比这两个模型大得多,但它们的具体规模尚不清楚。

  • Moondream2 开源许可

与一些因限制性条款而受到审查的“开放”模型(包括 PaliGemma)不同,Moondream2 是根据 Apache 2.0 许可开源的,也允许商业使用。

2、微调 Moondream2

对于本指南,我们将修改创建者提供的微调笔记本版本,并提高 Moondream2 在计数不同类型的美国货币时的性能。

首先,安装我们在整个过程中需要的软件包。

!pip install torch transformers timm einops datasets bitsandbytes accelerate roboflow supervision -q

3、收集用于微调 Moondream2 的数据

创建任何类型的机器学习模型都面临的挑战之一是获取高质量的训练数据。

由于我们想要微调 Moondream2 来计数硬币和钞票,因此我们将使用来自 Roboflow Universe 的这个数据集。你也可以构建和使用自己的 Roboflow 项目来执行此操作。

虽然这是一个对象检测数据集,但我们将展示如何使用它来微调 VLM。

首先,从 Universe 下载数据集:

from roboflow import Roboflow
from google.colab import userdatarf = Roboflow(api_key=userdata.get('ROBOFLOW_API_KEY'))
project = rf.workspace("alex-hyams-cosqx").project("cash-counter")
version = project.version(8)
dataset = version.download("coco")

然后,我们创建一个辅助类,供微调时使用。我们使用 Supervision 从我们下载的 COCO 格式导入数据集。

from torch.utils.data import Dataset
import json
from PIL import Image
import supervision as svclass RoboflowDataset(Dataset):def __init__(self, dataset_path, split='train'):self.split = splitsv_dataset = sv.DetectionDataset.from_coco(f"{dataset_path}/{split}/",f"{dataset_path}/{split}/_annotations.coco.json")self.dataset = sv_datasetdef __len__(self):return len(self.dataset)# ... other methods listed below (full code in Colab notebook)

然后,我们进入定义数据集的重要步骤。在此微调实现中,数据集是从对象读取的,其中 image 是数据集图像,数组 qa 包含一个带有问题和答案的对象,它将定义我们想要微调的提示/响应对。

    def __getitem__(self, idx):CLASSES = ["dime", "nickel", "penny", "quarter", "fifty", "five", "hundred", "one", "ten", "twenty"]# Retrieve the image/annotation info from the Supervision DetectionDataset image_name, annotations = list(self.dataset.annotations.items())[idx]image = self.dataset.images[image_name]# Finds the amount of each type of currency there is from the number of annotations there aremoney = {}for class_idx, money_type in enumerate(CLASSES):count = len(annotations[annotations.class_id == (class_idx+1)]) # Counts the number of annotations with that classif count == 0: continue; money[money_type] = count# Define the prompt/answerprompt = f"How many of each type of the currency ({', '.join(CLASSES)}) are there? Respond in JSON format with the currency type as the key and a integer count as the value."answer = json.dumps(money, indent=2) # Formats the JSON and makes it the answer# Return as the proper formatreturn {"image": Image.fromarray(image),"qa": [{"question": prompt,"answer": answer,}]}

以下代码检索数据并为我们数据的每个分割创建数据集类。

datasets = {"train": RoboflowDataset(dataset.location,"train"),"val": RoboflowDataset(dataset.location,"valid"),"test": RoboflowDataset(dataset.location,"test"),
}

4、Moondream2 的初步测试

现在我们有了数据集,我们可以开始测试它在没有微调的情况下的表现。我们可以通过运行以下命令来初始化 Moondream2:

import torch
from transformers import AutoTokenizer, AutoModelForCausalLMDEVICE = "cuda"
FLASHATTENTION = "flash_attention_2" # "flash_attention_2" if A100, RTX 3090, RTX 4090, H100, None if CPU
DTYPE = torch.float32 if DEVICE == "cpu" else torch.float16 # CPU doesn't support float16
MD_REVISION = "2024-04-02"tokenizer = AutoTokenizer.from_pretrained("vikhyatk/moondream2", revision=MD_REVISION)
moondream = AutoModelForCausalLM.from_pretrained("vikhyatk/moondream2", revision=MD_REVISION, trust_remote_code=True,attn_implementation=FLASHATTENTION,torch_dtype=DTYPE, device_map={"": DEVICE}
)

然后,我们传入一张美元钞票的图片,提示每种货币(一角硬币、五分硬币、一分硬币、四分之一美元硬币、五十美元硬币、五美元硬币、一百美元硬币、一美元硬币、十美元硬币、二十美元硬币)有多少种?以 JSON 格式响应,以货币类型为键,整数计数为值。:

sample = datasets['test'][0]md_answer = moondream.answer_question(moondream.encode_image(sample['image']),sample['qa'][0]['question'],tokenizer=tokenizer,
)sv.plot_image(sample['image'], (3,3))
print('Question:', sample['qa'][0]['question'])
print('Ground Truth:', sample['qa'][0]['answer'])
print('Moondream:', md_answer)

它返回了一个毫无帮助、支离破碎且不正确的答复:

来自数据集中其他图像的其他示例响应也不是特别有帮助、正确或一致:

  • [0.39, 0.28, 0.67, 0.52]
  • There is one silver coin in the image, which is a silver dollar coin. The coin is silver in color and features a profile of a man on it. The coin is worth one dollar.
  • 0
  • 1 dime, 1 nickel, 1 penny, 1 quarter, 1 fifty, 1 five, 1 hundred, 1 ten, 1 twenty, 1 dollar bill...

在评估了整个数据集的测试分割后,它达到了大约 0%,没有一个响应符合预期的地面实况输出。

5、微调 Moondream2 以计数对象

接下来,我们通过配置超参数来微调 Moondream2。在这里,我们将 epoch 数设置为 2,因为我们自己的测试证实,任何更少/更多的 epoch 都会导致欠拟合/过拟合。

修改了批处理大小以利用碰巧可用的更强大的 GPU。对于你可能在 Google Colab 中使用的 T4,我们建议使用 6。

其余参数保留为创建者的实现的默认值。

# Number of times to repeat the training dataset. Increasing this may cause the model to overfit or
# lose generalization due to catastrophic forgetting. Decreasing it may cause the model to underfit.
EPOCHS = 1# Number of samples to process in each batch. Set this to the highest value that doesn't cause an
# out-of-memory error. Decrease it if you're running out of memory. Batch size 8 currently uses around
# 15 GB of GPU memory during fine-tuning.
BATCH_SIZE = 24# Number of batches to process before updating the model. You can use this to simulate a higher batch
# size than your GPU can handle. Set this to 1 to disable gradient accumulation.
GRAD_ACCUM_STEPS = 1# Learning rate for the Adam optimizer. Needs to be tuned on a case-by-case basis. As a general rule
# of thumb, increase it by 1.4 times each time you double the effective batch size.
#
# Source: https://www.cs.princeton.edu/~smalladi/blog/2024/01/22/SDEs-ScalingRules/
#
# Note that we linearly warm the learning rate up from 0.1 * LR to LR over the first 10% of the
# training run, and then decay it back to 0.1 * LR over the last 90% of the training run using a
# cosine schedule.
LR = 3e-5# Whether to use Weights and Biases for logging training metrics.
USE_WANDB = False

一旦我们开始训练,训练时间将高度依赖于可用的系统,主要是 GPU。

6、评估微调的 Moondream2 结果

现在我们已经完成了训练过程,我们可以使用不属于微调数据的相同测试数据来评估微调模型的性能。

moondream.eval()correct = 0
for i, sample in enumerate(datasets['test']):md_answer = moondream.answer_question(moondream.encode_image(sample['image']),sample['qa'][0]['question'],tokenizer=tokenizer,)if md_answer == sample['qa'][0]['answer']:correct += 1if i < 21:sv.plot_image(sample['image'], (3,3))print('Ground Truth:', sample['qa'][0]['answer'])print('Moondream:', md_answer)print(f"\n\nAccuracy: {correct / len(datasets['test']) * 100:.2f}%")

查看样本,我们看到更加一致、可预测和准确的输出答案和输出格式。

经过微调的 Moondream2 对我们的第一张测试图像给出了更准确的答复:

不过,经过微调的 Moondream 版本仍然会存在计数错误的情况。

总体而言,在相同的测试数据集分割中,我们获得了 85.50% 的准确率。

7、结束语

通过本指南,我们能够利用计算机视觉数据集来微调视觉语言模型,以更一致、更准确的格式生成结果,使其易于解析以用于生产应用程序。这使 VLM 从一个有趣的实验级别变成了更大的计算机视觉系统中更有用的组件。


原文链接:MoonDream2微调指南 - BimAnt

这篇关于MoonDream2微调指南【最小VLM】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/998015

相关文章

Linux内核参数配置与验证详细指南

《Linux内核参数配置与验证详细指南》在Linux系统运维和性能优化中,内核参数(sysctl)的配置至关重要,本文主要来聊聊如何配置与验证这些Linux内核参数,希望对大家有一定的帮助... 目录1. 引言2. 内核参数的作用3. 如何设置内核参数3.1 临时设置(重启失效)3.2 永久设置(重启仍生效

Python列表去重的4种核心方法与实战指南详解

《Python列表去重的4种核心方法与实战指南详解》在Python开发中,处理列表数据时经常需要去除重复元素,本文将详细介绍4种最实用的列表去重方法,有需要的小伙伴可以根据自己的需要进行选择... 目录方法1:集合(set)去重法(最快速)方法2:顺序遍历法(保持顺序)方法3:副本删除法(原地修改)方法4:

PyInstaller打包selenium-wire过程中常见问题和解决指南

《PyInstaller打包selenium-wire过程中常见问题和解决指南》常用的打包工具PyInstaller能将Python项目打包成单个可执行文件,但也会因为兼容性问题和路径管理而出现各种运... 目录前言1. 背景2. 可能遇到的问题概述3. PyInstaller 打包步骤及参数配置4. 依赖

Nginx中配置HTTP/2协议的详细指南

《Nginx中配置HTTP/2协议的详细指南》HTTP/2是HTTP协议的下一代版本,旨在提高性能、减少延迟并优化现代网络环境中的通信效率,本文将为大家介绍Nginx配置HTTP/2协议想详细步骤,需... 目录一、HTTP/2 协议概述1.HTTP/22. HTTP/2 的核心特性3. HTTP/2 的优

在React中引入Tailwind CSS的完整指南

《在React中引入TailwindCSS的完整指南》在现代前端开发中,使用UI库可以显著提高开发效率,TailwindCSS是一个功能类优先的CSS框架,本文将详细介绍如何在Reac... 目录前言一、Tailwind css 简介二、创建 React 项目使用 Create React App 创建项目

SpringBoot3实现Gzip压缩优化的技术指南

《SpringBoot3实现Gzip压缩优化的技术指南》随着Web应用的用户量和数据量增加,网络带宽和页面加载速度逐渐成为瓶颈,为了减少数据传输量,提高用户体验,我们可以使用Gzip压缩HTTP响应,... 目录1、简述2、配置2.1 添加依赖2.2 配置 Gzip 压缩3、服务端应用4、前端应用4.1 N

使用Jackson进行JSON生成与解析的新手指南

《使用Jackson进行JSON生成与解析的新手指南》这篇文章主要为大家详细介绍了如何使用Jackson进行JSON生成与解析处理,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 核心依赖2. 基础用法2.1 对象转 jsON(序列化)2.2 JSON 转对象(反序列化)3.

Java利用JSONPath操作JSON数据的技术指南

《Java利用JSONPath操作JSON数据的技术指南》JSONPath是一种强大的工具,用于查询和操作JSON数据,类似于SQL的语法,它为处理复杂的JSON数据结构提供了简单且高效... 目录1、简述2、什么是 jsONPath?3、Java 示例3.1 基本查询3.2 过滤查询3.3 递归搜索3.4

Spring Boot结成MyBatis-Plus最全配置指南

《SpringBoot结成MyBatis-Plus最全配置指南》本文主要介绍了SpringBoot结成MyBatis-Plus最全配置指南,包括依赖引入、配置数据源、Mapper扫描、基本CRUD操... 目录前言详细操作一.创建项目并引入相关依赖二.配置数据源信息三.编写相关代码查zsRArly询数据库数

SpringBoot启动报错的11个高频问题排查与解决终极指南

《SpringBoot启动报错的11个高频问题排查与解决终极指南》这篇文章主要为大家详细介绍了SpringBoot启动报错的11个高频问题的排查与解决,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一... 目录1. 依赖冲突:NoSuchMethodError 的终极解法2. Bean注入失败:No qu