如何微调Segment Anything Model

文章目录

  • 什么是SAM?
  • 什么是模型微调?
  • 为什么要微调模型?
  • 如何微调 Segment Anything 模型
    • 背景与架构
    • 创建自定义数据集
    • 输入数据预处理
    • 训练设置
    • 循环训练
    • 保存检查点并从中启动模型
  • 下游应用程序的微调

随着 Meta 上周发布的 Segment Anything Model (SAM),计算机视觉迎来了它的 ChatGPT 时刻。SAM 训练了超过 110 亿个分割掩码,是预测 AI 用例而非生成 AI 的基础模型。虽然它在对广泛的图像模式和问题空间进行分割的能力方面表现出了令人难以置信的灵活性,但它在发布时没有“微调”功能。
本教程将概述使用掩码解码器微调 SAM 的一些关键步骤,特别是描述 SAM 中使用哪些函数对数据进行预处理/后处理,使其处于良好状态以进行微调。

什么是SAM?

Segment Anything Model (SAM) 是由 Meta AI 开发的一种分割模型。它被认为是计算机视觉的第一个基础模型。SAM 在包含数百万图像和数十亿掩码的庞大数据集上进行了训练,使其非常强大。顾名思义,SAM 能够为各种图像生成准确的分割掩码。Sam 的设计允许它考虑人类提示,这使得它对于 Human In The Loop 注释特别强大。这些提示可以是多模式的:它们可以是要分割区域上的点、要分割对象周围的边界框或关于应该分割什么的文本提示。

该模型分为 3 个组件:图像编码器、提示编码器和掩码解码器。

在这里插入图片描述

图像编码器为被分割的图像生成嵌入,而提示编码器为提示生成嵌入。图像编码器是模型中特别大的组件。这与轻量级掩码解码器形成对比,轻量级掩码解码器根据嵌入预测分割掩码。Meta AI 已将在 Segment Anything 10 亿掩码 (SA-1B) 数据集上训练的模型的权重和偏差用作模型检查点。在此处的解释器博客文章中了解有关 Segment Anything 工作原理的更多信息。

什么是模型微调?

公开可用的最先进模型具有自定义架构,通常提供预训练模型权重。如果这些架构在没有权重的情况下提供,那么用户将需要从头开始训练模型,用户将需要使用大量数据集来获得最先进的性能。

模型微调是采用预训练模型(架构+权重)并显示特定用例数据的过程。这通常是模型以前没有见过的数据,或者在其原始训练数据集中代表性不足的数据。

微调模型和从头开始的区别在于权重和偏差的起始值。如果我们从头开始训练,这些将根据某种策略随机初始化。在这样的初始配置中,模型对手头的任务“一无所知”并且表现不佳。通过使用预先存在的权重和偏差作为起点,我们可以“微调”权重和偏差,以便我们的模型在我们的自定义数据集上更好地工作。例如:学习识别猫的信息(边缘检测、计数爪子)将对识别狗有用。

为什么要微调模型?

微调模型的目的是在预训练模型以前没有见过的数据上获得更高的性能。例如,在从手机摄像头收集的广泛数据集上训练的图像分割模型将主要从水平视角看到图像。

如果我们尝试将此模型用于从垂直角度拍摄的卫星图像,它的性能可能不会那么好。如果我们试图分割屋顶,该模型可能不会产生最佳结果。预训练很有用,因为模型已经学会了一般如何分割对象,所以我们想利用这个起点来构建一个可以准确分割屋顶的模型。此外,我们的自定义数据集可能不会有数百万个示例,因此我们希望微调而不是从头开始训练模型。

微调是可取的,这样我们就可以在特定用例上获得更好的性能,而不必承担从头开始训练模型的计算成本。

如何微调 Segment Anything 模型

背景与架构

我们在介绍部分概述了 SAM 体系结构。图像编码器具有包含许多参数的复杂架构。为了微调模型,我们将重点放在轻量级的掩码解码器上是有意义的,因此微调更容易、更快、内存效率更高。

为了微调 SAM,我们需要提取其架构的底层部分(图像和提示编码器、掩码解码器)。我们不能使用SamPredictor.predict (链接) 有两个原因:

  • 我们只想微调掩码解码器
  • 这个函数调用SamPredictor.predict_torch,它有 @torch.no_grad()装饰器(链接),它阻止我们计算梯度。

因此,我们需要检查SamPredictor.predict函数并调用适当的函数,并在我们想要微调的部分(掩码解码器)上启用梯度计算。这样做也是了解更多有关 SAM 工作原理的好方法。

创建自定义数据集

我们需要三件事来微调我们的模型:

  • 在其上绘制分割的图像
  • 分割真值掩码
  • 提示输入模型,我正在使用边界框

我选择了印章验证数据集(链接),因为它包含 SAM 在其训练中可能没有看到的数据(即文档上的印章)。我可以通过使用预先训练的权重运行推理来验证它在这个数据集上表现良好,但并不完美。ground truth masks 也非常精确,这将使我们能够计算准确的损失。最后,该数据集包含分割掩码周围的边界框,我们可以将其用作 SAM 的提示。示例图像如下所示。这些边界框与人工注释者在寻找生成分段时所经历的工作流程非常吻合。

在这里插入图片描述

输入数据预处理

我们需要预处理从 numpy 数组到 pytorch 张量的扫描。为此,我们可以关注SamPredictor.set_image (链接) 和SamPredictor.set_torch_image (链接) 内部发生的事情,它们对图像进行预处理。首先,我们可以使用utils.transform.ResizeLongestSide来调整图像大小,因为这是预测器内部使用的转换器 ( link )。然后我们可以将图像转换为pytorch张量,并使用 SAM 预处理方法(链接)完成预处理。

训练设置

我们下载vit_b模型的模型检查点并将它们加载到:

sam_model = sam_model_registry['vit_b'](checkpoint='sam_vit_b_01ec64.pth')
我们可以使用默认设置 Adam 优化器,并指定要调整的参数是掩码解码器的参数:

optimizer = torch.optim.Adam(sam_model.mask_decoder.parameters())
同时,我们可以设置我们的损失函数,例如Mean Squared Error

loss_fn = torch.nn.MSELoss()

循环训练

在主训练循环中,我们将迭代我们的数据项,生成掩码并将它们与我们的真实掩码进行比较,以便我们可以根据损失函数优化模型参数。

在此示例中,我们使用 GPU 进行训练,因为它比使用 CPU 快得多。在适当的张量上使用.to(device)非常重要,以确保我们不会在 CPU 上使用某些张量而在 GPU 上使用其他张量。

我们希望通过将编码器包装在torch.no_grad()上下文管理器中来嵌入图像,否则我们将遇到内存问题,以及我们不希望微调图像编码器的事实。

with torch.no_grad():
	image_embedding = sam_model.image_encoder(input_image)

我们还可以在 no_grad 上下文管理器中生成提示嵌入。我们使用我们的边界框坐标,转换为 pytorch 张量。

with torch.no_grad():
      sparse_embeddings, dense_embeddings = sam_model.prompt_encoder(
          points=None,
          boxes=box_torch,
          masks=None,
      )

最后,我们可以生成掩码。请注意,这里我们处于单一掩码生成模式(与通常输出的 3 个掩码形成对比)。

low_res_masks, iou_predictions = sam_model.mask_decoder(
  image_embeddings=image_embedding,
  image_pe=sam_model.prompt_encoder.get_dense_pe(),
  sparse_prompt_embeddings=sparse_embeddings,
  dense_prompt_embeddings=dense_embeddings,
  multimask_output=False,
)

这里的最后一步是将蒙版放大回原始图像大小,因为它们的分辨率很低。我们可以使用Sam.postprocess_masks来实现这一点。我们还希望根据预测的掩码生成二进制掩码,以便我们可以将它们与我们的基本事实进行比较。为了不破坏反向传播,使用torch功能很重要。

upscaled_masks = sam_model.postprocess_masks(low_res_masks, input_size, original_image_size).to(device)

from torch.nn.functional import threshold, normalize

binary_mask = normalize(threshold(upscaled_masks, 0.0, 0)).to(device)

最后我们可以计算损失并运行优化步骤:

loss = loss_fn(binary_mask, gt_binary_mask)
optimizer.zero_grad()
loss.backward()
optimizer.step()

通过在多个时期和批次上重复此操作,我们可以微调 SAM 解码器。

保存检查点并从中启动模型

一旦我们完成训练并对性能提升感到满意,我们可以使用:

torch.save(model.state_dict(), PATH)

保存调优模型的状态字典。当我们想要对与我们用于微调模型的数据相似的数据执行推理时,我们可以加载这个状态字典。

您可以在此处找到 Colab Notebook,其中包含微调 SAM 所需的所有代码。如果您想要一个开箱即用的完整解决方案,请继续阅读!

下游应用程序的微调

虽然 SAM 目前不提供开箱即用的微调,但我们正在构建与 Encord 平台集成的自定义微调器。如本文所示,我们微调解码器以实现此目的。这可以在 Web 应用程序中作为开箱即用的一键式程序使用,其中会自动设置超参数。
在这里插入图片描述
原SAM 预测结果:

在这里插入图片描述

由模型的微调版本生成的掩码:

在这里插入图片描述
我们可以看到这个面具比原来的面具更紧。这是对邮票验证数据集中的一小部分图像进行微调,然后在以前未见过的示例上运行调优模型的结果。通过进一步的训练和更多的例子,我们可以获得更好的结果。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/13587.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

线程等待其他线程执行同步类CountDownLatch

文章目录 前言核心原理源码解析同步源码分析await源码分析countDown源码分析 实战演示1、创建演示代码2、创建测试用例3、测试结果演示 写在最后 前言 大家都知道多线程在我们实际编码过程中运用很多,很多情况我们需要靠多线程来提升系统性能。但是有些时候我们需要…

C语言开发环境搭建及调试

C简介 可移植 标准C C/C (系统硬件操作的接口,windows,Linux不一样) 跨平台 Java Python 下载 去官网选择Visual Studio 2019下载 安装过程中勾选使用C的桌面开发 安装好之后点击创建新项目——空项目 位置最好放在根目录下&…

【vue2】近期bug收集与整理02

⭐【前言】 在使用vue2构建页面时候,博主遇到的问题难点以及最终的解决方案。 🥳博主:初映CY的前说(前端领域) 🤘本文核心:博主遇到的问题与解决思路 目录 ⭐数据枚举文件的使用⭐elementUI中分页组件使用的注意事项⭐…

OpenAI-ChatGPT最新官方接口《从0到1生产最佳实例》全网最详细中英文实用指南和教程,助你零基础快速轻松掌握全新技术(十一)(附源码)

Production Best Practices 生产最佳实例 前言Introduction 导言Setting up your organization 设置您的组织Managing billing limits 管理计费限额API keys API密钥Staging accounts 演示账户 Building your prototype 构建您的原型Additional tips 其它技巧 Techniques for i…

C++函数重载

目录 函数重载函数重载是怎样实现的 函数重载 函数重载:是函数的一种特殊情况,C允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同,常用来处理实现功能类似数据类型不同的…

找PPT模板就上这5个网站~

分享几个可以永久免费下载PPT模板、素材的网站,上万个模板随便下载,赶紧收藏起来~ 1、菜鸟图库 https://www.sucai999.com/search/ppt/0_0_0_1.html?vNTYxMjky 网站素材非常全面,主要以设计类素材为主,办公类素材也很多&#x…

Spring MVC 接收 json 和返回 json (14)

目录 总入口 测试case 源码分析 1. 针对RequestBody的参数解析 2. 针对 ResponseBody 的返回值处理 总入口 通过上一篇Spring MVC 参数解析(13)_chen_yao_kerr的博客-CSDN博客的说明,相信大家对Sping MVC的参数解析有了一定的了解&…

8. 优先队列

8. 优先队列 普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。在某些情况下,我们可能需要找出队列中的最大值或者最小值,例如使用一个队列保存计算机的任务,一般情况下计算机的任务都是有优先级…

【有功-无功协调优化】基于改进多目标粒子群优化算法(小生境粒子群算法)的配电网有功-无功协调优化研究(Matlab代码实现)

💥 💥 💞 💞 欢迎来到本博客 ❤️ ❤️ 💥 💥 🏆 博主优势: 🌞 🌞 🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 …

中断嵌套实验

使用汇编语言,要求: 外部中断1可以嵌套外部中断0 没有中断时,8个LED发光二极管以0.1s的速度闪烁。 有外部中断0时,8个LED发光二极管以0.1s的速度流水点亮。(中断子程序0) 有外部中断1时,会打断外…

gdb调试常用指令及案例讲解

文章目录 前言一、常用指令二、案例说明1、测试源文件2、编译和调试 三、其他指令四、案例说明 前言 GDB是一个由GNU开源组织发布的、UNIX/LINUX 操作系统下的、基于命令行的、功能强大的程序调试工具。 GDB 支持断点、单步执行、打印变量、观察变量、查看寄存器、查看堆栈等调…

每天一道大厂SQL题【Day22】华泰证券真题实战(四)

每天一道大厂SQL题【Day22】华泰证券真题实战(四) 大家好,我是Maynor。相信大家和我一样,都有一个大厂梦,作为一名资深大数据选手,深知SQL重要性,接下来我准备用100天时间,基于大数据岗面试中的经典SQL题&…

2023软件测试工程师必备技能?要卷,谁还不会了......

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 软件测试岗位是怎…

day15 消息队列

目录 消息队列 消息队列的使用 发送消息 消息的接收 消息队列的控制 消息队列 概念: 消息队列是system V IPC对象的一种; 消息队列有消息队列ID来唯一标识; 消息队列就是一个消息的列表。用户可以在消息队列中添加消息、读取消息等&a…

zabbix故障排查

zabbix server服务问题可以查看server日志 tail -f /var/log/zabbix/zabbix_server.log 根据日志中的error报错提示分析原因 zabbix agent服务问题可以查看agent日志 tail -f /var/log/zabbix/zabbix_agentd.log 根据日志中的error报错提示分析原因 zabbix的nginx服务问题可…

从零开始学架构-计算高性能

一、概述 高性能是每个程序员的追求,无论做一个系统、还是写一组代码,都希望能够达到高性能的效果。而高性能又是最复杂的一环,磁盘、操作系统、CPU、内存、缓存、网络、编程语言、数据库、架构等,每个都可能影响系统的高性能&…

【FPGA实验1】FPGA点灯工程师养成记

对于FPGA几个与LED相关的实验(包括按键点灯、流水灯、呼吸灯等)的记录,方便日后查看。这世界上就又多了一个FPGA点灯工程师了😏 成为一个FPGA点灯工程师分三步: 一、按键点灯1、按键点灯程序2、硬件实现 二、流水灯1、…

智慧医院微信小程序定制开发功能有哪些

无论是哪个时代,人们对于医疗资源的需求都没有消退过,尤其是随着经济条件的提高,人们也越来越关注健康问题。无论是生病就诊还是定期体检都要用到医疗资源。但是平时到医院好像什么时候都人满为患,排很长时间的队,不仅…

ChatGPT4 的体验 一站式 AI工具箱 -—Poe(使用教程)

最近由于人工智能聊天机器人的爆火(ChatGPT),因此各种各样的AI助手流行与网络,各种各样的都有,不论是什么样的其实都是为了我们更方便的解决问题,今天介绍一款AI工具箱——Poe将多种AI集成与一个界面,大家可以一次感受…

SQL Server基础 第五章 函数的使用(日期、字符串、时间、数学、转换等函数)

前言 在SQL Server中提供了许多内置函数,SQL Server中的内置函数就相当于Java、C#等编程语言中的内置API函数。按照函数种类可以分为聚合函数、数学函数、字符串函数、日期函数和时间函数、转换函数和元数据的数6种。在本章中重点讲解比较常用的4种函数&#xff0c…