PPQ库中KLD算法实现代码解析

news2024/9/20 22:37:45

PPQ量化工具库KLD算法解析

  • 前言
  • PPQ算法实现
    • NVIDIA的PPT中KLD算法流程
    • KLD算法PPQ实现版本
    • PPQ与NVIDIA的区别:

前言

这是对PPQ库中KLD算法实现代码解析,关于PPQ库安装与使用详情见专栏上一篇博客。

PPQ算法实现

nvidia发布的PPT:8-bit Inference with TensorRT,百度可下载。下两图是KLD算法的实现伪代码:
在这里插入图片描述
在这里插入图片描述
下图是PPQ算法的实现过程:见https://github.com/openppl-public/ppq/blob/master/ppq/quantization/observer/range.py

def hist_to_scale_offset(
        self, histogram: torch.Tensor, hist_bins: int, hist_scale: float,
        config: TensorQuantizationConfig, computing_device: str = OBSERVER_KL_COMPUTING_DEVICE,
        scale_threshold: float=OBSERVER_MIN_SCALE
    ) -> Tuple[float, int]:
        """
        PPQ core quant parameter computing method - Histogram to scale & offset
        With a pre-defined histogram,
        this function will automatically search best clip value
        to minimize KL divergence between quantized result and fp32 input.
        only work for per-tensor symmetrical quantization policy for now.
        see also https://on-demand.gputechconf.com/gtc/2017/presentation/s7310-8-bit-inference-with-tensorrt.pdf
        Args:
            histogram (torch.Tensor): histogram records activation's statistics.
            hist_bins (int): how many bins are included in histogram(also known as histogram length)
            hist_scale (float): histogram step size. it can be solved by histogram.max_val / histogram.bins
            config (TensorQuantizationConfig): quantization config.
            computing_device (str, optional): computing device. Defaults to 'cpu'.
        Raises:
            ValueError: given quantization config is invalid.
        Returns:
            Tuple[float, int]: scale(fp32) and offset(int).
        """
        if config.policy.has_property(QuantizationProperty.ASYMMETRICAL):
            raise PermissionError('KL observer is not designed for ASYMMETRICAL quantization')
        
        if OBSERVER_MIN_SCALE_MANUL_OVERRIDE in config.detail:
            scale_threshold = config.detail[OBSERVER_MIN_SCALE_MANUL_OVERRIDE]

        # move histogram to cpu, speedup computation.
        histogram = histogram.to(computing_device).float()

        # compute symmtrical kl-divergence.
        # Here is a simple example: reference distribution P consisting of 8 bins, we want to quantize into 2 bins:
        # P = [ 1, 0, 2, 3, 5, 3, 1, 7]
        # we merge into 2 bins (8 / 2 = 4 consecutive bins are merged into one bin)
        # [1 + 0 + 2 + 3 , 5 + 3 + 1 + 7] = [6, 16]
        # then proportionally expand back to 8 bins, we preserve empty bins from the original distribution P:
        # Q = [ 6/3, 0, 6/3, 6/3, 16/4, 16/4, 16/4, 16/4] = [ 2, 0, 2, 2, 4, 4, 4, 4]
        # now we should normalize both distributions, after that we can compute KL_divergence
        # P /= sum(P) Q /= sum(Q)
        # result = KL_divergence(P, Q)
        # see also
        # https://github.com/NVIDIA/TensorRT/blob/3835424af081db4dc8cfa3ff3c9f4a8b89844421/tools/pytorch-quantization/pytorch_quantization/calib/histogram.py#L147

        losses, quant_bins = [], 2 ** (config.num_of_bits - 1)

        # following code is curcial, do not move
        histogram[: int(hist_bins * .002)] = 0
        histogram[int(hist_bins * .002)] = 1

        hist_sum = torch.sum(histogram)
        for bin_range in range(quant_bins, hist_bins + quant_bins - 1, quant_bins):
            p_hist = torch.zeros(size=(bin_range, ), dtype=torch.float, device=computing_device)
            p_hist[: bin_range].copy_(histogram[: bin_range])
            p_hist[bin_range - 1] += torch.sum(histogram[bin_range: ])
            p_hist = p_hist / hist_sum

            expand_ratio = int(bin_range / quant_bins)
            q_hist = histogram[: bin_range].clone()
            q_hist = q_hist.reshape((quant_bins, expand_ratio))
            positive_map = q_hist > 0
            positive_cnt = positive_map.sum(axis=1, keepdim=True)
            positive_cnt[positive_cnt == 0] = 1
            q_hist = torch.div(q_hist.sum(axis=1, keepdim=True), positive_cnt)
            q_hist = q_hist.repeat([1, expand_ratio])
            q_hist = q_hist * positive_map
            q_hist = q_hist / torch.sum(q_hist)
            q_hist = q_hist.flatten()

            losses.append({
                'kl': torch_KL_divergence(p_hist, q_hist),
                'bin_range': bin_range
            })

        best_bin_range = sorted(losses, key=lambda x: x['kl'])[0]['bin_range']
        scale, offset = (best_bin_range / self._hist_bins) * hist_scale * (self._hist_bins / quant_bins), 0
        
        if scale < scale_threshold and OBSERVER_WARNING: 
            ppq_warning('Numeric instability detected: '
                        'ppq find there is a scale value < 1e-7, '
                        'which probably cause numeric underflow in further computation.')
        scale = max(scale, scale_threshold)

        if config.policy.has_property(QuantizationProperty.POWER_OF_2):
            scale = ppq_round_to_power_of_2(scale, policy=RoundingPolicy.ROUND_HALF_UP)
        return scale, offset

NVIDIA的PPT中KLD算法流程

整个过程:从128循环到2048,i为截断阈值将bin截断(第i个条形图也会被舍弃),生成P和Q,计算每组P和Q的KL散度,最小散度对应阈值即为所求
输入Input:一个有2048个统计条条形图bin
输出:截断阈值threshhold,浮点数
在这里插入图片描述
在这里插入图片描述

KLD算法PPQ实现版本

算法流程:
在这里插入图片描述
具体代码分析:
在这里插入图片描述

PPQ与NVIDIA的区别:

1.原始histogram条形图舍弃
NVIDIA是:不进行预处理
PPQ:前其千分之二置为零,第千分之二个条形置为1
2.for循环找截断阈值
NVIDIA是:for i in range(102,2048)
PPQ库是:for bin_range in range(quant_bins, hist_bins + quant_bins - 1, quant_bins):
3.阈值m转为实际浮点数
NVIDIA是:threshold = ( m + 0.5 ) * ( width of a bin )
PPQ库是:
在这里插入图片描述

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

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

相关文章

使用vue-element-admin进行二次开发

vue-element-admin 介绍 基于 vue 和 element-ui实现 的后台前端解决方案 集成方案: vue-element-admin基础模板: vue-admin-template桌面终端: electron-vue-adminTypescript 版: vue-typescript-admin-template Others: awesome-project 亮点 i18 国际化解决方案 动态路由…

射频功率放大器在辉光放电特征及风速测量原理中的应用

实验名称&#xff1a;辉光放电特征及风速测量原理研究方向&#xff1a;辉光放电测试设备&#xff1a;信号发生器、ATA-8202射频功率放大器&#xff0c;热成像仪、万用表、等离子体传感器实验过程&#xff1a;在等离子体形成条件和流场响应机制的基础上&#xff0c;可以明确影响…

node使用支付宝沙箱模拟支付-好文

首页打开支付宝官方进行登录&#xff1a;支付宝开放平台 (alipay.com)下载支付宝提供的秘钥转化工具&#xff1a;密钥工具下载 - 支付宝文档中心 (alipay.com)打开工具生成密码&#xff1a;然后在支付宝页面配置秘钥开始配置nodenpm init -y初始化&#xff0c;再npm i express跟…

<Linux>进程间通信--管道

前言&#x1f603;&#x1f603;&#x1f603;进程间通信的方式管道 - Linux原生提供2SystemV - 多线程单机通信posix - 多线程网络通信这里我们主要是介绍一下管道一、生活和计算机中的管道&#x1f61c;生活中的管道特点都是有出口和入口的都是单向传输内容的(例如&#xff1…

雨水情测报设施包含哪些设备?

通常雨水情测报及大坝安全监测设施&#xff0c;主要包括&#xff1a;大坝安全监测终端、雨水情监测终端、GNSS监测站、雷达水位计、大坝安全监测平台、雨水情测报系统平台等产品。雨水情测报及大坝安全监测系统方案解决方案雨水情测报及大坝安全监测系统解决方案&#xff0c;主…

华为OD机试题,用 Java 解【字符串加密】问题

华为Od必看系列 华为OD机试 全流程解析+经验分享,题型分享,防作弊指南)华为od机试,独家整理 已参加机试人员的实战技巧华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典使用说明 参加华为od机试,一定要注意不…

Raft图文详解

Raft图文详解 refer to: Raft lecture (Raft user study) - YouTube Raft PDF Raft算法详解 - 知乎 (zhihu.com) 今天来详细介绍一下Raft协议 Raft是来解决公式问题的协议&#xff0c;那么什么是共识呢&#xff1f; 在分布式系统里面&#xff0c;consensus指的是多个节点对…

UEFI移植LVGL

自己组装过游戏主机的应该都有看到过&#xff0c;进入BIOS设置&#xff0c;酷炫的界面便呈现在眼前&#xff0c;而很多BIOS&#xff0c;使用的还是标准的界面。现在有个趋势&#xff0c;phoenix和insyde也在慢慢朝这种GUI界面发展&#xff0c;而AMI的使用C编写的界面已经非常完…

spring学习3.5

Bean是什么 Spring里面的Bean就类似是定义的一个组件&#xff0c;而这个组件的作用就是实现某个功能的&#xff0c;这里所定义的Bean就相当于给了你一个更为简便的方法来调用这个组件去实现你要完成的功能。 IoC是什么 谁控制谁&#xff0c;控制什么&#xff1f; 传统Java SE程…

11.SpringSecurity基于JWT实现Token的处理

SpringSecurity基于JWT实现Token的处理 前面介绍了手写单点登录和JWT的应用&#xff0c;本文结合SpringSecurity来介绍下在SpringBoot项目中基于SpringSecurity作为认证授权框架的情况下如何整合JWT来实现Token的处理。 一、认证思路分析 SpringSecurity主要是通过过滤器来实现…

【JavaWeb】从输入URL到展示出页面的过程

目录 DNS域名解析 检查hosts文件 查询缓存 查询本地DNS服务器 ​编辑查询根域名服务器等 三次握手建立连接 发送请求 响应请求 页面渲染 断开连接 这些过程简单的理解为先找到某人地址&#xff0c;给他发送消息可以去他家拿东西吗&#xff1f;他同意后拿到他的东西在…

33- PyTorch实现分类和线性回归 (PyTorch系列) (深度学习)

知识要点 pytorch最常见的创建模型的方式, 子类 读取数据: data pd.read_csv(./dataset/credit-a.csv, headerNone) 数据转换为tensor: X torch.from_numpy(X.values).type(torch.FloatTensor) 创建简单模型: from torch import nn model nn.Sequential(nn.Linear(15, 1…

Dockerfile简单使用入门

什么是 Dockerfile&#xff1f; Dockerfile 是一个用来构建镜像的文本文件&#xff0c;文本内容包含了一条条构建镜像所需的指令和说明。 docker build命令用于从Dockerfile构建映像。可以在docker build命令中使用-f标志指向文件系统中任何位置的Dockerfile。 例如&#xff1…

亚马逊电动水泵UL778测试报告

电动水泵UL778如何办理&#xff1f; 近期亚马逊在3C品类吹的风可够大的&#xff0c;严查起UL测试报告了。许多卖家反映收到相关邮件通知&#xff0c;产品也由于在规定时间内无法提供UL测试报告&#xff0c;出现被暂停销售、listing被下架等问题。 从亚马逊此次的动作来看&…

深度学习卷积神经网络CNN之 VGGNet模型主vgg16和vgg19网络模型详解说明(理论篇)

1.VGG背景 2. VGGNet模型结构 3. 特点&#xff08;创新、优缺点及新知识点&#xff09; 一、VGG背景 VGGNet是2014年ILSVRC&#xff08;ImageNet Large Scale Visual Recognition Challenge大规模视觉识别挑战赛&#xff09;竞赛的第二名&#xff0c;解决ImageNet中的1000类图…

Padloc:一个直观的开源密码管理器

让我们了解一下这个具有令人愉悦的用户界面、跨平台可用的开源密码管理器。有大量适用于个人和团队的免费的和收费的密码管理器。然而&#xff0c;当谈到开源方案时&#xff0c;它通常仅限于几个好的方案&#xff0c;如 Seahorse、KeePassXC 和 Bitwarden。如果你已阅读过我们的…

【浅学Java】InnoDB存储引擎下MVCC(多版本并发控制 )

TOC 1. MVCC是什么 MVCC是面试中比较常见的一个问题&#xff0c;那么什么是MVCC机制&#xff0c;它的作用是什么&#xff1f; 它的英文全称是 Multi-Version Concurrency Control &#xff0c;也就是“多版本并发控制”的意思。在MySQL InnoDB存储引擎下&#xff0c;RC、RR就…

DBeaver 超级详细的安装与使用

一、下载DBeaver DBeaver是一种通用数据库管理工具&#xff0c;适用于需要以专业方式使用数据的每个人&#xff1b;适用于开发人员&#xff0c;数据库管理员&#xff0c;分析师和所有需要使用数据库的人员的免费(DBeaver Community) 的多平台数据库工具。 DBeaver支持80多个数据…

Redis学习(四):三种特殊类型及常用操作

geospatial &#xff08;地理位置&#xff09; 查询经纬度网站 添加位置GEOADD 两极无法直接添加&#xff0c;我们一般会下载城市数据&#xff0c;通过java程序导入 可以看到这个命令也支持一次性添加多个。 获取位置GEOPOS 获取两点之间距离 GEODIST 默认单位是m&#xff0c…

MySQL面试题-锁相关

目录 1.MySQL 锁的类型有哪些呢&#xff1f; 2.如何使用全局锁 3.如果要全库只读&#xff0c;为什么不使用set global readonlytrue的方式&#xff1f; 4.表级锁和行级锁有什么区别&#xff1f; 5.行级锁的使用有什么注意事项&#xff1f; 6.InnoDB 有哪几类行锁&#xff…