前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >深度学习框架落地 | 量化网络的重要性(附源码地址下载)

深度学习框架落地 | 量化网络的重要性(附源码地址下载)

作者头像
计算机视觉研究院
发布于 2021-01-14 08:26:02
发布于 2021-01-14 08:26:02
1K00
代码可运行
举报
运行总次数:0
代码可运行

深度学习在移动端的应用是越来越广泛,由于移动端的运算力与服务器相比还是有差距,所以在移动端部署深度学习模型的难点就在于如何保证模型效果的同时,运行效率也有保证。

在实验阶段对于模型结构可以选择大模型,因为该阶段主要是为了验证方法的有效性。在验证完了之后,开始着手部署到移动端,这时候就要精简模型的结构了,一般是对训好的大模型进行剪枝,或者参考现有的比如MobileNetV2和ShuffleNetV2等轻量级的网络重新设计自己的网络模块。而算法层面的优化除了剪枝还有量化,量化就是把浮点数(高精度)表示的权值和激活值用更低精度的整数来近似表示。低精度的优点有,相比于高精度算术运算,其在单位时间内能处理更多的数据,而且权值量化之后模型的存储空间能进一步的减少等等。

超越MobileNetV3的轻量级网络(文末论文下载)

对训练好的网络做量化,在实践中尝试过TensorRT的后训练量化算法,效果还不错。但是如果能在训练过程中去模拟量化的过程,让网络学习去修正量化带来的误差,那么得到的量化参数应该是更准确的,而且在实际量化推断中模型的性能损失应该能更小。

近年来,定点量化使用更少的比特数(如8-bit、3-bit、2-bit等)表示神经网络的权重和激活已被验证是有效的。定点量化的优点包括低内存带宽、低功耗、低计算资源占用以及低模型存储需求等。

低精度定点数操作的硬件面积大小及能耗比高精度浮点数要少几个数量级。使用定点量化可带来4倍的模型压缩、4倍的内存带宽提升,以及更高效的cache利用(很多硬件设备,内存访问是主要能耗)。除此之外,计算速度也会更快(通常具有2x-3x的性能提升)。由表2可知,在很多场景下,定点量化操作对精度并不会造成损失。另外,定点量化对神经网络于嵌入式设备上的推断来说是极其重要的。

目前,学术界主要将量化分为两大类:Post Training Quantization和Quantization Aware Training。Post Training Quantization是指使用KL散度、滑动平均等方法确定量化参数且不需要重新训练的定点量化方法。Quantization Aware Training是在训练过程中对量化进行建模以确定量化参数,它与Post Training Quantization模式相比可以提供更高的预测精度。本文主要针对Quantization Aware Training量化模式进行阐述说明。

训练模拟量化

方法介绍

首先来看下量化的具体定义,对于量化激活值到有符号8bit整数,论文中给出的定义如下:

公式中的三角形表示量化的缩放因子,x表示浮点数激活值,首先通过除以缩放因子然后最近邻取整,然后把范围限制到一个区间内,比如量化到有符号8bit,那么范围就是 [-128, 127]。而对于权值还有一个小的技巧,就是量化到[-127, 127]:

具体为什么这么做,论文中说了是为了实现上的优化,具体解释可以看论文[Quantization and Training of Neural Networks for Efficient Integer-Arithmetic-Only Inference]附录B ARM NEON details这一小节。而训练量化说白了就是在forward阶段去模拟量化这个过程,本质就是把权值和激活值量化到8bit再反量化回有误差的32bit,所以训练还是浮点,backward阶段是对模拟量化之后权值的求梯度,然后用这个梯度去更新量化前的权值。然后在下个batch继续这个过程,通过这样子能够让网络学会去修正量化带来的误差。

上面给这个示意图就很直观的表示了模拟量化的过程,比如上面那条线表示的是量化前的范围[rmin, rmax],然后下面那条线表示的就是量化之后的范围[-128, 127],比如现在要进行模拟量化的forward,先看上面那条线从左到右数第4个圆点,通过除以缩放因子之后就会映射124到125之间的一个浮点数,然后通过最近邻取整就取到了125,再通过乘以缩放因子返回上面第五个圆点,最后就用这个有误差的数替换原来的去forward。forward阶段的模拟量化用公式表示如下:

backward阶段求梯度的公式表示如下:

对于缩放因子的计算,权值和激活值的不一样,权值的计算方法是每次forward直接对权值求绝对值取最大值,然后缩放因子 weight scale = max(abs(weight)) / 127。然后对于激活值,稍微有些不一样,激活值的量化范围不是简单的计算最大值,而是通过EMA(exponential moving averages)在训练中去统计这个量化范围,更新公式如下:

moving_max = moving_max * momenta + max(abs(activation)) * (1- momenta)

公式中的activation表示每个batch的激活值,而论文中说momenta取接近1的数就行了,在实验中是取0.95。然后缩放因子 activation scale = moving_max /128。

量化训练时怎么进行反向传播

如下图所示,经过quantize和dequantize后得到的是有误差的浮点数,所以训练还是针对浮点,反向传播过程中的所有输入和输出均为浮点型数据。梯度更新时,计算出的梯度将被加到原始权重上而非量化后或反量化后的权重上。

左图是Backward Pass,右图是Weight Updating

对称量化与非对称量化

非对称量化将浮点数范围内的最小/最大值映射为整数范围内的最小/最大值。这是通过使用零点(也称为量化偏差,或偏移)来实现的。需要注意的是bias的需要是整型,因为在深度学习的模型中,有太多的0-padding存在了,若是bias非整型,那么在量化过程中会有大量的数值0的精度收到损失。

对称量化在最大或最小值间选择最大的绝对值作为量化范围,不设置零点,量化的浮点范围关于原点对称。

对称量化的范围选择有full range和restricted range两种,论文上说restricted range精度会更低一些。PyTorch(v1.3)和ONNX用的是full range,TensorFlow、 NVIDIA TensorRT 和Intel DNNL (aka MKL-DNN)用的是restricted range。

这两种模式的选择主要是做简单性和量化范围利用率之间的trade off。当使用非对称量化时,量化范围被充分利用,浮点数的min、max直接映射到量化范围的min、max;当使用对称量化时,如果浮点数分布偏向零点一侧,会造成量化范围利用率降低(如ReLU,相当于有效位减少了1bit)。另一方面来看,非对称量化要引入零点增加复杂度。

逐层量化和逐通道量化

某些层的权重参数不同通道之间的数据方差很大,利用常见的per-layer量化策略(即整个层的参数作为一个tensor进行量化),则会使得值较小的通道直接全部被置为0,导致精度的下降,per-channel的方法可以解决这个问题,但是在硬件实现上因为要针对每一个通道都有自己独立的缩放系数和偏移值考虑,会导致很多额外的开销,所以目前TensorRT和Tensorflow等都采用的是per-layer。

add和concat怎么量化?

量化的add相比float计算开销更expensive,需要将一组input基于另一组input先rescale,公式为

concat支持和add一样的rescale方法来实现,但uint8的rescale是一个有损的操作,tensorflow采用重新统计concat op的input、output,采用input、output统一min、max的方式可以实现无损,代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
bool HardcodeMinMaxForConcatenation(Model* model, Operator* op) {
  // Do not early return if the output already has min/max:
  // we may still need to adjust the inputs min/max.
  bool has_minmax = false;
  double overall_min = std::numeric_limits<double>::infinity();
  double overall_max = -std::numeric_limits<double>::infinity();
  for (const auto& input : op->inputs) {
    if (model->GetArray(input).minmax) {
      has_minmax = true;
      const auto* minmax = model->GetArray(input).minmax.get();
      if (minmax) {
        overall_min = std::min(overall_min, minmax->min);
        overall_max = std::max(overall_max, minmax->max);
      }
    }
  }
  auto& output = model->GetArray(op->outputs[0]);
  if (output.minmax) {
    has_minmax = true;
    const auto* minmax = model->GetArray(op->outputs[0]).minmax.get();
    if (minmax) {
      overall_min = std::min(overall_min, minmax->min);
      overall_max = std::max(overall_max, minmax->max);
    }
  }
  if (!has_minmax) {
    return false;
  }
  MinMax overall_minmax;
  overall_minmax.min = overall_min;
  overall_minmax.max = overall_max;
  bool changed = false;
  for (const auto& input : op->inputs) {
    auto& array = model->GetArray(input);
    if (!array.minmax) {
      changed = true;
    } else if (!(overall_minmax == array.GetMinMax())) {
      changed = true;
      LOG(WARNING)
          << "Tweaking the MinMax of array " << input << ", which is "
          << "an input to " << LogName(*op) << ", because we want all inputs "
          << "and outputs of a Concatenation operator to have the same MinMax "
          << "so that it can be implemented as a pure byte-copy, no "
             "arithmetic.";
    }
    array.GetOrCreateMinMax() = overall_minmax;
  }
  if (!output.minmax) {
    changed = true;
  } else if (!(overall_minmax == output.GetMinMax())) {
    changed = true;
    LOG(WARNING)
        << "Tweaking the MinMax of the output array of " << LogName(*op)
        << ", because we want all inputs "
        << "and outputs of a Concatenation operator to have the same MinMax "
        << "so that it can be implemented as a pure byte-copy, no arithmetic.";
  }
  output.GetOrCreateMinMax() = overall_minmax;

  return changed;
}

量化范围的选取

量化分为weight和activation的量化。

weight量化范围通过每次forward时,对weight的绝对值取最大值得到。

activation量化范围用EMA算法平滑,可以避免一些极端激活值情况带来的参数分布影响,公式如下 :

为每个batch的激活值,

为接近1的值,可取0.9。

今天就先到这里,下一期我们给大家带来量化训练以及卷积核剪裁原理

© THE END

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-01-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 计算机视觉战队 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【AI系统】低比特量化原理
计算机里面数值有很多种表示方式,如浮点表示的 FP32、FP16,整数表示的 INT32、INT16、INT8,量化一般是将 FP32、FP16 降低为 INT8 甚至 INT4 等低比特表示。
用户11307734
2024/12/05
2080
LLM 大模型学习必知必会系列(六):量化技术解析、QLoRA技术、量化库介绍使用(AutoGPTQ、AutoAWQ)
模型的推理过程是一个复杂函数的计算过程,这个计算一般以矩阵乘法为主,也就是涉及到了并行计算。一般来说,单核CPU可以进行的计算种类更多,速度更快,但一般都是单条计算;而显卡能进行的都是基础的并行计算,做矩阵乘法再好不过。如果把所有的矩阵都加载到显卡上,就会导致显卡显存的占用大量增加,尤其是LLM模型大小从7b、14b、34b到几百b不等,占用显存的大小就是惊人的数字,如何在减少运算量和显存占用的条件下,做到推理效果不下降太多呢?在这里需要引入浮点数和定点数的概念。
汀丶人工智能
2024/05/26
2.2K0
LLM 大模型学习必知必会系列(六):量化技术解析、QLoRA技术、量化库介绍使用(AutoGPTQ、AutoAWQ)
MXNet实现卷积神经网络训练量化
深度学习在移动端的应用是越来越广泛,由于移动端的运算力与服务器相比还是有差距,所以在移动端部署深度学习模型的难点就在于如何保证模型效果的同时,运行效率也有保证。
BBuf
2020/03/20
1.2K0
MXNet实现卷积神经网络训练量化
深度学习算法优化系列三 | Google CVPR2018 int8量化算法
这是Google在CVPR 2018上发表的一篇int8量化的论文,题目为《Quantization and Training of Neural Networks for Efficient Integer-Arithmetic-Only Inference》。也是入门量化最经典的论文之一。论文介绍了一种只使用整数运算的量化方式,相比于浮点数运算效率更高。一起先来看看这篇论文吧。论文的axriv地址可以在附录中找到。
BBuf
2019/12/27
2.7K0
深度学习算法优化系列三 | Google CVPR2018 int8量化算法
Pytorch实现卷积神经网络训练量化(QAT)
深度学习在移动端的应用越来越广泛,而移动端相对于GPU服务来讲算力较低并且存储空间也相对较小。基于这一点我们需要为移动端定制一些深度学习网络来满足我们的日常续需求,例如SqueezeNet,MobileNet,ShuffleNet等轻量级网络就是专为移动端设计的。但除了在网络方面进行改进,模型剪枝和量化应该算是最常用的优化方法了。剪枝就是将训练好的「大模型」的不重要的通道删除掉,在几乎不影响准确率的条件下对网络进行加速。而量化就是将浮点数(高精度)表示的权重和偏置用低精度整数(常用的有INT8)来近似表示,在量化到低精度之后就可以应用移动平台上的优化技术如NEON对计算过程进行加速,并且原始模型量化后的模型容量也会减少,使其能够更好的应用到移动端环境。但需要注意的问题是,将高精度模型量化到低精度必然会存在一个精度下降的问题,如何获取性能和精度的TradeOff很关键。
BBuf
2020/08/04
3.9K0
Pytorch实现卷积神经网络训练量化(QAT)
TORCH.FX第二篇——PTQ量化实操
本文紧接上一篇《实践torch.fx第一篇——基于Pytorch的模型优化量化神器》继续说,主要讲如何利用FX进行模型量化。
老潘
2023/10/19
2.1K0
TORCH.FX第二篇——PTQ量化实操
卷积神经网络训练模拟量化实践
深度学习在移动端的应用是越来越广泛,由于移动端的运算力与服务器相比还是有差距,
Ldpe2G
2019/01/13
1.8K0
INT8量化训练
【GiantPandaCV导读】本文聊了两篇做INT8量化训练的文章,量化训练说的与quantization-aware Training有区别,量化训练指的是在模型训练的前向传播和后向传播都有INT8量化。两篇文章都是基于对梯度构建分析方程求解得到解决量化训练会引起的训练崩溃和精度损失严重的情况。
BBuf
2021/04/30
1.1K0
LLM 盛行,如何优雅地训练大模型?
ChatGPT于2022年12月初发布,震惊轰动了全世界,发布后的这段时间里,一系列国内外的大模型训练开源项目接踵而至,例如Alpaca、BOOLM、LLaMA、ChatGLM、DeepSpeedChat、ColossalChat等。不论是学术界还是工业界,都有训练大模型来优化下游任务的需求。
NewBeeNLP
2023/09/01
2.3K0
LLM 盛行,如何优雅地训练大模型?
模型量化-学习笔记
随着深度学习的不断发展,神经网络广泛应用于不同的领域,取得远超以往的效果的同时深度网络模型的复杂度也越来越高, 这严重制约了它在工业界发展.
Johns
2022/06/22
4.2K0
【AI系统】TVM 实践案例
在本文我们探讨一下,如何利用 AI 编译器在新的硬件上部署一个神经网络,从算法设计到实际运行,有哪些需要考虑的地方?本文将以 TVM 为例,首先介绍一下 TVM 的工作流:
用户11307734
2024/12/02
3120
低比特量化之DoreFa-Net理论与实践
这篇文章首先详细介绍了DoreFaNet任意比特量化网络的原理,然后提供了DoreFaNet的Pytorch代码实现解析,并给出将DoreFa-Net应用到YOLOV3模型上之后的精度测试结果。论文原文:https://arxiv.org/pdf/1606.06160.pdf 。
BBuf
2020/07/28
1.4K0
低比特量化之DoreFa-Net理论与实践
深度学习Int8的部署推理原理和经验验证
论文出处:《Integer Quantization for Deep Learning Inference Principles and Empirical Evaluation》 时间:2020.April 单位:NVIDIA
BBuf
2022/05/27
2.1K0
深度学习Int8的部署推理原理和经验验证
一起实践神经网络量化系列教程(一)!
老潘刚开始接触神经网络量化是2年前那会,用NCNN和TVM在树莓派上部署一个简单的SSD网络。那个时候使用的量化脚本是参考于TensorRT和NCNN的PTQ量化(训练后量化)模式,使用交叉熵的方式对模型进行量化,最终在树莓派3B+上部署一个简单的分类模型(识别剪刀石头布静态手势)。
老潘
2023/10/19
1.3K0
一起实践神经网络量化系列教程(一)!
F8Net:只有8比特乘法的神经网络量化
【GaintPandaCV导语】F8Net用定点化量化方法对DNN进行量化,在模型推理只有8-bit的乘法,没有16-bit/32-bit的乘法,采用非学习的方法即标准差来定小数位宽。目前是我看到的第一篇硬件层面全8-bit乘法的模型推理的方法。
BBuf
2022/04/06
1.6K0
F8Net:只有8比特乘法的神经网络量化
TensorFlow下构建高性能神经网络模型的最佳实践
作者 | 李嘉璇 责编 | 何永灿 随着神经网络算法在图像、语音等领域都大幅度超越传统算法,但在应用到实际项目中却面临两个问题:计算量巨大及模型体积过大,不利于移动端和嵌入式的场景;模型内存占用过大,导致功耗和电量消耗过高。因此,如何对神经网络模型进行优化,在尽可能不损失精度的情况下,减小模型的体积,并且计算量也降低,就是我们将深度学习在更广泛的场景下应用时要解决的问题。 加速神经网络模型计算的方向 在移动端或者嵌入式设备上应用深度学习,有两种方式:一是将模型运行在云端服务器上,向服务器发送请求,接收服务器
用户1737318
2018/07/20
1.2K0
tf.quantization
三、tf.quantization.fake_quant_with_min_max_args
狼啸风云
2019/09/06
1.8K0
深度学习算法优化系列十二 | 旷视科技 DoReFa-Net
我们知道,XORNet以及BNN都没有在反向传播阶段做梯度的量化,之前也没有任何工作可以在反向传播阶段将梯度量化到8位一下并且保持相当的预测精度。在BNN和XORNet中,虽然权重是二值化的,但是梯度仍然是全精度浮点数,因此在反向传播时反卷积依然是1bit和32bit数之间的运算,这导致BNN和XORNet的训练时间主要花在反向传播阶段。
BBuf
2020/02/25
2.7K4
INT4量化用于目标检测
【GiantPandaCV】文章2019 CVPR,讲的是Int 4量化用于目标检测,主要是工程化的一些trick。
BBuf
2021/03/24
1.1K0
INT4量化用于目标检测
基于OneFlow实现量化感知训练
这篇文章主要是讲解一下量化感知训练的原理,以及基于OneFlow实现一个Demo级别的手动量化感知训练。
BBuf
2021/08/19
8660
相关推荐
【AI系统】低比特量化原理
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验