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

相关文章

Java使用Mail构建邮件功能的完整指南

《Java使用Mail构建邮件功能的完整指南》JavaMailAPI是一个功能强大的工具,它可以帮助开发者轻松实现邮件的发送与接收功能,本文将介绍如何使用JavaMail发送和接收邮件,希望对大家有所... 目录1、简述2、主要特点3、发送样例3.1 发送纯文本邮件3.2 发送 html 邮件3.3 发送带

IDEA连接达梦数据库的详细配置指南

《IDEA连接达梦数据库的详细配置指南》达梦数据库(DMDatabase)作为国产关系型数据库的代表,广泛应用于企业级系统开发,本文将详细介绍如何在IntelliJIDEA中配置并连接达梦数据库,助力... 目录准备工作1. 下载达梦JDBC驱动配置步骤1. 将驱动添加到IDEA2. 创建数据库连接连接参数

JavaScript中的Map用法完全指南

《JavaScript中的Map用法完全指南》:本文主要介绍JavaScript中Map用法的相关资料,通过实例讲解了Map的创建、常用方法和迭代方式,还探讨了Map与对象的区别,并通过一个例子展... 目录引言1. 创建 Map2. Map 和对象的对比3. Map 的常用方法3.1 set(key, v

Java中使用注解校验手机号格式的详细指南

《Java中使用注解校验手机号格式的详细指南》在现代的Web应用开发中,数据校验是一个非常重要的环节,本文将详细介绍如何在Java中使用注解对手机号格式进行校验,感兴趣的小伙伴可以了解下... 目录1. 引言2. 数据校验的重要性3. Java中的数据校验框架4. 使用注解校验手机号格式4.1 @NotBl

使用Java发送邮件到QQ邮箱的完整指南

《使用Java发送邮件到QQ邮箱的完整指南》在现代软件开发中,邮件发送功能是一个常见的需求,无论是用户注册验证、密码重置,还是系统通知,邮件都是一种重要的通信方式,本文将详细介绍如何使用Java编写程... 目录引言1. 准备工作1.1 获取QQ邮箱的SMTP授权码1.2 添加JavaMail依赖2. 实现

Nginx实现动态封禁IP的步骤指南

《Nginx实现动态封禁IP的步骤指南》在日常的生产环境中,网站可能会遭遇恶意请求、DDoS攻击或其他有害的访问行为,为了应对这些情况,动态封禁IP是一项十分重要的安全策略,本篇博客将介绍如何通过NG... 目录1、简述2、实现方式3、使用 fail2ban 动态封禁3.1 安装 fail2ban3.2 配

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景

SQL Server数据库迁移到MySQL的完整指南

《SQLServer数据库迁移到MySQL的完整指南》在企业应用开发中,数据库迁移是一个常见的需求,随着业务的发展,企业可能会从SQLServer转向MySQL,原因可能是成本、性能、跨平台兼容性等... 目录一、迁移前的准备工作1.1 确定迁移范围1.2 评估兼容性1.3 备份数据二、迁移工具的选择2.1