Distiller:量化算法

Quantization Algorithms

量化算法

注意:
对于任何需要量化感知训练的以下方法,请参阅这里,了解如何使用Distiller的机制调用它。

基于范围的线性量化(Range-Based Linear Quantization)

让我们在此分解使用的术语:

  • 线性(Linear): 表示通过乘以数字常数(比例因子)来量化浮点值。
  • 基于范围(Range-Based): 意味着为了计算比例因子,我们查看张量值的实际范围。 在最原始的实现中,我们使用张量的实际最小/最大值。或者,我们使用一些基于张量范围/分布的推导来得出更窄的最小/最大范围,以便去除可能的异常值。这与此处描述的其他方法形成对比,我们可以将其称为基于截断的(clipping-based),因为它们在张量采用截断函数。

非对称(Asymmetric)与对称(Symmetric)

在这种方法中,我们可以使用两种模式 - 非对称对称

非对称模式

Asymmetric Mode

非对称模式下,我们将浮点范围中的最小值/最大值映射到整数范围的最小值/最大值。除了比例因子之外,这通过使用零点(也称为量化偏差,或偏移)来完成。

让我们用 x f x_f xf表示原始浮点张量,用 x q x_q xq表示量化张量,用 q x q_x qx表示比例因子,用 z p x zp_x zpx表示零点,以及用 n n n表示量化的比特。然后,我们得到:

x q = r o u n d ( ( x f − m i n x f ) 2 n − 1 m a x x f − m i n x f ⎵ q x ) = r o u n d ( q x x f − m i n x f q x ) ⎵ z p x = r o u n d ( q x x f − z p x ) x_q = round\left ((x_f - min_{x_f})\underbrace{\frac{2^n - 1}{max_{x_f} - min_{x_f}}}_{q_x} \right) = round(q_x x_f - \underbrace{min_{x_f}q_x)}_{zp_x} = round(q_x x_f - zp_x)\ xq=round(xfminxf)qx maxxfminxf2n1=round(qxxfzpx minxfqx)=round(qxxfzpx) 

我们实际上使用 z p x = r o u n d ( m i n x f q x ) zp_x = round(min_{x_f}q_x) zpx=round(minxfqx)。这意味着零可以通过量化范围中的整数精确表示。例如,对于具有零填充的层(zero-padding),这很重要。通过四舍五入零点,我们有效地“微调”浮动范围中的最小值/最大值,以获得零的精确量化。

请注意,在上面的推导中,我们使用无符号整数来表示量化范围。也就是说, x q ∈ [ 0 , 2 n − 1 ] x_q \in [0,2 ^ n-1] xq[0,2n1]。如果需要,可以使用有符号整数(可能由于硬件考虑因素。这可以通过减去 2 n − 1 2 ^ {n-1} 2n1来实现。

让我们看看卷积全连接层如何在非对称模式下量化(我们分别用 x , y , w x,y,w x,y,w b b b表示输入,输出,权重和偏置):

y f = ∑ x f w f + b f = ∑ x q + z p x q x w q + z p w q w + b q + z p b q b = y_f = \sum{x_f w_f} + b_f = \sum{\frac{x_q + zp_x}{q_x} \frac{w_q + zp_w}{q_w}} + \frac{b_q + zp_b}{q_b} = yf=xfwf+bf=qxxq+zpxqwwq+zpw+qbbq+zpb=
= 1 q x q w ( ∑ ( x q + z p x ) ( w q + z p w ) + q x q w q b ( b q + z p b ) ) = \frac{1}{q_x q_w} \left( \sum { (x_q + zp_x) (w_q + zp_w) + \frac{q_x q_w}{q_b}(b_q + zp_b) } \right) =qxqw1((xq+zpx)(wq+zpw)+qbqxqw(bq+zpb))

因此有:

y q = r o u n d ( q y y f ) = r o u n d ( q y q x q w ( ∑ ( x q + z p x ) ( w q + z p w ) + q x q w q b ( b q + z p b ) ) ) y_q = round(q_y y_f) = round\left(\frac{q_y}{q_x q_w} \left( \sum { (x_q+zp_x) (w_q+zp_w) + \frac{q_x q_w}{q_b}(b_q+zp_b) } \right) \right) yq=round(qyyf)=round(qxqwqy((xq+zpx)(wq+zpw)+qbqxqw(bq+zpb)))

注意:

  • 可以看到,必须重新调整偏置以匹配求和的比例。
  • 在适当的全整数HW(宽高)通道中,我们希望我们的主要累积项简单地表示为 ∑ x q w q \sum {x_q w_q} xqwq。为了实现这一点,我们需要进一步发展上面得出的表达式。有关详细信息,请参阅gemmlowp。

对称模式

对称模式

对称模式中,我们选择最小/最大值之间的最大绝对值,而不是将浮点范围的精确最小值/最大值映射到量化范围。另外,我们不使用零点。因此,我们有效量化的浮点范围相对于零是对称的,量化范围也是如此。

用同样的符号,我们得到:

x q = r o u n d ( x f 2 n − 1 − 1 max ⁡ ∣ x f ∣ ⎵ q x ) = r o u n d ( q x x f ) x_q = round\left (x_f \underbrace{\frac{2^{n-1} - 1}{\max|x_f|}}_{q_x} \right) = round(q_x x_f) xq=roundxfqx maxxf2n11=round(qxxf)

卷积全连接层如何在对称模式下量化:

y f = ∑ x f w f + b f = ∑ x q q x w q q w + b q q b = 1 q x q w ( ∑ x q w q + q x q w q b b q ) y_f = \sum{x_f w_f} + b_f = \sum{\frac{x_q}{q_x} \frac{w_q}{q_w}} + \frac{b_q}{q_b} = \frac{1}{q_x q_w} \left( \sum { x_q w_q + \frac{q_x q_w}{q_b}b_q } \right) yf=xfwf+bf=qxxqqwwq+qbbq=qxqw1(xqwq+qbqxqwbq)

因此:

y q = r o u n d ( q y y f ) = r o u n d ( q y q x q w ( ∑ x q w q + q x q w q b b q ) ) y_q = round(q_y y_f) = round\left(\frac{q_y}{q_x q_w} \left( \sum { x_q w_q + \frac{q_x q_w}{q_b}b_q } \right) \right) yq=round(qyyf)=round(qxqwqy(xqwq+qbqxqwbq))

模式对比

这两种模式之间的主要权衡是简单性量化范围的利用

  • 当使用非对称量化时,充分利用量化范围。这是因为我们精确地将浮点范围中的最小值/最大值映射到量化范围的最小值/最大值。使用对称模式,如果浮动范围偏向一侧,则可能导致量化范围,其中显着的动态范围专用于我们将永远看不到的值。最极端的例子是在ReLU之后,整个张量是正的。在对称模式下量化它意味着我们实际上失去了1位。
  • 另一方面,如果我们查看上面的卷积/全连接层的偏差,我们可以看到对称模式的实际实现要简单得多。在非对称模式下,零点需要宽高中的附加逻辑。在延迟和/或功率方面,这种额外逻辑的成本当然取决于具体的实现。

其他特点

  • 删除异常值: 如这里所讨论的,在某些情况下,激活的浮动范围包含异常值。在这些异常值上花费动态范围会损害我们准确表达我们实际关注的值的能力。
    outliers-removal
    目前,Distiller支持在训练后量化期间通过平均来截断激活。即对于每批数据(batch),而不是计算全局最小/最大值,而是批次中每个样品的最小/最大值的平均值。
  • 比例因子范围: 对于权重张量,Distiller支持每通道量化(每个输出通道)。

在Distiller中的实现

训练后

对于训练后量化,目前使用此方法支持卷积全连接

  • 它们是通过利用量化和去量化操作包装现有PyTorch层来实现的。也就是说,计算是在浮点张量上完成的,但值本身仅限于整数值。在RangeLinearQuantParamLayerWrapper类中实现。
  • 所有其他层不受影响,并使用其原始FP32实现执行。
  • 要使用此方法将现有模型自动转换为量化模型,请使用PostTrainLinearQuantizer类。 有关如何执行此操作的示例,请参阅compress_classifier.py。此示例提供命令行参数以调用训练后量化。详阅这里。
  • 对于权重和偏置,在量化设置(“离线”)处确定一次比例因子和零点,并且对于激活,在运行时(“在线”)动态地确定比例因子和零点。计算出的量化参数作为缓冲区存储在模块中,因此在保存模型检查点时会自动序列化。
  • 由于这是训练后量化,因此使用位数<8的情况可能会导致精确度降低。

Quantization-Aware训练

要在训练中应用基于范围的线性量化,请使用QuantAwareTrainRangeLinearQuantizer类。它将权重量化应用于卷积和全连接模块。 对于激活量化,它将在ReLU之后插入实例FakeLinearQuantization模块。 该模块遵循Benoit et al., 2018中描述的方法,并使用指数移动平均值来跟踪激活范围。

与post-training类似,计算出的量化参数(比例因子,零点,跟踪激活范围)作为缓冲区存储在各自的模块中,因此在创建检查点时会保存它们。

注意,尚不支持从量化感知训练模型到训练后量化模型的转换。这种转换将使用在训练期间跟踪的激活范围,因此将不需要额外的离线或在线计算量化参数。

DoReFa

(方法提出在 DoReFa-Net: Training Low Bitwidth Convolutional Neural Networks with Low Bitwidth Gradients)

在这个方法中,我们首先定义量化函数 q u a n t i z e k quantize_k quantizek,输入实数值 a f ∈ [ 0 , 1 ] a_f \in [0, 1] af[0,1]并且输出离散值 a q ∈ { 0 2 k − 1 , 1 2 k − 1 , . . . , 2 k − 1 2 k − 1 } a_q \in \left\{ \frac{0}{2^k-1}, \frac{1}{2^k-1}, ... , \frac{2^k-1}{2^k-1} \right\} aq{2k10,2k11,...,2k12k1},其中 k k k 是量化比特数。

a q = q u a n t i z e k ( a f ) = 1 2 k − 1 r o u n d ( ( 2 k − 1 ) a f ) a_q = quantize_k(a_f) = \frac{1}{2^k-1} round \left( \left(2^k - 1 \right) a_f \right) aq=quantizek(af)=2k11round((2k1)af)

激活值被截断为 [ 0 , 1 ] [0, 1] [0,1]的范围并遵循下式量化:

x q = q u a n t i z e k ( x f ) x_q = quantize_k(x_f) xq=quantizek(xf)

对于权重,我们定义以下函数 f f f,它接受无界实值输入并在 [ 0 , 1 ] [0,1] [0,1]中输出实数值:

f ( w ) = t a n h ( w ) 2 m a x ( ∣ t a n h ( w ) ∣ ) + 1 2 f(w) = \frac{tanh(w)}{2 max(|tanh(w)|)} + \frac{1}{2} f(w)=2max(tanh(w))tanh(w)+21

现在我们可以使用 q u a n t i z e k quantize_k quantizek来获得量化的权重值,如下所示:

w q = 2 q u a n t i z e k ( f ( w f ) ) − 1 w_q = 2 quantize_k \left( f(w_f) \right) - 1 wq=2quantizek(f(wf))1

该方法需要用量化感知训练训练模型,如这里所讨论的。 使用DorefaQuantizer类将现有模型转换为使用DoReFa进行量化训练的模型。

注意:

  • 本文提出的梯度量化尚不支持。
  • 本文定义了二进制权重的特殊处理,但Distiller尚不支持。

PACT

(方法提出在 PACT: Parameterized Clipping Activation for Quantized Neural Networks)

此方法类似于DoReFa,但激活函数的截断上界 α \alpha α是学习的参数而不是直接设置为1。请注意,根据论文的建议, α \alpha α是每层共享的。

该方法需要用量化感知训练训练模型,如这里所讨论的。 使用PACTQuantizer类将现有模型转换为使用PACT进行量化训练的模型。

WRPN

(方法提出在 WRPN: Wide Reduced-Precision Networks)

在这种方法中,激活被剪切为 [ 0 , 1 ] [0,1] [0,1]并按照如下方式量化( k k k是用于量化的比特数):

x q = 1 2 k − 1 r o u n d ( ( 2 k − 1 ) x f ) x_q = \frac{1}{2^k-1} round \left( \left(2^k - 1 \right) x_f \right) xq=2k11round((2k1)xf)

权重被剪切为 [ − 1 , 1 ] [ -1,1] [1,1]并量化如下:

w q = 1 2 k − 1 − 1 r o u n d ( ( 2 k − 1 − 1 ) w f ) w_q = \frac{1}{2^{k-1}-1} round \left( \left(2^{k-1} - 1 \right)w_f \right) wq=2k111round((2k11)wf)

注意, k − 1 k-1 k1位用于量化权重,留下一位用于符号。

该方法需要用量化感知训练训练模型,如这里所讨论的。 使用WRPNQuantizer类将现有模型转换为使用WRPN进行量化训练的模型。

注意:

  • 该论文提出扩大层作为降低精度损失的手段。 目前,这不是作为WRPNQuantizer的一部分实现的。 要试验这一点,请修改模型实现以获得更宽的层。
  • 本文定义了二进制权重的特殊处理,但Distiller尚不支持。

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

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

相关文章

模型压缩工具Distiller-剪枝

1.distiller剪枝模块的使用 &#xff08;1&#xff09;distiller自带剪枝实例测试 distiller自带一些测试实例如ResNet56cifar-10&#xff0c;下面是对ResNet56cifar-10的测试&#xff1a; 测试前准备 yaml文件(注意&#xff1a;这里的yaml文件是coder配置好的&#xff0c;具体…

模型压缩工具Distiller-INT8量化

1.distiller工具介绍 Distiller是一个开源的Python软件包&#xff0c;用于神经网络压缩研究。网络压缩可以减少神经网络的内存占用&#xff0c;提高推理速度并节省能源。Distiller提供了一个PyTorch环境&#xff0c;用于对压缩算法进行原型设计和分析。 主要功能&#xff1a; …

Z3约束器详细学习(0)—Z3安装|语句详解

推荐肉丝r0ysue课程&#xff08;包含安卓逆向与js逆向&#xff09;&#xff1a; 参考资料&#xff1a; Z3 API IN PYTHON 中文文档 1. Z3安装 linux安装Z3 git clone https://github.com/angr/angr-z3.git cd angr-z3 python scripts/mk_make.py cd build make sudo make …

z3求解器(SMT)解各类方程各种逻辑题非常简单直观

各位小伙伴大家好&#xff0c;今天我将给大家演示一个非常高级的工具&#xff0c;SMT求解器。应用领域非常广&#xff0c;解各类方程&#xff0c;解各类编程问题&#xff08;例如解数独&#xff09;&#xff0c;解逻辑题等都不在话下。 今天小小明就将带大家看看这其中的精彩&…

z3学习笔记(有空继续整理)

一、基本语法 Declare-const: 声明给定类型&#xff08;type/ sort&#xff09;的常量 declare-fun&#xff1a;声明一个函数 (declare-fun f (Int Bool) Int)&#xff1a;声明一个接收整型和布尔型两个参数的函数&#xff0c;返回int (define-fun a () Int [val])&#xf…

生成带参数的二维码

获取带参数的二维码的过程包括两步,首先创建二维码ticket,然后凭借ticket到指定URL换取二维码。 首先,创建二维码ticket 参考一下参数 临时二维码请求说明 http请求方式: POST URL: https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKEN POST数据格式:j…

DH参数例子-SCARA机器人

建议先阅读<上一篇>。 DH参数分配 此处说到的SCARA机器人是KUKA KR10机器人&#xff1a; 它是一个revolute_revolute_prismatic_revolute结构或者简称为RRPR结构&#xff0c;并且所有的关节轴都是平行的。 步骤&#xff11;&#xff1a;从{1&#xff0c;2&#xff0c…

约束求解器-Z3

关于z3 Z3 是一个微软出品的开源约束求解器&#xff0c;能够解决很多种情况下的给定部分约束条件寻求一组满足条件的解的问题&#xff08;可以简单理解为解方程的感觉&#xff0c;虽然这么比喻其实还差距甚远&#xff0c;请勿吐槽&#xff09;&#xff0c;功能强大且易于使用&a…

约束求解器Z3

目录 预备知识1.关于z3 实验目的实验环境实验步骤一实验步骤二实验步骤三 预备知识 1.关于z3 Z3是一个微软出品的开源约束求解器&#xff0c;能够解决很多种情况下的给定部分约束条件寻求一组满足条件的解的问题&#xff08;可以简单理解为解方程的感觉&#xff0c;虽然这么比…

Geomesa-HBase索引篇——Z3索引

目录 1. 概述 2. 原理 2.1 概述 2.2 分片存储机制 2.3 Epoch Week机制 2.4 时空索引机制 2.5 Fid机制 2.6 多个数据的封装 3. 代码实现 3.1 获取分片 3.2 获取Epoch Week 3.3 获取时空索引 3.4 获取Fid 3.5 多个数据的封装 1. 概述 在大量的场景当中&#xff0c…

matlab函数参数不足,调用函数显示输入参数不足

问题描述.png (29.7 KB, 下载次数: 1) 2015-1-27 09:34 上传 %Gauss-Newton算法实现如下 function[x,minf] = GN(f,x0,var,eps)formatlong; ifnargin == 3 %如果没有设置eps,则eps=1.0e-6eps = 1.0e-6; end m = 0; S =transpose(f)*f; %trnspose是转…

mark点Z3学习资料整理

文章目录 Anything is NothingLess is MoreSMTz3 classeslogic programming Reasoning符号推理策略strategiesFixed-point关系代数datalog程序分析验证 Anything is Nothing 前几个月科研用到z3-solver&#xff0c;学习了下&#xff0c;主要注释写在源码上进行学习和试验&…

z3 guide

Z3是微软研究院开发的高性能定理证明程序。Z3有许多应用场合&#xff0c;如:软件/硬件验证和测试&#xff0c;约束求解&#xff0c;混合系统的分析&#xff0c;安全&#xff0c;生物(硅分析)&#xff0c;几何问题。 Z3发行版还包含C、C、.Net、Java和OCaml 的api。Z3Py的源代码…

【Django】无法从“django.utils.encoding”导入名称“force_text”

整晚处理 Django 的导入错误。 我将把它作为提醒&#xff0c;希望处于相同情况的人数会减少。 原因 某些软件包版本不支持Django 4 请看下表并决定Django和Python的版本 方案 如果出现难以响应&#xff0c;或者更改环境麻烦&#xff0c;请尝试以下操作 例如出现以下错误 …

走迷宫(maze) 难度**

题目描述 有一个 mn 格的迷宫(表示有 m 行、n 列)&#xff0c;其中有可走的也有不可走的&#xff0c;如果用 11 表示可以走&#xff0c;00 表示不可以走。 文件读入这 mn 个数据和起 始点、结束点(起始点和结束点都是用两个数据来描述的&#xff0c;分别表示这个点的行号和列…

地下迷宫

import java.util.*;/*** 题目大意:n*m格迷宫,1代表青蛙可以通过,0不能通过* 青蛙体力值P,每次走一步,横向走消耗体力值1,向下走不消耗体力,* 向上走消耗体力值3.* 青蛙初始位置(0,0),迷宫出口(0,m-1)* 求青蛙走出迷宫的路径*/ public class Main {static class Node {int x;in…

7-2 地下迷宫探索

7-2 地下迷宫探索 分数 30 全屏浏览题目 切换布局 作者 DS课程组 单位 浙江大学 地道战是在抗日战争时期&#xff0c;在华北平原上抗日军民利用地道打击日本侵略者的作战方式。地道网是房连房、街连街、村连村的地下工事&#xff0c;如下图所示。 我们在回顾前辈们艰苦卓绝…

走迷宫图解

本节利用栈的思想用试探法进行了迷宫一条路径的探索。其中主要的操作是找到下一个空格、如果空格不再可行退回上一个格、每走过一个格子将走过的格子标记为-1防止循环走。 原理如下图&#xff1a; 具体的代码如下&#xff1a; #走一个任意的5*5迷宫 #mg可以为[[1,1,1,1,1,1],…

C/C++编程:获取路径中的文件名

文件是否存在 bool fileExists(const char *fileName) {ifstream infile(fileName);return infile.good(); }C/C获取路径中的文件名 void getfilename(const char *filename, char *name)//从完整路径名中解析出文件名称&#xff0c;例如&#xff1a;/home/test/abc.txt,解析…

Linux C 文件路径中获取文件名及路径

编程中有时会遇到需要把文件路径中的文件名或者路径提取出来的情况&#xff0c;发现了两个好用的函数记录一下。 一、提取文件名 头文件&#xff1a;#include <libgen.h> **函数&#xff1a;**char *basename(char *path); 注&#xff1a;这个函数不会修改传入的 path …