开发者实战 | 分割一切?Segment Anything 量化加速实战

news2024/11/18 7:40:47

点击蓝字

关注我们,让开发变得更有趣

作者 | 杨亦诚

排版 | 李擎

分割一切?

Segment Anything 量化加速实战

前言

“分割一切,大家一起失业!”——近期,这样一句话在社交媒体上大火!这讲的就是 Segment Anything Model(简称 “SAM” )。SAM 到底是什么?它具备哪些功能?它真的有这么强大吗?让我们一起通过本文了解详情!

SAM 是一个由 Meta AI 实验室推出的强大人工智能图像分割应用,可以自动识别哪些图像像素属于一个对象,并且对图像中各个对象进行自动风格处理,可广泛用于分析科学图像、编辑照片等。

SAM 的完整应用由一个图片编码器模型(encoder)以及掩码解码(mask decoder) + 提示编码模型(prompt encoder)构成,这两部分都可以被解析为独立的静态模型。其中大部分的算力负载和推理延时都集中在图片编码器任务,因此如果进一步提升图片编码器部分的执行效率,就成为了 SAM 应用的主要优化方向之一。

b9af64e49a87cb642cc1415037e1dd6a.png

图:SAM 模型任务pipeline

本次分享讲重点演示如何通过 OpenVINO™  的 NNCF 模型压缩工具实现对 SAM 编码器部分的量化压缩,实现在 CPU 侧的性能提升。

一、量化介绍

在正式开始实战之前,我们不得不提一下量化的概念,量化是指在不改变模型结构的情况下,将模型参数的表达区间从 FP32 映射到 INT8 或是 INT4 范围,用更小数值位宽来表示相同的信息,实现对于模型体积的压缩,降低内存消耗,同时在模型网络的执行过程中,系统会自动调用硬件平台专门针对低比特数据优化的指令集或 kernel 函数,提升性能。

de178db019a9e7a61800493925ba5447.png

图:不同精度数据的表示位宽

Intel AVX512 VNNI 扩展指令集实现了将原本需要3个时钟周期才能完成的INT8矩阵点乘与加法运算压缩到一个时钟周期,而在最新的 AMX 指令集更是将多个 VNNI 模块进行堆叠实现了单周期内成倍的性能提升。

6eb0753d420030fc0dabce12983f280e.png

图:INT8 矩阵点乘与加法运算指令集优化

二、NNCF  训练后量化模式

NNCF 工具的全称是 Neural Network Compression Framework,是 OpenVINO™ 工具链中专门用于模型压缩加速的方案实现,包含 量化,剪枝,二值化 等多种模型压缩算法,调用方式又可以分化为训练后量化 (PTQ)训练时压缩 (QAT) 两种模式,训练时压缩要需要引入原始的训练脚本和数据集,而训练后量化则可以直接针对训练生成模型文件进行压缩,无需额外的训练脚本和标注数据集参与,这也是 NNCF 在 OpenVINO™ 2023.0 正式发布的新功能特性, 而这个模式也仅仅需要以下两步便可实现:

1. 准备校验数据集

这里的校验数据仅用作量化过程中对数据表示范围与分布的计算,因此不需要额外的标签数据,例如在图像识别任务中,我们仅需要送入200-300张左右的图片文件即可。此外我们还需要定义 DataLoader 对象与 transform_fn 数据转换函数, DataLoader 用于读取校验数据集中的每一个元素,transform_fn 用于将读取的元素转化为 OpenVINO™ 模型推理的直接输入数据。

import nncf
calibration_loader = torch.utils.data.DataLoader(...)
def transform_fn(data_item):
    images, _ = data_item
    return images
calibration_dataset = nncf.Dataset(calibration_loader, transform_fn)

2. 运行模型量化

首先需要导入模型对象,然后通过 nncf.quantize() 接口,将模型对象与校验数据集绑定开启量化任务, NNCF 工具可以支持多种模型对象类型,包含openvino.runtime.Model, torch.nn.Module,  onnx.ModelProto以及 tensorflow.Module

model = ... #OpenVINO/ONNX/PyTorch/TF object
quantized_model = nncf.quantize(model, calibration_dataset)

3.(可选)准确性控制模式

如果发现 NNCF 在默认模式下的导出的模型准确性下降超过预期,我们也可以使用准确性控制模式(accuracy control)完成训练后量化,此时我们需要加入带标签的测试集数据,用来评估模型在量化过程中哪些 layer 对模型准确性损失的影响(敏感度)比较大,并作为排序依据,依次将这些 layer 回退至原始精度,直到模型符合预期准确性表现。通过这个模式,我们可以在保证模型准确性的情况下,尽可能压缩模型体积,实现性能和准确性之间的平衡。具体方法可以参考以下链接:

https://docs.openvino.ai/nightly/quantization_w_accuracy_control.html

三、 Segment Anything + NNCF实战

接下来让我们具体一步步看下如何使用 NNCF 的 PTQ 模式完成 SAM encoder 的量化。

项目地址:https://github.com/openvinotoolkit/openvino_notebooks/blob/main/notebooks/237-segment-anything/237-segment-anything.ipynb

1. 定义数据加载器

本示例使用 coco128 作为校验数据集,其中包含 128 张 .jpg 格式的图片。由于在量化 ONNX 或 IR 静态模型的情况下,数据加载器必须是一个 torch 的 DataLoader 类,因此这里我们需要继承 torch.utils.data.Dataset 并重新构建一个数据集类,其中必须包含__getitem__方法,用于遍历数据集中的每一个对象,__len__用于获取数据集的对象数量,最后再通过 torch.utils.data.DataLoader 方法生成数据加载器。

class COCOLoader(data.Dataset):
    def __init__(self, images_path):
        self.images = list(Path(images_path).iterdir())


    def __getitem__(self, index):
        image_path = self.images[index]
        image = cv2.imread(str(image_path))
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        return image
    
    def __len__(self):
        return len(self.images)
    
coco_dataset = COCOLoader(OUT_DIR / 'coco128/images/train2017')
calibration_loader = torch.utils.data.DataLoader(coco_dataset)

2. 定义数据格式转化模块

下一步是定义数据转化模块,我们可以调用之前定义 preprocess_image 函数完成数据的预处理,值得注意的是由于 calibration_loader 模块返回的单个数据对象为 torch tensor 类型  ,而 OpenVINO™ 的 Python 接口不支持该类型数据,我们需要先将其强制转化为 numpy 格式。

def transform_fn(image_data):
    image = image_data.numpy()
    processed_image = preprocess_image(np.squeeze(image))
    return processed_image


calibration_dataset = nncf.Dataset(calibration_loader, transform_fn)

3. 运行 NNCF 量化

为了确保量化后的模型准确性,这里我们使用原始的 FP32 ONNX 格式模型作为输入对象,而不是 FP16 的 IR 格式模型,然后再将该对象送入 nncf.quantize 接口执行量化,该函数接口中有几个比较重要的额外参数:

# Load FP32 ONNX model
model = core.read_model(onnx_encoder_path)
quantized_model = nncf.quantize(model,
                                calibration_dataset,
                                model_type=nncf.parameters.ModelType.TRANSFORMER,
                                preset=nncf.common.quantization.structs.QuantizationPreset.MIXED)
ov_encoder_path_int8 = "sam_image_encoder_int8.xml"
serialize(quantized_model, ov_encoder_path_int8)

· model_type:模型类别,用于开启特殊的量化策略,例如在类 Transformer 模型中,我们需要优先保证模型的准确性。

· preset:量化模式,默认为 PERFORMANCE,使用对卷积的权重和偏置均采用对称量化算法,有助于提升模型性能,此处为了提升模型准确性,我们采用 MIXED 模式,采用权重对称量化,偏置非对称量化的方法,适合模型中包含非 Relu 或者非对称的激活层。

由于 SAM encoder 模型的网络结构比较复杂,而量化过程中我们需要多次遍历模型每一个 layer 的参数,所以量化耗时相对会长一些,请大家耐心等待。这边建议使用 32G 以上内存的硬件设备,如果遇到内存不够的情况,可以通过 subset_size=100 参数,适当降低校验数据数量。

4.模型准确性比较

接下来我们比较下 INT8 和 FP16 模型的推理结果:

79c8666669688ca5451ebebd888bb883.png

b804df60f523089fee14c967e5547077.png

左右滑动查看更多

图:prompt 模式 FP16 – INT8 结果比较

1cc14e356c117423a2d77562ac0e8b4d.jpeg

255cddd58f0a85fd132082b791f19e47.jpeg

左右滑动查看更多

图:auto 模式 FP16 – INT8 结果比较

可以看到在 prompt 和 auto 模式下,INT8 模型的准确性相较 FP16 模型,几乎没有任何变化。

注:auto 模式下,mask 将使用随机生成的颜色。

5. 性能比较

最后我们通过 OpenVINO™ 自带的 benchmark_app 工具比较下性能指标:

[ INFO ] Execution Devices:['CPU']
[ INFO ] Count:            60 iterations
[ INFO ] Duration:         75716.93 ms
[ INFO ] Latency:
[ INFO ]    Median:        14832.33 ms
[ INFO ]    Average:       14780.77 ms
[ INFO ]    Min:           10398.47 ms
[ INFO ]    Max:           16725.65 ms
[ INFO ] Throughput:   0.79 FPS

Benchmark结果(FP16

[ INFO ] Execution Devices:['CPU']
[ INFO ] Count:            72 iterations
[ INFO ] Duration:         68936.14 ms
[ INFO ] Latency:
[ INFO ]    Median:        11281.87 ms
[ INFO ]    Average:       11162.87 ms
[ INFO ]    Min:           6736.09 ms
[ INFO ]    Max:           12547.48 ms
[ INFO ] Throughput:   1.04 FPS

Benchmark 结果 (INT8)

可以看到在 CPU 端,INT8 模型相较 FP16 提升了大约 30%, 体积从原本的 350MB 压缩到了 100MB 不到。

四、总结

鉴于 SAM 出色的自动化分割能力,相信未来会有越来越多应用场景会部署这项技术,而在产业化落地的过程中,开发者往往最关注的就是性能和准确性之间的平衡,以此获取成本更优的方案。OpenVINO™ NNCF 工具通过对 Segment Anything encoder 部分的量化压缩,在几乎没有影响模型准确性的情况下,显著提升模型的运行效率,降低模型占用空间。

--END--

你也许想了解(点击蓝字查看)⬇️➡️ 以AI作画,祝她节日快乐;简单三步,OpenVINO™ 助你轻松体验AIGC

➡️ 还不知道如何用OpenVINO™作画?点击了解教程。➡️ 如何给开源项目做贡献? | 开发者节日福利➡️ 几行代码轻松实现对于PaddleOCR的实时推理,快来get!➡️ 使用OpenVINO 在“端—边—云”快速实现高性能人工智能推理➡️ 图片提取文字很神奇?试试三步实现OCR!➡️【Notebook系列第六期】基于Pytorch预训练模型,实现语义分割任务➡️使用OpenVINO™ 预处理API进一步提升YOLOv5推理性能
扫描下方二维码立即体验 
OpenVINO™ 工具套件 2022.3

点击 阅读原文 立即体验OpenVINO 2022.3

a67efe5af2422154ca9882b621c4af0a.png

文章这么精彩,你有没有“在看”?

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

chatgpt赋能python:Python创建一个Person类

Python 创建一个 Person 类 Python 是一种高级编程语言,因为它易于学习和使用,并且可以用于多种用途。使用 Python,您可以轻松创建各种程序,从简单的脚本到完整的应用程序。Python 的一个重要特点是它的面向对象编程能力&#xf…

「VS」Visual Studio 字符集

✨博客主页:何曾参静谧的博客 📌文章专栏:「VS」Visual Studio 当我们在使用 Visual Studio 编写程序时,经常会遇到字符集的问题。在 Visual Studio 中,字符集选项有两个选项:Unicode 字符集和多字节字符集…

期刊和会议如何查询、期刊级别分类和顶会概念一文精析

期刊和会议查询、期刊级别分类和顶会概念分析 一、如何查询期刊和会议1.中文期刊-用知网出版物检索2.外文期刊-一般用letpub3.会议查询 二、国内期刊的正刊三、国内核心期刊四、国际核心期刊五、ESCI、SCI和SCIE的区别六、国际会议核心七、普刊八、顶刊九、水刊十、预警期刊 了…

一起看 I/O | Android 性能相关最新动态

作者 / Ben Weiss 过去几年来,我们一直致力于让性能提升工作变得更易上手、回报更高。我们将在本文中分享这一领域的最新发展动态。为您介绍基准配置文件、Android Studio 中的工具改进、库,以及我们如何让这项技术更好地在后台为您服务。此外&#xff0…

IPA50R190CE-ASEMI代理英飞凌MOS管IPA50R190CE

编辑:ll IPA50R190CE-ASEMI代理英飞凌MOS管IPA50R190CE 型号:IPA50R190CE 品牌:Infineon(英飞凌) 封装:TO-220F 最大漏源电流:24.8A 漏源击穿电压:500V RDS(ON)Max&#xff1…

某oa 11.10 未授权任意文件上传

漏洞简介 之前也对通达 oa 做过比较具体的分析和漏洞挖掘,前几天看到通达 oa 11.10 存在未授权任意文件上传漏洞,于是也打算对此进行复现和分析。 环境搭建 https://www.tongda2000.com/download/p2019.php 下载地址 :https://cdndown.tongda…

java-Lambde和方法引用

java-Lambde和方法引用 一、Lambda表达式 1.1 Lambda标准格式 格式: ​ (形参) -> {代码块} 形参:如果有多个参数,参数之间用逗号隔开;如果没有参数,留空即可 ->:由英文中画线和大于符号组成&#…

企业虚拟机服务器中了lockbit3.0勒索病毒怎么办,lockbit勒索病毒解密

虚拟机服务器在现代企业中扮演着至关重要的角色,它是一个重要的基础设施,用于支持大量的业务应用和数据存储。然而,随着网络攻击技术的不断发展,企业虚拟机服务器也面临着来自黑客的威胁。其中一种最具破坏性的攻击是勒索病毒&…

单例模式8种写法

0. 为什么需要单例模式? 节省内存和计算保证结果正确方便管理 使用场景: 1. 饿汉式(静态常量)—推荐指数:★★☆☆☆ 优点:不会有线程安全问题。 缺点:在类加载的时候就创建对象,…

VMware SD-WAN 5.2 发布 - 软件定义的 WAN

VMware SD-WAN 5.2 发布 - 软件定义的 WAN SD-WAN 解决方案的领导者 请访问原文链接:https://sysin.org/blog/vmware-sd-wan-5/,查看最新版。原创作品,转载请保留出处。 作者主页:sysin.org 产品概述 软件定义的 WAN (SD-WAN)…

chatgpt赋能python:Python列表横向合并

Python列表横向合并 Python是一种功能强大的编程语言,被越来越多的开发者所青睐。列表是Python中最常用的数据结构之一,它是一种有序的集合,可以存储任意类型的数据。在编写Python程序时,很常见的需求是将两个或多个列表横向合并…

(超详细)关于Nacos的共享配置( shared-configs)和拓展配置(extension-config)

前言 用SpringBoot的铁子们,相信大多数人都使用过Nacos作为注册中心和配置文件管理中心,确实很方便。但是很多铁子们依葫芦画瓢,都知道怎么用,但是对于其中的细节可能没有系统地整理过。今天就讲讲关于Nacos的共享配置和扩展配置…

【C++11】C++11新增语法 Lambda表达式/Lambda的底层原理

Lambda表达式 1 Lambda使用的一个例子2 Lambda 表达式的语法3 初次体验Lambda表达式4 Lambda函数底层实现原理 1 Lambda使用的一个例子 在C98中&#xff0c;如果我们想要对一个自定义类型进行排序&#xff0c;就需要用户自定义去书写比较的规则。 #include <iostream> …

排序算法——直接插入排序

直接插入排序 基本思想 直接插入排序是一种简单明了的插入排序法&#xff0c;其基本思想是&#xff1a;把待排序的数据按其关键码值的大小逐个插入到一个已经排好序的有序序列中&#xff0c;直到所有数据插入完为止。 在现实生活中&#xff0c;我们玩扑克对牌进行排序就运用了…

开源、易扩展、方便集成的Web绘图工具(流程图、架构图、组态、SCADA、大屏)

乐吾乐2D可视化Meta2d.js是一个基于typescript canvas 实现的开源在线绘图软件。采用引擎 图形库中间件的思路能够方便、快速的扩展、集成到前端项目。 集实时数据展示、动态交互、数据管理等一体的全功能可视化平台。帮助物联网、工业互联网、电力能源、水利工程、智慧农业…

【unity之c#】所以迭代器的原理知识你还清楚吗?

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;uni…

day46-动态规划8-单词拆分问题

139.单词拆分-完全背包问题区分求组合数和排列数 本题可以使用回溯算法进行暴力搜索&#xff0c;但是如何使用动态规划的思路进行求解呢。将字符串可以理解成一个容器&#xff0c;将单词可以当成物品&#xff0c;那么此时问题转化成利用物品能否装满容器的问题。这个时候由于返…

chatgpt赋能python:Python列表框-理解列表框的功能和用途

Python列表框 -理解列表框的功能和用途 列表框可以说是Python编程中最常用的控件之一。列表框用于在桌面应用程序中显示和管理数据。与其他编程语言一样&#xff0c;Python编程语言提供了许多列表框控件&#xff0c;可以使用它们来管理和显示各种数据。 列表框是一种视觉化的…

软件工程导论(5)软件编码测试与维护

一、软件编程 2.1良好的编程习惯 变量命名有意义并且使用统一的命名规则 编写自文档代码&#xff08;序言性注释 or 行内注释&#xff09; 提前进行可维护性考量&#xff08;可以用常量的方式存在的数值最好以变量的方式存在&#xff09; 良好的视觉安排可以提高代码的可读性(…

【服务器】零基础搭建私有云盘并内网穿透远程访问

文章目录 摘要视频教程1. 环境搭建2. 测试局域网访问3. 内网穿透3.1 ubuntu本地安装cpolar3.2 创建隧道3.3 测试公网访问 4 配置固定http公网地址4.1 保留一个二级子域名4.1 配置固定二级子域名4.3 测试访问公网固定二级子域名 转载自cpolar极点云的文章&#xff1a;使用Nextcl…