Reference:

https://github.com/NervanaSystems/distiller

https://nervanasystems.github.io/distiller/index.html

PART I: 介绍

Distiller模型压缩包含的算法:  稀疏算法(剪枝+正则化)+低精度算法(量化)

Distiller特点:

(1)    该框架融合了剪枝,正则化及量化算法

(2)    一系列分析及评估压缩性能的工具

(3)    较流行压缩算法的应用

稀疏神经网络可以基于 (weight and biases) activations的稀疏tensor进行计算。

关注稀疏度的原因:对于像GoogleNet 之类的大型网络,对计算十分敏感,在经过加速处理过的设备上进行inference仍需花费大量时间。较大的模型占用内存资源

在移动端模型的存储及转移主要受到模型的大小及下载时间限制

Smaller

具有稀疏表示的数据并不需要进行解压缩

三种表示方法:1.稀疏表示,2.密集表示,3.针对硬件特点进行特殊的表示

通过剪枝及正则化处理,对于向量计算的compute engine的权重删除。

Faster

神经网络中的许多层都是bandwidth-bound,这意味着执行时间主要是被可利用的bandwidth占用,其中,占用时间比较长的为全连接层,同时RNN及LSTM层存在大量的bandwidth-dominated操作。

Pruning:对网络中的权重及激活值进行稀疏化处理,基于二元标准来进行决定那个权重可以修剪。将满足修剪标准的权重进行赋值为0并不让其参见反向传播运算。

可修剪的对象包括:权重,偏差及激活值。

稀疏性:张量中存在0元素的个数占整个tensor向量中的比例,L0正则化,统计非0元素的个数

Density = 1 – sparsity

Distiller工具:distiller.sparsity distiller.density

权重/模型修剪:用于提高网络权重稀疏性的一系列方法,通过一个修剪标准来决定哪个元素需要进行修剪,标准即pruning criteria,最常用的标准是每个元素的绝对值,其值与某个阈值进行比较,如果低于这个阈值,就将该元素的值置为0.

Distiller工具:distiller.MagnitudeParameterPruner 基于L1正则化的对于最终结果贡献量较小的权重重要性较低,而且可以被移除。

对于prune的理解 :参数量较大的模型中,存在大量的逻辑及特征冗余。一种想法是搜索尽可能多的权值为0的权重,同时在inference时可以达到与密集模型相似的准确率。另一种想法是,在高维度的参数空间中,密集模型的解空间中可能会存在一些稀疏解,修剪算法就是为了寻找这个稀疏解。

One-shot pruning :对一个训练好的模型进行一次修剪

Iterative training :pruning-followed-by-retraining(fine-tuning),在训练迭代过程中,需要考虑的问题包括:pruning的标准是如何改变,迭代多少次,多久变化一次,那些张量需要被prune,这些被称为pruning schedule

对Iterative pruning 的理解:基于一个评价标准将权重进行重复训练学习,判断哪个权重是重要的,并将不重要的权重进行删除。 调整后的权重将模型进行性能上的恢复,每次迭代修剪更多的权重。

修剪的停止条件也在schedule中,其取决于修剪算法。停止条件两个参考: specific sparsity level,required compute budget

修剪粒度(pruning granularity):对单个权重元素进行修剪,称为element-wise修剪,有时被称为find-grained pruning

Coarse-grained pruning: structure pruning , group pruning(filter pruning整个filters被移除),block pruning

敏感度分析:

将稀疏性引入修剪过程中的难点在于:对于每层网络张量中,阈值的选择及sparsity level,根据张量对修剪的敏感度进行排序。

其思想是,针对特定的网络层设置pruning level(percentage),只对模型修剪一次,然后在测试数据集上进行评估并记录得到的分数值。若在每个参数化的网络层上应用此方法,在每个层上设置多个sparsity levels,可以得到每个层对于修剪的敏感性。

在进行敏感度分析前,预训练模型应达到最大的准确率,这是因为需要了解对于特定层权重的修剪对模型的性能造成的影响。

Distiler可以对结构进行敏感性评估,基于L1 –normal的独立元素进行element-wise pruning 敏感度分析以及基于filters间的mean L1-Norm 的filter-wise pruning 。

相关函数:perform_sensitivity_analysis

正则化: 对模型算法进行修改的主要目的是减少generalization loss而不是训练损失。

正则化与网络稀疏表达的关系:

通过稀疏修剪对模型进行正则化处理:在给定sparsity constraint的限制条件下,网络一旦达到了局部最小值,则放宽限制条件,让网络可以以更高准确率逃离局部极小值的鞍点。

正则化也可以应用到稀疏表达中:L2正则化可以减少过拟合,同时压缩较大值的参数,但无法使这些参数的值完全变为0。而L1正则化则可以将某些参数置为0,在限制模型的同时对模型进行了简化处理。

Group Regularization

对整个groups of parameter elements进行正则化处理。无论这个group是否被稀疏化处理过,该group结构都要预先定义。

Distiller中的相关函数: distiller.GroupLassoRegularizer

量化

量化是减少表示一个数的bit位数的过程,deep learning中的主流精度为32位浮点精度。为了降低网络模型的带宽及计算需求,开始转向较低精度的研究。

如果权重为二值的,如(-1,1)或者为(-1,0,1)则卷积层及全连接层中的计算可以由加减操作执行,将乘法操作完全移除。如果激活值也为二值类型的,则加法操作也可以移除,可以用位运算代替。

Integer与FP32的对比

数字精度的两个属性,I:动态范围,即可以表示数字的范围。II:根据需要表示的数值来决定精度。对于n位整形数字,其动态范围为[-2^(n-1)..2^(n-1)-1],INT8:[-128,127],可以表示2^(N)个数字,网络模型中32位精度能够表示的分布范围更广,同时,模型中不同层动态范围是不同的,权重及activation的分布也是不同的。

为了将tensor的浮点动态范围映射到整数精度的范围内增加了一个scale factor,scale factor大部分情况为浮点型。

避免溢出

累加器中存放卷积层及全连接层的中间结果。如果,将权重以及激活值的设置相同的比特位,很快就会溢出。因此,累加器中的精度要更高一些。两个n-bit的数字相乘得到2n-bit的数字,卷积层中存在c*k^2次乘法操作,为了避免溢出,累加器的位数应为(2n+M),M至少为log2(c*k^2)

保守量化:INT8

如果将一个FP32的预训练模型不进行再训练直接将其量化为INT8,则会造成一定准确率的损失。

Simple factor的设置:根据每个tensor中的每一层进行确定,最简单的方式就是将float tensor中的min/max映射为integer中的min/max,对于权重及偏差,这种操作比较简单,是因为其训练完成后,其值是固定的,而对于activation,其值可以从两个方面进行获得。

(1)Offline:即在部署模型之前进行激活值统计操作,基于统计的信息,计算得到scale factor,当模型部署完后将其值固定。这种方式存在一定的风险,即运行时,遇到的值超出了原来观察到的范围,而这个超出的值会被clip,进而造成准确率上的损失。

(2)Online:即在运行时动态的计算tensor中的min/max值。这种方式不会发生clip情况。而增加的计算量却很大。

基于全精度的激活层存在异常值,可以通过缩小min/max的范围将这个异常值进行丢弃,同时,也可以通过clip操作来提高包含主要信息部分的精度。一种简单有效的方式是用min/max的均值来替换实际的值

另一个可以优化的点是scale factor:最常用的方法是每一层使用scale-factor,也可以每个通道进行设置。

贪婪型量化:INT4

将FP32模型直接量化为INT4或者更低的精度,使准确率大幅度降低

解决方法:

(1)    training/retraining:将量化考虑到训练中

(2)    替换激活函数:将无边界的ReLU替换为有边界的激活函数。

(3)    调整网络的结构:通过增加层的宽度来弥补由于量化产生的损失信息。或者将卷积用多个二值卷积进行替换,通过scale可以调整覆盖更大的范围

(4)    模型的第一层和最后一层不进行量化操作

(5)    迭代量化:首先对预训练的FP32的模型进行部分量化,然后进行再训练恢复由于量化产生的准确率的损失

(6)    将权重及激活值的精度进行混合:激活对量化的敏感度相比权重要更敏感一些

包含量化的训练

训练过程中全精度的权重也被保留,用于记录精度损失造成 的梯度上的变化,inference时只有量化后的权重起作用。

PART II: 基于Distiller 的分类模型

Step I : git clone https://github.com/NervanaSystems/distiller.git
Step II: 创建环境 python3 –m virtualenv env (安装参考: https://packaging.python.org/guides/installing-using-pip-and-virtual-environments/)
StepIII: cd distiller  && pip3 install -e . 
StepIV: cd distiller/examples/classifier_compression
StepV: 只对模型进行训练,不进行压缩处理
python3 compress_classifier.py --arch simplenet_cifar ../../../data.cifar10 -p 30 -j=1 --lr=0.01
--arch:模型名称
-p:打印频率
-j: 线程
--lr:学习率
StepVI: 统计稀疏模型的参数
python3 compress_classifier.py --resume=../ssl/checkpoints/checkpoint_trained_ch_regularized_dense.pth.tar -a=resnet20_cifar ../../../data.cifar10 --summary=sparsity
--resume:稀疏模型文件路径
--summary: {sparsity,compute,model,modules,png,png_w_params,onnx}
Sparsity:统计稀疏信息
Compute:统计计算量信息
Model:详细的模型描述
Modules:每层对应的类型
PNG:将网络结构保存为图片
png_w_params:将网络中的权重信息保存为图片
打印信息

Name:处理层名称
Shape:该层尺寸
NNZ(dense):稀疏前该层的参数量,其值为shape[0]*shape[1]*shape[2]*shape[3]
NNZ(sparse):处理后该层的参数量。
Cols,Rows,Ch,2D,3D,Fine分别代表,在纵向,横向,Channel-wise,Kernel-wise,Filter-wise,Element-wise(属于Fine-grained pruning)上参数稀疏的程度,其值为(NNZ(dense)-NNZ(sparse)) / NNZ(dense)
Std:该层的标准差
Mean: 该层的均值
Abs-Mean:该层绝对值的均值 
Total sparsity = (total_NNZ(dense) – total_NNZ(sparse)) / total_NNZ(dense)
StepVII: 统计稀疏模型的计算量
python3 compress_classifier.py --resume=../ssl/checkpoints/checkpoint_trained_ch_regularized_dense.pth.tar -a=resnet20_cifar ../../../data.cifar10 --summary=sparsity

Name:该层名称
Type:该层的类型
Attrs: 卷积核大小
IFM:输入尺寸
IFM volume:输入维度 = IFM[0] * IFM[1] * IFM[2] * IFM[3]
OFM:输出尺寸
OFM volume:输出维度 = OFM[0] * OFM[1] * OFM[2] * OFM[3]
Weights volume:权重维度 = Attrs[0] * Attrs[1] * IFM[1] * OFM[1]
MACs  = OFM[2] * OFM[3] * Weights volume
Step VIII: post-training quantization
python3 compress_classifier.py -a resnet20_cifar ../../../data.cifar10 --resume ../ssl/checkpoints/checkpoint_trained_dense.pth.tar --quantize-eval --evaluate
--quantize-eval 在进行evaluate前进行线性量化操作

PART III: Distiller 代码部署步骤

Step I:  在 main.py中增加代码

1. Preparing the code: 调用Distiller  通过sys.path将distiller的根目录引入到main.py文件中。

2. 置定义输入参数

--summary:有关压缩说明

--compress:指明 compression schedule文件路径

增加对上面两个参数的处理代码

3. Optimizer及learning-rate decay policy scheduler

4. setup the logging backends:一个是Python logger backend用于从文件及命令行中读取参数;另一个是TensorBoard backend logger将logs信息变为tensorboard 数据文件(tflogger)

5. Training loop:

6. 下列代码位于train中用于记录信息

7. 在train外进行迭代训练优化

												

基于Distiller的模型压缩工具简介的更多相关文章

  1. ChatGirl 一个基于 TensorFlow Seq2Seq 模型的聊天机器人[中文文档]

    ChatGirl 一个基于 TensorFlow Seq2Seq 模型的聊天机器人[中文文档] 简介 简单地说就是该有的都有了,但是总体跑起来效果还不好. 还在开发中,它工作的效果还不好.但是你可以直 ...

  2. TensorFlow-Bitcoin-Robot:一个基于 TensorFlow LSTM 模型的 Bitcoin 价格预测机器人

    简介 TensorFlow-Bitcoin-Robot:一个基于 TensorFlow LSTM 模型的 Bitcoin 价格预测机器人. 文章包括一下几个部分: 1.为什么要尝试做这个项目? 2.为 ...

  3. TensorFlow-Bitcoin-Robot:一个基于 TensorFlow LSTM 模型的 Bitcoin 价格预测机器人。

    简介 TensorFlow-Bitcoin-Robot:一个基于 TensorFlow LSTM 模型的 Bitcoin 价格预测机器人. 文章包括一下几个部分: 1.为什么要尝试做这个项目? 2.为 ...

  4. 【tornado】系列项目(二)基于领域驱动模型的区域后台管理+前端easyui实现

    本项目是一个系列项目,最终的目的是开发出一个类似京东商城的网站.本文主要介绍后台管理中的区域管理,以及前端基于easyui插件的使用.本次增删改查因数据量少,因此采用模态对话框方式进行,关于数据量大采 ...

  5. 【tornado】系列项目(一)之基于领域驱动模型架构设计的京东用户管理后台

    本博文将一步步揭秘京东等大型网站的领域驱动模型,致力于让读者完全掌握这种网络架构中的“高富帅”. 一.预备知识: 1.接口: python中并没有类似java等其它语言中的接口类型,但是python中 ...

  6. 【转】【SSE】基于SSE指令集的程序设计简介

    基于SSE指令集的程序设计简介 作者:Alex Farber 出处:http://www.codeproject.com/cpp/sseintro.asp SSE技术简介 Intel公司的单指令多数据 ...

  7. DL4NLP——词表示模型(二)基于神经网络的模型:NPLM;word2vec(CBOW/Skip-gram)

    本文简述了以下内容: 神经概率语言模型NPLM,训练语言模型并同时得到词表示 word2vec:CBOW / Skip-gram,直接以得到词表示为目标的模型 (一)原始CBOW(Continuous ...

  8. Lucene:基于Java的全文检索引擎简介

    Lucene:基于Java的全文检索引擎简介 Lucene是一个基于Java的全文索引工具包. 基于Java的全文索引/检索引擎--Lucene Lucene不是一个完整的全文索引应用,而是是一个用J ...

  9. 基于 Agent 的模型入门:Python 实现隔离仿真

    2005 年诺贝尔经济学奖得主托马斯·谢林(Thomas Schelling)在上世纪 70 年代就纽约的人种居住分布得出了著名的 Schelling segregation model,这是一个 A ...

随机推荐

  1. AtCoder Grand Contest 036

    Preface 这篇已经鸽了好久的说,AGC037都打完了才回来补所以题目可能都记不大清楚了,如有错误请指正 这场感觉难度远高于上一场,从D开始就不会了,E没写(看了题解都不会写),F就是抄曲明姐姐的 ...

  2. [题解向] CF#536Div2の题解 E&F

    \(0x01~~Preface\) \(emmm\)这次CF本身打的很顺畅,但是居然unrated了--咕咕咕咕 这是头一次CF有比赛我全部题目都做了--可喜可贺可喜可贺233 简单总结一下前面四道题 ...

  3. linux的命令操作

    linux的命令操作 1.日常操作命令 **查看当前所在的工作目录pwd **查看当前系统的时间 date **查看有谁在线(哪些人登陆到了服务器)who 查看当前在线last 查看最近的登陆历史记录 ...

  4. Paper | No-reference Quality Assessment of Deblocked Images

    目录 故事背景 本文方法(DBIQ) 发表在2016年Neurocomputing. 摘要 JPEG is the most commonly used image compression stand ...

  5. Flutter命令突然无响应、vscode突然无法连接到IOS模拟器

    这周过来突然flutter相关命令运行都没有响应, 打开任务管理器,关闭所有dart进程即可解决

  6. Jmockit 构造函数与初始代码块

    from Jmockit 中文网 http://jmockit.cn/showArticle.htm?channel=4&id=14 有些编写不良好的类的构造函数,初始代码块,静态代码块存在大 ...

  7. centos上tcp抓包

    tcpdump host 10.1.131.75 -i eth0  -w data.cap 其中,10.1.131.75上目标机器的IP,eth0上网卡名称,data.cap上抓包数据写入的文件.

  8. win10怎么打开服务界面?

    在键盘上同时点击“win+R”键弹出运行界面,输入services.msc,按确定. 这时就弹出了服务的界面,如图:

  9. 云原生生态周报 Vol.9| K8s v1.15 版本发布

    本周作者 | 衷源.心贵 业界要闻 1.Kubernetes Release v1.15 版本发布,新版本的两个主题是持续性改进和可扩展性.(https://github.com/kubernetes ...

  10. Java 函数式编程—@FunctionalInterface----functional interface

    单一函数接口,可以使用拉姆达表达式的形式具体化和实例化. 本质是将接口函数签名化. 如定义了一个函数式接口如下: @FunctionalInterface interface GreetingServ ...