提交 7e0913ca 编写于 作者: W wanghaoshuang

Update

上级 11377e3c
...@@ -14,14 +14,14 @@ ...@@ -14,14 +14,14 @@
近年来,定点量化使用更少的比特数(如8-bit、3-bit、2-bit等)表示神经网络的权重和激活已被验证是有效的。定点量化的优点包括低内存带宽、低功耗、低计算资源占用以及低模型存储需求等。 近年来,定点量化使用更少的比特数(如8-bit、3-bit、2-bit等)表示神经网络的权重和激活已被验证是有效的。定点量化的优点包括低内存带宽、低功耗、低计算资源占用以及低模型存储需求等。
<p align="center"> <p align="center">
<img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/develop/docs/docs/images/algo/quan_table_0.png" height=258 width=600 hspace='10'/> <br /> <img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/release/1.0.1/docs/images/algo/quan_table_0.png" height=258 width=600 hspace='10'/> <br />
<strong>表1: 不同类型操作的开销对比</strong> <strong>表1: 不同类型操作的开销对比</strong>
</p> </p>
由表1可知,低精度定点数操作的硬件面积大小及能耗比高精度浮点数要少几个数量级。 使用定点量化可带来4倍的模型压缩、4倍的内存带宽提升,以及更高效的cache利用(很多硬件设备,内存访问是主要能耗)。除此之外,计算速度也会更快(通常具有2x-3x的性能提升)。由表2可知,在很多场景下,定点量化操作对精度并不会造成损失。另外,定点量化对神经网络于嵌入式设备上的推断来说是极其重要的。 由表1可知,低精度定点数操作的硬件面积大小及能耗比高精度浮点数要少几个数量级。 使用定点量化可带来4倍的模型压缩、4倍的内存带宽提升,以及更高效的cache利用(很多硬件设备,内存访问是主要能耗)。除此之外,计算速度也会更快(通常具有2x-3x的性能提升)。由表2可知,在很多场景下,定点量化操作对精度并不会造成损失。另外,定点量化对神经网络于嵌入式设备上的推断来说是极其重要的。
<p align="center"> <p align="center">
<img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/develop/docs/docs/images/algo/quan_table_1.png" height=155 width=500 hspace='10'/> <br /> <img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/release/1.0.1/docs/images/algo/quan_table_1.png" height=155 width=500 hspace='10'/> <br />
<strong>表2:模型量化前后精度对比</strong> <strong>表2:模型量化前后精度对比</strong>
</p> </p>
...@@ -45,7 +45,7 @@ $q = scale * r + b$ ...@@ -45,7 +45,7 @@ $q = scale * r + b$
前向传播过程采用模拟量化的方式,具体描述如下: 前向传播过程采用模拟量化的方式,具体描述如下:
<p align="center"> <p align="center">
<img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/develop/docs/docs/images/algo/quan_forward.png" height=433 width=335 hspace='10'/> <br /> <img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/release/1.0.1/docs/images/algo/quan_forward.png" height=433 width=335 hspace='10'/> <br />
<strong>图1:基于模拟量化训练的前向过程</strong> <strong>图1:基于模拟量化训练的前向过程</strong>
</p> </p>
...@@ -69,7 +69,7 @@ $$ ...@@ -69,7 +69,7 @@ $$
上述公式表明反量化操作可以被移动到`GEMM`之前,即先对$Xq$和$Wq$执行反量化操作再做`GEMM`操作。因此,前向传播的工作流亦可表示为如下方式: 上述公式表明反量化操作可以被移动到`GEMM`之前,即先对$Xq$和$Wq$执行反量化操作再做`GEMM`操作。因此,前向传播的工作流亦可表示为如下方式:
<p align="center"> <p align="center">
<img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/develop/docs/docs/images/algo/quan_fwd_1.png" height=435 width=341 hspace='10'/> <br /> <img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/release/1.0.1/docs/images/algo/quan_fwd_1.png" height=435 width=341 hspace='10'/> <br />
<strong>图2:基于模拟量化训练前向过程的等价工作流</strong> <strong>图2:基于模拟量化训练前向过程的等价工作流</strong>
</p> </p>
...@@ -79,7 +79,7 @@ $$ ...@@ -79,7 +79,7 @@ $$
由图3可知,权重更新所需的梯度值可以由量化后的权重和量化后的激活求得。反向传播过程中的所有输入和输出均为32-bit浮点型数据。注意,梯度更新操作需要在原始权重上进行,即计算出的梯度将被加到原始权重上而非量化后或反量化后的权重上。 由图3可知,权重更新所需的梯度值可以由量化后的权重和量化后的激活求得。反向传播过程中的所有输入和输出均为32-bit浮点型数据。注意,梯度更新操作需要在原始权重上进行,即计算出的梯度将被加到原始权重上而非量化后或反量化后的权重上。
<p align="center"> <p align="center">
<img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/develop/docs/docs/images/algo/quan_bwd.png" height=300 width=650 hspace='10'/> <br /> <img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/release/1.0.1/docs/images/algo/quan_bwd.png" height=300 width=650 hspace='10'/> <br />
<strong>图3:基于模拟量化训练的反向传播和权重更新过程</strong> <strong>图3:基于模拟量化训练的反向传播和权重更新过程</strong>
</p> </p>
...@@ -127,7 +127,7 @@ $$ Vt = (1 - k) * V + k * V_{t-1} $$ ...@@ -127,7 +127,7 @@ $$ Vt = (1 - k) * V + k * V_{t-1} $$
<p align="center"> <p align="center">
<img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/develop/docs/docs/images/algo/pruning_0.png" height=200 width=600 hspace='10'/> <br /> <img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/release/1.0.1/docs/images/algo/pruning_0.png" height=200 width=600 hspace='10'/> <br />
<strong>图4</strong> <strong>图4</strong>
</p> </p>
...@@ -139,7 +139,7 @@ $$ Vt = (1 - k) * V + k * V_{t-1} $$ ...@@ -139,7 +139,7 @@ $$ Vt = (1 - k) * V + k * V_{t-1} $$
减去被删除的一行:greedy pruning 减去被删除的一行:greedy pruning
<p align="center"> <p align="center">
<img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/develop/docs/docs/images/algo/pruning_1.png" height=200 width=450 hspace='10'/> <br /> <img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/release/1.0.1/docs/images/algo/pruning_1.png" height=200 width=450 hspace='10'/> <br />
<strong>图5</strong> <strong>图5</strong>
</p> </p>
...@@ -149,7 +149,7 @@ $$ Vt = (1 - k) * V + k * V_{t-1} $$ ...@@ -149,7 +149,7 @@ $$ Vt = (1 - k) * V + k * V_{t-1} $$
<p align="center"> <p align="center">
<img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/develop/docs/docs/images/algo/pruning_2.png" height=240 width=600 hspace='10'/> <br /> <img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/release/1.0.1/docs/images/algo/pruning_2.png" height=240 width=600 hspace='10'/> <br />
<strong>图6</strong> <strong>图6</strong>
</p> </p>
...@@ -176,7 +176,7 @@ $$ Vt = (1 - k) * V + k * V_{t-1} $$ ...@@ -176,7 +176,7 @@ $$ Vt = (1 - k) * V + k * V_{t-1} $$
#### 敏感度的理解 #### 敏感度的理解
<p align="center"> <p align="center">
<img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/develop/docs/docs/images/algo/pruning_3.png" height=200 width=400 hspace='10'/> <br /> <img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/release/1.0.1/docs/images/algo/pruning_3.png" height=200 width=400 hspace='10'/> <br />
<strong>图7</strong> <strong>图7</strong>
</p> </p>
...@@ -189,7 +189,7 @@ $$ Vt = (1 - k) * V + k * V_{t-1} $$ ...@@ -189,7 +189,7 @@ $$ Vt = (1 - k) * V + k * V_{t-1} $$
用户给定一个模型整体的剪裁率,我们通过移动**图5**中的黑色实线来找到一组满足条件的且合法的剪裁率。 用户给定一个模型整体的剪裁率,我们通过移动**图5**中的黑色实线来找到一组满足条件的且合法的剪裁率。
<p align="center"> <p align="center">
<img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/develop/docs/docs/images/algo/pruning_4.png" height=200 width=400 hspace='10'/> <br /> <img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/release/1.0.1/docs/images/algo/pruning_4.png" height=200 width=400 hspace='10'/> <br />
<strong>图8</strong> <strong>图8</strong>
</p> </p>
...@@ -206,12 +206,11 @@ $$ Vt = (1 - k) * V + k * V_{t-1} $$ ...@@ -206,12 +206,11 @@ $$ Vt = (1 - k) * V + k * V_{t-1} $$
一般情况下,模型参数量越多,结构越复杂,其性能越好,但参数也越允余,运算量和资源消耗也越大;模型蒸馏是将复杂网络中的有用信息将复杂网络中的有用信息提取出来提取出来,迁移到一个更小的网络中去,在我们的工具包中,支持两种蒸馏的方法。 一般情况下,模型参数量越多,结构越复杂,其性能越好,但参数也越允余,运算量和资源消耗也越大;模型蒸馏是将复杂网络中的有用信息将复杂网络中的有用信息提取出来提取出来,迁移到一个更小的网络中去,在我们的工具包中,支持两种蒸馏的方法。
第一种是传统的蒸馏方法(参考论文:[Distilling the Knowledge in a Neural Network](https://arxiv.org/pdf/1503.02531.pdf)) 第一种是传统的蒸馏方法(参考论文:[Distilling the Knowledge in a Neural Network](https://arxiv.org/pdf/1503.02531.pdf))
使用复杂的网络作为teacher模型去监督训练一个参数量和运算量更少的student模型。teacher模型可以是一个或者多个提前训练好的高性能模型。student模型的训练有两个目标:一个是原始的目标函数,为student模型输出的类别概率和label的交叉熵,记为hard-target;另一个是student模型输出的类别概率和teacher模型输出的类别概率的交叉熵,记为soft target,这两个loss加权后得到最终的训练loss,共同监督studuent模型的训练。 使用复杂的网络作为teacher模型去监督训练一个参数量和运算量更少的student模型。teacher模型可以是一个或者多个提前训练好的高性能模型。student模型的训练有两个目标:一个是原始的目标函数,为student模型输出的类别概率和label的交叉熵,记为hard-target;另一个是student模型输出的类别概率和teacher模型输出的类别概率的交叉熵,记为soft target,这两个loss加权后得到最终的训练loss,共同监督studuent模型的训练。
第二种是基于FSP的蒸馏方法(参考论文:[A Gift from Knowledge Distillation: 第二种是基于FSP的蒸馏方法(参考论文:[A Gift from Knowledge Distillation: Fast Optimization, Network Minimization and Transfer Learning](http://openaccess.thecvf.com/content_cvpr_2017/papers/Yim_A_Gift_From_CVPR_2017_paper.pdf))
Fast Optimization, Network Minimization and Transfer Learning](http://openaccess.thecvf.com/content_cvpr_2017/papers/Yim_A_Gift_From_CVPR_2017_paper.pdf))
相比传统的蒸馏方法直接用小模型去拟合大模型的输出,该方法用小模型去拟合大模型不同层特征之间的转换关系,其用一个FSP矩阵(特征的内积)来表示不同层特征之间的关系,大模型和小模型不同层之间分别获得多个FSP矩阵,然后使用L2 loss让小模型的对应层FSP矩阵和大模型对应层的FSP矩阵尽量一致,具体如下图所示。这种方法的优势,通俗的解释是,比如将蒸馏类比成teacher(大模型)教student(小模型)解决一个问题,传统的蒸馏是直接告诉小模型问题的答案,让小模型学习,而学习FSP矩阵是让小模型学习解决问题的中间过程和方法,因此其学到的信息更多。 相比传统的蒸馏方法直接用小模型去拟合大模型的输出,该方法用小模型去拟合大模型不同层特征之间的转换关系,其用一个FSP矩阵(特征的内积)来表示不同层特征之间的关系,大模型和小模型不同层之间分别获得多个FSP矩阵,然后使用L2 loss让小模型的对应层FSP矩阵和大模型对应层的FSP矩阵尽量一致,具体如下图所示。这种方法的优势,通俗的解释是,比如将蒸馏类比成teacher(大模型)教student(小模型)解决一个问题,传统的蒸馏是直接告诉小模型问题的答案,让小模型学习,而学习FSP矩阵是让小模型学习解决问题的中间过程和方法,因此其学到的信息更多。
<p align="center"> <p align="center">
<img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/develop/docs/docs/images/algo/distillation_0.png" height=300 width=600 hspace='10'/> <br /> <img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/release/1.0.1/docs/images/algo/distillation_0.png" height=300 width=600 hspace='10'/> <br />
<strong>图9</strong> <strong>图9</strong>
</p> </p>
...@@ -258,7 +257,7 @@ e^{\frac{(r_k-r)}{T_k}} & r_k < r\\ ...@@ -258,7 +257,7 @@ e^{\frac{(r_k-r)}{T_k}} & r_k < r\\
因为要搜索出在移动端运行速度快的模型,我们参考了MobileNetV2中的Linear Bottlenecks和Inverted residuals结构,搜索每一个Inverted residuals中的具体参数,包括kernelsize、channel扩张倍数、重复次数、channels number。如图10所示: 因为要搜索出在移动端运行速度快的模型,我们参考了MobileNetV2中的Linear Bottlenecks和Inverted residuals结构,搜索每一个Inverted residuals中的具体参数,包括kernelsize、channel扩张倍数、重复次数、channels number。如图10所示:
<p align="center"> <p align="center">
<img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/develop/docs/docs/images/algo/light-nas-block.png" height=300 width=600 hspace='10'/> <br /> <img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/release/1.0.1/docs/images/algo/light-nas-block.png" height=300 width=600 hspace='10'/> <br />
<strong>图10</strong> <strong>图10</strong>
</p> </p>
......
...@@ -16,5 +16,5 @@ API文档 ...@@ -16,5 +16,5 @@ API文档
prune_api.rst prune_api.rst
quantization_api.rst quantization_api.rst
single_distiller_api.rst single_distiller_api.rst
search_space.rst search_space.md
table_latency.md table_latency.md
...@@ -5,7 +5,7 @@ SA-NAS ...@@ -5,7 +5,7 @@ SA-NAS
---------------------- ----------------------
通过参数配置搜索空间。更多搜索空间的使用可以参考: [search_space](../search_space.md) 通过参数配置搜索空间。更多搜索空间的使用可以参考: `search_space <https://paddlepaddle.github.io/PaddleSlim/api_cn/search_space.html>`_
**参数:** **参数:**
...@@ -119,7 +119,7 @@ SANAS(Simulated Annealing Neural Architecture Search)是基于模拟退火 ...@@ -119,7 +119,7 @@ SANAS(Simulated Annealing Neural Architecture Search)是基于模拟退火
sanas.reward(float(score)) sanas.reward(float(score))
.. py:methd:: tokens2arch(tokens) .. py:method:: tokens2arch(tokens)
通过一组tokens得到实际的模型结构,一般用来把搜索到最优的token转换为模型结构用来做最后的训练。tokens的形式是一个列表,tokens映射到搜索空间转换成相应的网络结构,一组tokens对应唯一的一个网络结构。 通过一组tokens得到实际的模型结构,一般用来把搜索到最优的token转换为模型结构用来做最后的训练。tokens的形式是一个列表,tokens映射到搜索空间转换成相应的网络结构,一组tokens对应唯一的一个网络结构。
......
...@@ -51,15 +51,15 @@ ...@@ -51,15 +51,15 @@
- **weight_quantize_type(str)** - 参数量化方式。可选 ``'abs_max'`` , ``'channel_wise_abs_max'`` , ``'range_abs_max'`` , ``'moving_average_abs_max'`` 。如果使用 ``TensorRT`` 加载量化后的模型来预测,请使用 ``'channel_wise_abs_max'`` 。 默认 ``'channel_wise_abs_max'`` 。 - **weight_quantize_type(str)** - 参数量化方式。可选 ``'abs_max'`` , ``'channel_wise_abs_max'`` , ``'range_abs_max'`` , ``'moving_average_abs_max'`` 。如果使用 ``TensorRT`` 加载量化后的模型来预测,请使用 ``'channel_wise_abs_max'`` 。 默认 ``'channel_wise_abs_max'`` 。
- **activation_quantize_type(str)** - 激活量化方式,可选 ``'abs_max'`` , ``'range_abs_max'`` , ``'moving_average_abs_max'`` 。如果使用 ``TensorRT`` 加载量化后的模型来预测,请使用 ``'range_abs_max', 'moving_average_abs_max'`` 。,默认 ``'moving_average_abs_max'`` 。 - **activation_quantize_type(str)** - 激活量化方式,可选 ``'abs_max'`` , ``'range_abs_max'`` , ``'moving_average_abs_max'`` 。如果使用 ``TensorRT`` 加载量化后的模型来预测,请使用 ``'range_abs_max', 'moving_average_abs_max'`` 。,默认 ``'moving_average_abs_max'`` 。
- **weight_bits(int)** - 参数量化bit数,默认8, 推荐设为8 - **weight_bits(int)** - 参数量化bit数,默认8, 可选1-8,推荐设为8,因为量化后的数据类型是 ``int8``
- **activation_bits(int)** - 激活量化bit数,默认8, 推荐设为8 - **activation_bits(int)** - 激活量化bit数,默认8,可选1-8,推荐设为8,因为量化后的数据类型是 ``int8``
- **not_quant_pattern(str | list[str])** - 所有 ``name_scope`` 包含 ``'not_quant_pattern'`` 字符串的 ``op`` ,都不量化, 设置方式请参考 `fluid.name_scope <https://www.paddlepaddle.org.cn/documentation/docs/zh/api_cn/fluid_cn/name_scope_cn.html#name-scope>`_ 。 - **not_quant_pattern(str | list[str])** - 所有 ``name_scope`` 包含 ``'not_quant_pattern'`` 字符串的 op ,都不量化, 设置方式请参考 `fluid.name_scope <https://www.paddlepaddle.org.cn/documentation/docs/zh/api_cn/fluid_cn/name_scope_cn.html#name-scope>`_ 。
- **quantize_op_types(list[str])** - 需要进行量化的 ``op`` 类型,目前支持 ``'conv2d', 'depthwise_conv2d', 'mul'`` 。 - **quantize_op_types(list[str])** - 需要进行量化的 op 类型,目前支持 ``'conv2d', 'depthwise_conv2d', 'mul'`` 。
- **dtype(int8)** - 量化后的参数类型,默认 ``int8`` , 目前仅支持 ``int8`` 。 - **dtype(int8)** - 量化后的参数类型,默认 ``int8`` , 目前仅支持 ``int8`` 。
- **window_size(int)** - ``'range_abs_max'`` 量化方式的 ``window size`` ,默认10000。 - **window_size(int)** - ``'range_abs_max'`` 量化方式的 ``window size`` ,默认10000。
- **moving_rate(int)** - ``'moving_average_abs_max'`` 量化方式的衰减系数,默认 0.9。 - **moving_rate(int)** - ``'moving_average_abs_max'`` 量化方式的衰减系数,默认 0.9。
- **for_tensorrt(bool)** - 量化后的模型是否使用 ``TensorRT`` 进行预测。如果是的话,量化op类型为: ``TENSORRT_OP_TYPES`` 。默认值为False. - **for_tensorrt(bool)** - 量化后的模型是否使用 ``TensorRT`` 进行预测。如果是的话,量化op类型为: ``TENSORRT_OP_TYPES`` 。默认值为False.
- **is_full_quantize(bool)** - 是否量化所有可支持op类型。默认值为False. - **is_full_quantize(bool)** - 是否量化所有可支持op类型。可量化op为 ``TRANSFORM_PASS_OP_TYPES + QUANT_DEQUANT_PASS_OP_TYPES`` 。 默认值为False.
.. :note:: .. :note::
...@@ -69,22 +69,24 @@ ...@@ -69,22 +69,24 @@
quant_aware quant_aware
------------ ------------
.. py:function:: paddleslim.quant.quant_aware(program, place, config, scope=None, for_test=False)[[源代码]](https://github.com/PaddlePaddle/PaddleSlim/blob/develop/paddleslim/quant/quanter.py) .. py:function:: paddleslim.quant.quant_aware(program, place, config, scope=None, for_test=False)
在 ``program`` 中加入量化和反量化 ``op``, 用于量化训练。 `源代码 <https://github.com/PaddlePaddle/PaddleSlim/blob/develop/paddleslim/quant/quanter.py>`_
在 program 中加入量化和反量化op, 用于量化训练。
**参数:** **参数:**
- **program (fluid.Program)** - 传入训练或测试 ``program`` - **program (fluid.Program)** - 传入训练或测试program
- **place(fluid.CPUPlace | fluid.CUDAPlace)** - 该参数表示 ``Executor`` 执行所在的设备。 - **place(fluid.CPUPlace | fluid.CUDAPlace)** - 该参数表示 ``Executor`` 执行所在的设备。
- **config(dict)** - 量化配置表。 - **config(dict)** - 量化配置表。
- **scope(fluid.Scope, optional)** - 传入用于存储 ``Variable`` 的 ``scope`` ,需要传入 ``program`` 所使用的 ``scope`` ,一般情况下,是 `fluid.global_scope() <https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/api_cn/executor_cn/global_scope_cn.html>`_ 。设置为 ``None`` 时将使用 `fluid.global_scope() <https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/api_cn/executor_cn/global_scope_cn.html>`_ ,默认值为 ``None`` 。 - **scope(fluid.Scope, optional)** - 传入用于存储 ``Variable`` 的 ``scope`` ,需要传入 ``program`` 所使用的 ``scope`` ,一般情况下,是 `fluid.global_scope() <https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/api_cn/executor_cn/global_scope_cn.html>`_ 。设置为 ``None`` 时将使用 `fluid.global_scope() <https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/api_cn/executor_cn/global_scope_cn.html>`_ ,默认值为 ``None`` 。
- **for_test(bool)** - 如果 ``program`` 参数是一个测试 ``program`` , ``for_test`` 应设为 ``True`` ,否则设为 ``False`` - **for_test(bool)** - 如果 ``program`` 参数是一个测试 ``program`` , ``for_test`` 应设为True,否则设为False
**返回** **返回**
含有量化和反量化 ``operator`` 的 ``program`` 含有量化和反量化 operator 的 program
**返回类型** **返回类型**
...@@ -93,10 +95,10 @@ quant_aware ...@@ -93,10 +95,10 @@ quant_aware
.. note:: .. note::
- 此接口会改变 ``program`` 结构,并且可能增加一些``persistable``的变量,所以加载模型参数时请注意和相应的``program``对应。 - 此接口会改变program 结构,并且可能增加一些persistable的变量,所以加载模型参数时请注意和相应的 program 对应。
- 此接口底层经历了``fluid.Program``-> ``fluid.framework.IrGraph``->``fluid.Program``的转变,在``fluid.framework.IrGraph``中没有``Parameter``的概念,``Variable``只有``persistable``和``not persistable``的区别,所以在保存和加载参数时,请使用``fluid.io.save_persistables``和``fluid.io.load_persistables``接口。 - 此接口底层经历了 fluid.Program -> fluid.framework.IrGraph -> fluid.Program 的转变,在 ``fluid.framework.IrGraph`` 中没有 ``Parameter`` 的概念,``Variable`` 只有 persistable 和not persistable的区别,所以在保存和加载参数时,请使用 ``fluid.io.save_persistables`` 和 ``fluid.io.load_persistables`` 接口。
- 由于此接口会根据``program``的结构和量化配置来对``program``添加op,所以``Paddle``中一些通过``fuse op``来加速训练的策略不能使用。已知以下策略在使用量化时必须设为``False``: ``fuse_all_reduce_ops, sync_batch_norm`` - 由于此接口会根据 program 的结构和量化配置来对program 添加op,所以 ``Paddle`` 中一些通过 ``fuse op`` 来加速训练的策略不能使用。已知以下策略在使用量化时必须设为False : ``fuse_all_reduce_ops, sync_batch_norm``
- 如果传入的 ``program`` 中存在和任何op都没有连接的 ``Variable`` ,则会在量化的过程中被优化掉。 - 如果传入的 program 中存在和任何op都没有连接的 ``Variable`` ,则会在量化的过程中被优化掉。
...@@ -108,24 +110,24 @@ convert ...@@ -108,24 +110,24 @@ convert
`源代码 <https://github.com/PaddlePaddle/PaddleSlim/blob/develop/paddleslim/quant/quanter.py>`_ `源代码 <https://github.com/PaddlePaddle/PaddleSlim/blob/develop/paddleslim/quant/quanter.py>`_
把训练好的量化 ``program`` ,转换为可用于保存 ``inference model`` 的 ``program`` 把训练好的量化 program ,转换为可用于保存 ``inference model`` 的 program
**参数:** **参数:**
- **program (fluid.Program)** - 传入测试``program`` - **program (fluid.Program)** - 传入测试 program
- **place(fluid.CPUPlace | fluid.CUDAPlace)** - 该参数表示``Executor``执行所在的设备。 - **place(fluid.CPUPlace | fluid.CUDAPlace)** - 该参数表示 ``Executor`` 执行所在的设备。
- **config(dict)** - 量化配置表。 - **config(dict)** - 量化配置表。
- **scope(fluid.Scope)** - 传入用于存储``Variable``的``scope``,需要传入``program``所使用的``scope``,一般情况下,是 `fluid.global_scope() <https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/api_cn/executor_cn/global_scope_cn.html>`_ 。设置为 ``None`` 时将使用 `fluid.global_scope() <https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/api_cn/executor_cn/global_scope_cn.html>`_ ,默认值为 ``None`` 。 - **scope(fluid.Scope)** - 传入用于存储 ``Variable`` 的 ``scope`` ,需要传入 ``program`` 所使用的 ``scope`` ,一般情况下,是 `fluid.global_scope() <https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/api_cn/executor_cn/global_scope_cn.html>`_ 。设置为 ``None`` 时将使用 `fluid.global_scope() <https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/api_cn/executor_cn/global_scope_cn.html>`_ ,默认值为 ``None`` 。
- **save_int8(bool)** - 是否需要返回参数为 ``int8`` 的 ``program`` 。该功能目前只能用于确认模型大小。默认值为 ``False`` 。 - **save_int8(bool)** - 是否需要返回参数为 ``int8`` 的 program 。该功能目前只能用于确认模型大小。默认值为 ``False`` 。
**返回** **返回**
- **program (fluid.Program)** - freezed program,可用于保存inference model,参数为``float32``类型,但其数值范围可用int8表示。 - **program (fluid.Program)** - freezed program,可用于保存inference model,参数为 ``float32`` 类型,但其数值范围可用int8表示。
- **int8_program (fluid.Program)** - freezed program,可用于保存inference model,参数为``int8``类型。当``save_int8``为``False``时,不返回该值。 - **int8_program (fluid.Program)** - freezed program,可用于保存inference model,参数为 ``int8`` 类型。当 ``save_int8`` 为False 时,不返回该值。
.. note:: .. note::
因为该接口会对``op``和``Variable``做相应的删除和修改,所以此接口只能在训练完成之后调用。如果想转化训练的中间模型,可加载相应的参数之后再使用此接口。 因为该接口会对 op 和 Variable 做相应的删除和修改,所以此接口只能在训练完成之后调用。如果想转化训练的中间模型,可加载相应的参数之后再使用此接口。
**代码示例** **代码示例**
...@@ -186,18 +188,19 @@ quant_post ...@@ -186,18 +188,19 @@ quant_post
- **model_dir(str)** - 需要量化的模型所在的文件夹。 - **model_dir(str)** - 需要量化的模型所在的文件夹。
- **quantize_model_path(str)** - 保存量化后的模型的路径 - **quantize_model_path(str)** - 保存量化后的模型的路径
- **sample_generator(python generator)** - 读取数据样本,每次返回一个样本。 - **sample_generator(python generator)** - 读取数据样本,每次返回一个样本。
- **model_filename(str, optional)** - 模型文件名,如果需要量化的模型的参数存在一个文件中,则需要设置``model_filename``为模型文件的名称,否则设置为``None``即可。默认值是``None`` - **model_filename(str, optional)** - 模型文件名,如果需要量化的模型的参数存在一个文件中,则需要设置 ``model_filename`` 为模型文件的名称,否则设置为 ``None`` 即可。默认值是 ``None``
- **params_filename(str)** - 参数文件名,如果需要量化的模型的参数存在一个文件中,则需要设置``params_filename``为参数文件的名称,否则设置为``None``即可。默认值是``None`` - **params_filename(str)** - 参数文件名,如果需要量化的模型的参数存在一个文件中,则需要设置 ``params_filename`` 为参数文件的名称,否则设置为 ``None`` 即可。默认值是 ``None``
- **batch_size(int)** - 每个batch的图片数量。默认值为16 。 - **batch_size(int)** - 每个batch的图片数量。默认值为16 。
- **batch_nums(int, optional)** - 迭代次数。如果设置为``None``,则会一直运行到``sample_generator`` 迭代结束, 否则,迭代次数为``batch_nums``, 也就是说参与对 ``Scale`` 进行校正的样本个数为 ``'batch_nums' * 'batch_size'`` . - **batch_nums(int, optional)** - 迭代次数。如果设置为 ``None`` ,则会一直运行到 ``sample_generator`` 迭代结束, 否则,迭代次数为 ``batch_nums``, 也就是说参与对 ``Scale`` 进行校正的样本个数为 ``'batch_nums' * 'batch_size'`` .
- **scope(fluid.Scope, optional)** - 用来获取和写入 ``Variable`` , 如果设置为 ``None`` ,则使用 `fluid.global_scope() <https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/api_cn/executor_cn/global_scope_cn.html>`_ . 默认值是``None``. - **scope(fluid.Scope, optional)** - 用来获取和写入 ``Variable`` , 如果设置为 ``None`` ,则使用 `fluid.global_scope() <https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/api_cn/executor_cn/global_scope_cn.html>`_ . 默认值是 ``None`` .
- **algo(str)** - 量化时使用的算法名称,可为 ``'KL'`` 或者 ``'direct'`` 。该参数仅针对激活值的量化,因为参数值的量化使用的方式为 ``'channel_wise_abs_max'`` . 当 ``algo`` 设置为 ``'direct'`` 时,使用校正数据的激活值的绝对值的最大值当作 ``Scale`` 值,当设置为 ``'KL'`` 时,则使用KL散度的方法来计算 ``Scale`` 值。默认值为 ``'KL'`` 。 - **algo(str)** - 量化时使用的算法名称,可为 ``'KL'`` 或者 ``'direct'`` 。该参数仅针对激活值的量化,因为参数值的量化使用的方式为 ``'channel_wise_abs_max'`` . 当 ``algo`` 设置为 ``'direct'`` 时,使用校正数据的激活值的绝对值的最大值当作 ``Scale`` 值,当设置为 ``'KL'`` 时,则使用KL散度的方法来计算 ``Scale`` 值。默认值为 ``'KL'`` 。
- **quantizable_op_type(list[str])** - 需要量化的 ``op`` 类型列表。默认值为 ``["conv2d", "depthwise_conv2d", "mul"]`` 。 - **quantizable_op_type(list[str])** - 需要量化的 op 类型列表。默认值为 ``["conv2d", "depthwise_conv2d", "mul"]`` 。
- **is_full_quantize(bool)** - 是否量化所有可支持的op类型。如果设置为False, 则按照 ``'quantizable_op_type'`` 的设置进行量化。 - **is_full_quantize(bool)** - 是否量化所有可支持的op类型。如果设置为False, 则按照 ``'quantizable_op_type'`` 的设置进行量化。如果设置为True, 则按照 `量化配置 <#id2>`_ 中 ``QUANT_DEQUANT_PASS_OP_TYPES + QUANT_DEQUANT_PASS_OP_TYPES`` 定义的op进行量化。
- **weight_bits(int)** - weight的量化比特位数。 - **weight_bits(int)** - weight的量化比特位数, 默认值为8。
- **activation_bits(int)** - 激活值的量化比特位数。 - **activation_bits(int)** - 激活值的量化比特位数, 默认值为8。
- **is_use_cache_file(bool)** - 是否使用硬盘对中间结果进行存储。如果为False, 则将中间结果存储在内存中。 - **is_use_cache_file(bool)** - 是否使用硬盘对中间结果进行存储。如果为False, 则将中间结果存储在内存中。默认值为False。
- **cache_dir(str)** - 如果 ``'is_use_cache_file'`` 为True, 则将中间结果存储在此参数设置的路径下。 - **cache_dir(str)** - 如果 ``'is_use_cache_file'`` 为True, 则将中间结果存储在此参数设置的路径下。默认值为 ``./temp_post_training`` 。
**返回** **返回**
...@@ -205,14 +208,14 @@ quant_post ...@@ -205,14 +208,14 @@ quant_post
.. note:: .. note::
- 因为该接口会收集校正数据的所有的激活值,当校正图片比较多时,请设置``'is_use_cache_file'``为True, 将中间结果存储在硬盘中。另外,``'KL'``散度的计算比较耗时。 - 因为该接口会收集校正数据的所有的激活值,当校正图片比较多时,请设置 ``'is_use_cache_file'`` 为True, 将中间结果存储在硬盘中。另外,``'KL'`` 散度的计算比较耗时。
- 目前``Paddle-Lite``有int8 kernel来加速的op只有 ``['conv2d', 'depthwise_conv2d', 'mul']``, 其他op的int8 kernel将陆续支持。 - 目前 ``Paddle-Lite`` 有int8 kernel来加速的op只有 ``['conv2d', 'depthwise_conv2d', 'mul']`` , 其他op的int8 kernel将陆续支持。
**代码示例** **代码示例**
.. warning:: .. warning::
此示例不能直接运行,因为需要加载``${model_dir}``下的模型,所以不能直接运行。 此示例不能直接运行,因为需要加载 ``${model_dir}`` 下的模型,所以不能直接运行。
.. code-block:: python .. code-block:: python
...@@ -249,12 +252,12 @@ quant_embedding ...@@ -249,12 +252,12 @@ quant_embedding
**参数:** **参数:**
- **program(fluid.Program)** - 需要量化的program - **program(fluid.Program)** - 需要量化的program
- **scope(fluid.Scope, optional)** - 用来获取和写入``Variable``, 如果设置为``None``,则使用 `fluid.global_scope() <https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/api_cn/executor_cn/global_scope_cn.html>`_ . - **scope(fluid.Scope, optional)** - 用来获取和写入 ``Variable``, 如果设置为 ``None``,则使用 `fluid.global_scope() <https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/api_cn/executor_cn/global_scope_cn.html>`_ .
- **place(fluid.CPUPlace | fluid.CUDAPlace)** - 运行program的设备 - **place(fluid.CPUPlace | fluid.CUDAPlace)** - 运行program的设备
- **config(dict)** - 定义量化的配置。可以配置的参数有: - **config(dict)** - 定义量化的配置。可以配置的参数有:
- ``'params_name'`` (str, required): 需要进行量化的参数名称,此参数必须设置。 - ``'params_name'`` (str, required): 需要进行量化的参数名称,此参数必须设置。
- ``'quantize_type'`` (str, optional): 量化的类型,目前支持的类型是 ``'abs_max'``, 待支持的类型有 ``'log', 'product_quantization'`` 。 默认值是``'abs_max'`` . - ``'quantize_type'`` (str, optional): 量化的类型,目前支持的类型是 ``'abs_max'``, 待支持的类型有 ``'log', 'product_quantization'`` 。 默认值是 ``'abs_max'`` .
- ``'quantize_bits'`` (int, optional): 量化的 ``bit`` 数,目前支持的 ``bit`` 数为8。默认值是8. - ``'quantize_bits'`` (int, optional): 量化的bit数,目前支持的bit数为8。默认值是8.
- ``'dtype'`` (str, optional): 量化之后的数据类型, 目前支持的是 ``'int8'``. 默认值是 ``int8`` 。 - ``'dtype'`` (str, optional): 量化之后的数据类型, 目前支持的是 ``'int8'``. 默认值是 ``int8`` 。
- ``'threshold'`` (float, optional): 量化之前将根据此阈值对需要量化的参数值进行 ``clip``. 如果不设置,则跳过 ``clip`` 过程直接量化。 - ``'threshold'`` (float, optional): 量化之前将根据此阈值对需要量化的参数值进行 ``clip``. 如果不设置,则跳过 ``clip`` 过程直接量化。
...@@ -293,4 +296,4 @@ fluid.Program ...@@ -293,4 +296,4 @@ fluid.Program
config = {'params_name': 'emb', 'quantize_type': 'abs_max'} config = {'params_name': 'emb', 'quantize_type': 'abs_max'}
quant_program = quant.quant_embedding(infer_program, place, config) quant_program = quant.quant_embedding(infer_program, place, config)
更详细的用法请参考 `Embedding量化demo <https://github.com/PaddlePaddle/PaddleSlim/tree/develop/demo/quant/quant_embedding'>`_ 更详细的用法请参考 `Embedding量化demo <https://github.com/PaddlePaddle/PaddleSlim/tree/develop/demo/quant/quant_embedding>`_
...@@ -16,5 +16,5 @@ API Documents ...@@ -16,5 +16,5 @@ API Documents
paddleslim.nas.rst paddleslim.nas.rst
paddleslim.nas.one_shot.rst paddleslim.nas.one_shot.rst
paddleslim.pantheon.rst paddleslim.pantheon.rst
search_space_en.rst search_space_en.md
table_latency_en.md table_latency_en.md
# 图像分类模型量化训练-快速开始 # 图像分类模型量化训练-快速开始
该教程以图像分类模型MobileNetV1为例,说明如何快速使用PaddleSlim的[量化训练接口](https://github.com/PaddlePaddle/PaddleSlim/blob/develop/docs/docs/api/quantization_api.md)。 该示例包含以下步骤: 该教程以图像分类模型MobileNetV1为例,说明如何快速使用PaddleSlim的[量化训练接口](https://paddlepaddle.github.io/PaddleSlim/api_cn/quantization_api.html)。 该示例包含以下步骤:
1. 导入依赖 1. 导入依赖
2. 构建模型 2. 构建模型
...@@ -61,7 +61,7 @@ def train(prog): ...@@ -61,7 +61,7 @@ def train(prog):
if iter % 100 == 0: if iter % 100 == 0:
print('train iter={}, top1={}, top5={}, loss={}'.format(iter, acc1.mean(), acc5.mean(), loss.mean())) print('train iter={}, top1={}, top5={}, loss={}'.format(iter, acc1.mean(), acc5.mean(), loss.mean()))
iter += 1 iter += 1
def test(prog): def test(prog):
iter = 0 iter = 0
res = [[], []] res = [[], []]
...@@ -93,7 +93,7 @@ test(val_program) ...@@ -93,7 +93,7 @@ test(val_program)
## 4. 量化 ## 4. 量化
按照[默认配置](https://paddlepaddle.github.io/PaddleSlim/api/quantization_api/#_1)在``train_program``和``val_program``中加入量化和反量化op. 按照[默认配置](https://paddlepaddle.github.io/PaddleSlim/api_cn/quantization_api.html#id2)在``train_program``和``val_program``中加入量化和反量化op.
```python ```python
...@@ -121,7 +121,7 @@ test(val_quant_program) ...@@ -121,7 +121,7 @@ test(val_quant_program)
## 6. 保存量化后的模型 ## 6. 保存量化后的模型
在``4. 量化``中使用接口``slim.quant.quant_aware``接口得到的模型只适合训练时使用,为了得到最终使用时的模型,需要使用[slim.quant.convert](https://paddlepaddle.github.io/PaddleSlim/api/quantization_api/#convert)接口,然后使用[fluid.io.save_inference_model](https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/api_cn/io_cn/save_inference_model_cn.html#save-inference-model)保存模型。``float_prog``的参数数据类型是float32,但是数据范围是int8, 保存之后可使用fluid或者paddle-lite加载使用,paddle-lite在使用时,会先将类型转换为int8。``int8_prog``的参数数据类型是int8, 保存后可看到量化后模型大小,不可加载使用。 在``4. 量化``中使用接口``slim.quant.quant_aware``接口得到的模型只适合训练时使用,为了得到最终使用时的模型,需要使用[slim.quant.convert](https://paddlepaddle.github.io/PaddleSlim/api_cn/quantization_api.html#convert)接口,然后使用[fluid.io.save_inference_model](https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/api_cn/io_cn/save_inference_model_cn.html#save-inference-model)保存模型。``float_prog``的参数数据类型是float32,但是数据范围是int8, 保存之后可使用fluid或者paddle-lite加载使用,paddle-lite在使用时,会先将类型转换为int8。``int8_prog``的参数数据类型是int8, 保存后可看到量化后模型大小,不可加载使用。
```python ```python
......
# Training-aware Quantization of image classification model - quick start # Training-aware Quantization of image classification model - quick start
This tutorial shows how to do training-aware quantization using [API](https://github.com/PaddlePaddle/PaddleSlim/blob/develop/docs/docs/api/quantization_api.md) in PaddleSlim. We use MobileNetV1 to train image classification model as example. The tutorial contains follow sections: This tutorial shows how to do training-aware quantization using [API](https://paddlepaddle.github.io/PaddleSlim/api_en/paddleslim.quant.html#paddleslim.quant.quanter.quant_aware) in PaddleSlim. We use MobileNetV1 to train image classification model as example. The tutorial contains follow sections:
1. Necessary imports 1. Necessary imports
2. Model architecture 2. Model architecture
...@@ -89,7 +89,7 @@ test(val_program) ...@@ -89,7 +89,7 @@ test(val_program)
## 4. Quantization ## 4. Quantization
We call ``quant_aware`` API to add quantization and dequantization operators in ``train_program`` and ``val_program`` according to [default configuration](https://paddlepaddle.github.io/PaddleSlim/api/quantization_api/#_1). We call ``quant_aware`` API to add quantization and dequantization operators in ``train_program`` and ``val_program`` according to [default configuration](https://paddlepaddle.github.io/PaddleSlim/api_cn/quantization_api.html#id2).
```python ```python
quant_program = slim.quant.quant_aware(train_program, exe.place, for_test=False) quant_program = slim.quant.quant_aware(train_program, exe.place, for_test=False)
...@@ -114,7 +114,7 @@ test(val_quant_program) ...@@ -114,7 +114,7 @@ test(val_quant_program)
## 6. Save model after quantization ## 6. Save model after quantization
The model in ``4. Quantization`` after calling ``slim.quant.quant_aware`` API is only suitable to train. To get the inference model, we should use [slim.quant.convert](https://paddlepaddle.github.io/PaddleSlim/api/quantization_api/#convert) API to change model architecture and use [fluid.io.save_inference_model](https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/api_cn/io_cn/save_inference_model_cn.html#save-inference-model) to save model. ``float_prog``'s parameters are float32 dtype but in int8's range which can be used in ``fluid`` or ``paddle-lite``. ``paddle-lite`` will change the parameters' dtype from float32 to int8 first when loading the inference model. ``int8_prog``'s parameters are int8 dtype and we can get model size after quantization by saving it. ``int8_prog`` cannot be used in ``fluid`` or ``paddle-lite``. The model in ``4. Quantization`` after calling ``slim.quant.quant_aware`` API is only suitable to train. To get the inference model, we should use [slim.quant.convert](https://paddlepaddle.github.io/PaddleSlim/api_en/paddleslim.quant.html#paddleslim.quant.quanter.convert) API to change model architecture and use [fluid.io.save_inference_model](https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/api_cn/io_cn/save_inference_model_cn.html#save-inference-model) to save model. ``float_prog``'s parameters are float32 dtype but in int8's range which can be used in ``fluid`` or ``paddle-lite``. ``paddle-lite`` will change the parameters' dtype from float32 to int8 first when loading the inference model. ``int8_prog``'s parameters are int8 dtype and we can get model size after quantization by saving it. ``int8_prog`` cannot be used in ``fluid`` or ``paddle-lite``.
```python ```python
......
# 图像分类模型离线量化-快速开始 # 图像分类模型离线量化-快速开始
该教程以图像分类模型MobileNetV1为例,说明如何快速使用PaddleSlim的[离线量化接口](https://github.com/PaddlePaddle/PaddleSlim/blob/develop/docs/docs/api/quantization_api.md)。 该示例包含以下步骤: 该教程以图像分类模型MobileNetV1为例,说明如何快速使用PaddleSlim的[离线量化接口](https://paddlepaddle.github.io/PaddleSlim/api_cn/quantization_api.html#quant-post)。 该示例包含以下步骤:
1. 导入依赖 1. 导入依赖
2. 构建模型 2. 构建模型
...@@ -19,7 +19,7 @@ import numpy as np ...@@ -19,7 +19,7 @@ import numpy as np
``` ```
## 2. 构建网络 ## 2. 构建网络
该章节构造一个用于对MNIST数据进行分类的分类模型,选用`MobileNetV1`,并将输入大小设置为`[1, 28, 28]`,输出类别数为10。 为了方便展示示例,我们在`paddleslim.models`下预定义了用于构建分类模型的方法,执行以下代码构建分类模型: 该章节构造一个用于对MNIST数据进行分类的分类模型,选用`MobileNetV1`,并将输入大小设置为`[1, 28, 28]`,输出类别数为10。为了方便展示示例,我们在`paddleslim.models`下预定义了用于构建分类模型的方法,执行以下代码构建分类模型:
>注意:paddleslim.models下的API并非PaddleSlim常规API,是为了简化示例而封装预定义的一系列方法,比如:模型结构的定义、Program的构建等。 >注意:paddleslim.models下的API并非PaddleSlim常规API,是为了简化示例而封装预定义的一系列方法,比如:模型结构的定义、Program的构建等。
...@@ -60,7 +60,7 @@ def train(prog): ...@@ -60,7 +60,7 @@ def train(prog):
if iter % 100 == 0: if iter % 100 == 0:
print('train', acc1.mean(), acc5.mean(), loss.mean()) print('train', acc1.mean(), acc5.mean(), loss.mean())
iter += 1 iter += 1
def test(prog, outputs=outputs): def test(prog, outputs=outputs):
iter = 0 iter = 0
res = [[], []] res = [[], []]
......
# Post-training Quantization of image classification model - quick start # Post-training Quantization of image classification model - quick start
This tutorial shows how to do post training quantization using [API](https://github.com/PaddlePaddle/PaddleSlim/blob/develop/docs/docs/api/quantization_api.md) in PaddleSlim. We use MobileNetV1 to train image classification model as example. The tutorial contains follow sections: This tutorial shows how to do post training quantization using [API](https://paddlepaddle.github.io/PaddleSlim/api_en/paddleslim.quant.html#paddleslim.quant.quanter.quant_post) in PaddleSlim. We use MobileNetV1 to train image classification model as example. The tutorial contains follow sections:
1. Necessary imports 1. Necessary imports
2. Model architecture 2. Model architecture
......
...@@ -113,16 +113,16 @@ ...@@ -113,16 +113,16 @@
</ul> </ul>
</li> </li>
<li class="toctree-l2"><a class="reference internal" href="#id22">3. 蒸馏</a></li> <li class="toctree-l2"><a class="reference internal" href="#id22">3. 蒸馏</a></li>
<li class="toctree-l2"><a class="reference internal" href="#id25">4. 轻量级模型结构搜索</a><ul> <li class="toctree-l2"><a class="reference internal" href="#id23">4. 轻量级模型结构搜索</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#id26">4.1 搜索策略</a><ul> <li class="toctree-l3"><a class="reference internal" href="#id24">4.1 搜索策略</a><ul>
<li class="toctree-l4"><a class="reference internal" href="#id27">4.1.1 模拟退火</a></li> <li class="toctree-l4"><a class="reference internal" href="#id25">4.1.1 模拟退火</a></li>
</ul> </ul>
</li> </li>
<li class="toctree-l3"><a class="reference internal" href="#id28">4.2 搜索空间</a></li> <li class="toctree-l3"><a class="reference internal" href="#id26">4.2 搜索空间</a></li>
<li class="toctree-l3"><a class="reference internal" href="#id29">4.3 模型延时评估</a></li> <li class="toctree-l3"><a class="reference internal" href="#id27">4.3 模型延时评估</a></li>
</ul> </ul>
</li> </li>
<li class="toctree-l2"><a class="reference internal" href="#id30">5. 参考文献</a></li> <li class="toctree-l2"><a class="reference internal" href="#id28">5. 参考文献</a></li>
</ul> </ul>
</li> </li>
</ul> </ul>
...@@ -186,11 +186,11 @@ ...@@ -186,11 +186,11 @@
<h3>1.1 背景<a class="headerlink" href="#id7" title="永久链接至标题"></a></h3> <h3>1.1 背景<a class="headerlink" href="#id7" title="永久链接至标题"></a></h3>
<p>近年来,定点量化使用更少的比特数(如8-bit、3-bit、2-bit等)表示神经网络的权重和激活已被验证是有效的。定点量化的优点包括低内存带宽、低功耗、低计算资源占用以及低模型存储需求等。</p> <p>近年来,定点量化使用更少的比特数(如8-bit、3-bit、2-bit等)表示神经网络的权重和激活已被验证是有效的。定点量化的优点包括低内存带宽、低功耗、低计算资源占用以及低模型存储需求等。</p>
<p align="center"> <p align="center">
<img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/develop/docs/docs/images/algo/quan_table_0.png" height=258 width=600 hspace='10'/> <br /> <img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/release/1.0.1/docs/images/algo/quan_table_0.png" height=258 width=600 hspace='10'/> <br />
<strong>表1: 不同类型操作的开销对比</strong> <strong>表1: 不同类型操作的开销对比</strong>
</p><p>由表1可知,低精度定点数操作的硬件面积大小及能耗比高精度浮点数要少几个数量级。 使用定点量化可带来4倍的模型压缩、4倍的内存带宽提升,以及更高效的cache利用(很多硬件设备,内存访问是主要能耗)。除此之外,计算速度也会更快(通常具有2x-3x的性能提升)。由表2可知,在很多场景下,定点量化操作对精度并不会造成损失。另外,定点量化对神经网络于嵌入式设备上的推断来说是极其重要的。</p> </p><p>由表1可知,低精度定点数操作的硬件面积大小及能耗比高精度浮点数要少几个数量级。 使用定点量化可带来4倍的模型压缩、4倍的内存带宽提升,以及更高效的cache利用(很多硬件设备,内存访问是主要能耗)。除此之外,计算速度也会更快(通常具有2x-3x的性能提升)。由表2可知,在很多场景下,定点量化操作对精度并不会造成损失。另外,定点量化对神经网络于嵌入式设备上的推断来说是极其重要的。</p>
<p align="center"> <p align="center">
<img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/develop/docs/docs/images/algo/quan_table_1.png" height=155 width=500 hspace='10'/> <br /> <img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/release/1.0.1/docs/images/algo/quan_table_1.png" height=155 width=500 hspace='10'/> <br />
<strong>表2:模型量化前后精度对比</strong> <strong>表2:模型量化前后精度对比</strong>
</p><p>目前,学术界主要将量化分为两大类:<code class="docutils literal"><span class="pre">Post</span> <span class="pre">Training</span> <span class="pre">Quantization</span></code><code class="docutils literal"><span class="pre">Quantization</span> <span class="pre">Aware</span> <span class="pre">Training</span></code><code class="docutils literal"><span class="pre">Post</span> <span class="pre">Training</span> <span class="pre">Quantization</span></code>是指使用KL散度、滑动平均等方法确定量化参数且不需要重新训练的定点量化方法。<code class="docutils literal"><span class="pre">Quantization</span> <span class="pre">Aware</span> <span class="pre">Training</span></code>是在训练过程中对量化进行建模以确定量化参数,它与<code class="docutils literal"><span class="pre">Post</span> <span class="pre">Training</span> <span class="pre">Quantization</span></code>模式相比可以提供更高的预测精度。</p> </p><p>目前,学术界主要将量化分为两大类:<code class="docutils literal"><span class="pre">Post</span> <span class="pre">Training</span> <span class="pre">Quantization</span></code><code class="docutils literal"><span class="pre">Quantization</span> <span class="pre">Aware</span> <span class="pre">Training</span></code><code class="docutils literal"><span class="pre">Post</span> <span class="pre">Training</span> <span class="pre">Quantization</span></code>是指使用KL散度、滑动平均等方法确定量化参数且不需要重新训练的定点量化方法。<code class="docutils literal"><span class="pre">Quantization</span> <span class="pre">Aware</span> <span class="pre">Training</span></code>是在训练过程中对量化进行建模以确定量化参数,它与<code class="docutils literal"><span class="pre">Post</span> <span class="pre">Training</span> <span class="pre">Quantization</span></code>模式相比可以提供更高的预测精度。</p>
</div> </div>
...@@ -214,7 +214,7 @@ $q = scale * r + b$ ...@@ -214,7 +214,7 @@ $q = scale * r + b$
<h5>1.2.2.1 前向传播<a class="headerlink" href="#id11" title="永久链接至标题"></a></h5> <h5>1.2.2.1 前向传播<a class="headerlink" href="#id11" title="永久链接至标题"></a></h5>
<p>前向传播过程采用模拟量化的方式,具体描述如下:</p> <p>前向传播过程采用模拟量化的方式,具体描述如下:</p>
<p align="center"> <p align="center">
<img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/develop/docs/docs/images/algo/quan_forward.png" height=433 width=335 hspace='10'/> <br /> <img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/release/1.0.1/docs/images/algo/quan_forward.png" height=433 width=335 hspace='10'/> <br />
<strong>图1:基于模拟量化训练的前向过程</strong> <strong>图1:基于模拟量化训练的前向过程</strong>
</p><p>由图1可知,基于模拟量化训练的前向过程可被描述为以下四个部分: </p><p>由图1可知,基于模拟量化训练的前向过程可被描述为以下四个部分:
1) 输入和权重均被量化成8-bit整数。 1) 输入和权重均被量化成8-bit整数。
...@@ -232,7 +232,7 @@ Y</em>{dq} = frac{Y_q}{(n - 1) * (n - 1)} * X_m * W_m =frac{X_q * W_q}{(n - 1) * ...@@ -232,7 +232,7 @@ Y</em>{dq} = frac{Y_q}{(n - 1) * (n - 1)} * X_m * W_m =frac{X_q * W_q}{(n - 1) *
$$ $$
上述公式表明反量化操作可以被移动到<code class="docutils literal"><span class="pre">GEMM</span></code>之前,即先对$Xq$和$Wq$执行反量化操作再做<code class="docutils literal"><span class="pre">GEMM</span></code>操作。因此,前向传播的工作流亦可表示为如下方式:</p> 上述公式表明反量化操作可以被移动到<code class="docutils literal"><span class="pre">GEMM</span></code>之前,即先对$Xq$和$Wq$执行反量化操作再做<code class="docutils literal"><span class="pre">GEMM</span></code>操作。因此,前向传播的工作流亦可表示为如下方式:</p>
<p align="center"> <p align="center">
<img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/develop/docs/docs/images/algo/quan_fwd_1.png" height=435 width=341 hspace='10'/> <br /> <img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/release/1.0.1/docs/images/algo/quan_fwd_1.png" height=435 width=341 hspace='10'/> <br />
<strong>图2:基于模拟量化训练前向过程的等价工作流</strong> <strong>图2:基于模拟量化训练前向过程的等价工作流</strong>
</p><p>训练过程中,PaddleSlim使用图2中所示的等价工作流。在设计中,量化Pass在IrGraph中插入量化op和反量化op。因为在连续的量化、反量化操作之后输入仍然为32-bit浮点型数据。因此,PaddleSlim量化训练框架所采用的量化方式被称为模拟量化。</p> </p><p>训练过程中,PaddleSlim使用图2中所示的等价工作流。在设计中,量化Pass在IrGraph中插入量化op和反量化op。因为在连续的量化、反量化操作之后输入仍然为32-bit浮点型数据。因此,PaddleSlim量化训练框架所采用的量化方式被称为模拟量化。</p>
</div> </div>
...@@ -240,7 +240,7 @@ $$ ...@@ -240,7 +240,7 @@ $$
<h5>1.2.2.2 反向传播<a class="headerlink" href="#id12" title="永久链接至标题"></a></h5> <h5>1.2.2.2 反向传播<a class="headerlink" href="#id12" title="永久链接至标题"></a></h5>
<p>由图3可知,权重更新所需的梯度值可以由量化后的权重和量化后的激活求得。反向传播过程中的所有输入和输出均为32-bit浮点型数据。注意,梯度更新操作需要在原始权重上进行,即计算出的梯度将被加到原始权重上而非量化后或反量化后的权重上。</p> <p>由图3可知,权重更新所需的梯度值可以由量化后的权重和量化后的激活求得。反向传播过程中的所有输入和输出均为32-bit浮点型数据。注意,梯度更新操作需要在原始权重上进行,即计算出的梯度将被加到原始权重上而非量化后或反量化后的权重上。</p>
<p align="center"> <p align="center">
<img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/develop/docs/docs/images/algo/quan_bwd.png" height=300 width=650 hspace='10'/> <br /> <img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/release/1.0.1/docs/images/algo/quan_bwd.png" height=300 width=650 hspace='10'/> <br />
<strong>图3:基于模拟量化训练的反向传播和权重更新过程</strong> <strong>图3:基于模拟量化训练的反向传播和权重更新过程</strong>
</p><p>因此,量化Pass也会改变相应反向算子的某些输入。</p> </p><p>因此,量化Pass也会改变相应反向算子的某些输入。</p>
</div> </div>
...@@ -282,20 +282,20 @@ $$ ...@@ -282,20 +282,20 @@ $$
<p><strong>剪裁注意事项1</strong> <p><strong>剪裁注意事项1</strong>
剪裁一个conv layer的filter,需要修改后续conv layer的filter. 如<strong>图4</strong>所示,剪掉Xi的一个filter,会导致$X<em>{i+1}$少一个channel, $X</em>{i+1}$对应的filter在input_channel纬度上也要减1.</p> 剪裁一个conv layer的filter,需要修改后续conv layer的filter. 如<strong>图4</strong>所示,剪掉Xi的一个filter,会导致$X<em>{i+1}$少一个channel, $X</em>{i+1}$对应的filter在input_channel纬度上也要减1.</p>
<p align="center"> <p align="center">
<img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/develop/docs/docs/images/algo/pruning_0.png" height=200 width=600 hspace='10'/> <br /> <img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/release/1.0.1/docs/images/algo/pruning_0.png" height=200 width=600 hspace='10'/> <br />
<strong>图4</strong> <strong>图4</strong>
</p><p><strong>剪裁注意事项2</strong></p> </p><p><strong>剪裁注意事项2</strong></p>
<p><strong>图5</strong>所示,剪裁完$X<em>i$之后,根据注意事项1我们从$X</em>{i+1}$的filter中删除了一行(图中蓝色行),在计算$X_{i+1}$的filters的l1_norm(图中绿色一列)的时候,有两种选择: <p><strong>图5</strong>所示,剪裁完$X<em>i$之后,根据注意事项1我们从$X</em>{i+1}$的filter中删除了一行(图中蓝色行),在计算$X_{i+1}$的filters的l1_norm(图中绿色一列)的时候,有两种选择:
算上被删除的一行:independent pruning 算上被删除的一行:independent pruning
减去被删除的一行:greedy pruning</p> 减去被删除的一行:greedy pruning</p>
<p align="center"> <p align="center">
<img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/develop/docs/docs/images/algo/pruning_1.png" height=200 width=450 hspace='10'/> <br /> <img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/release/1.0.1/docs/images/algo/pruning_1.png" height=200 width=450 hspace='10'/> <br />
<strong>图5</strong> <strong>图5</strong>
</p><p><strong>剪裁注意事项3</strong> </p><p><strong>剪裁注意事项3</strong>
在对ResNet等复杂网络剪裁的时候,还要考虑到后当前卷积层的修改对上一层卷积层的影响。 在对ResNet等复杂网络剪裁的时候,还要考虑到后当前卷积层的修改对上一层卷积层的影响。
<strong>图6</strong>所示,在对residual block剪裁时,$X<em>{i+1}$层如何剪裁取决于project shortcut的剪裁结果,因为我们要保证project shortcut的output和$X</em>{i+1}$的output能被正确的concat.</p> <strong>图6</strong>所示,在对residual block剪裁时,$X<em>{i+1}$层如何剪裁取决于project shortcut的剪裁结果,因为我们要保证project shortcut的output和$X</em>{i+1}$的output能被正确的concat.</p>
<p align="center"> <p align="center">
<img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/develop/docs/docs/images/algo/pruning_2.png" height=240 width=600 hspace='10'/> <br /> <img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/release/1.0.1/docs/images/algo/pruning_2.png" height=240 width=600 hspace='10'/> <br />
<strong>图6</strong> <strong>图6</strong>
</p></div> </p></div>
<div class="section" id="uniform"> <div class="section" id="uniform">
...@@ -323,7 +323,7 @@ $$ ...@@ -323,7 +323,7 @@ $$
<div class="section" id="id19"> <div class="section" id="id19">
<h4>敏感度的理解<a class="headerlink" href="#id19" title="永久链接至标题"></a></h4> <h4>敏感度的理解<a class="headerlink" href="#id19" title="永久链接至标题"></a></h4>
<p align="center"> <p align="center">
<img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/develop/docs/docs/images/algo/pruning_3.png" height=200 width=400 hspace='10'/> <br /> <img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/release/1.0.1/docs/images/algo/pruning_3.png" height=200 width=400 hspace='10'/> <br />
<strong>图7</strong> <strong>图7</strong>
</p><p><strong>图7</strong>所示,横坐标是将filter剪裁掉的比例,竖坐标是精度的损失,每条彩色虚线表示的是网络中的一个卷积层。 </p><p><strong>图7</strong>所示,横坐标是将filter剪裁掉的比例,竖坐标是精度的损失,每条彩色虚线表示的是网络中的一个卷积层。
以不同的剪裁比例<strong>单独</strong>剪裁一个卷积层,并观察其在验证数据集上的精度损失,并绘出<strong>图7</strong>中的虚线。虚线上升较慢的,对应的卷积层相对不敏感,我们优先剪不敏感的卷积层的filter.</p> 以不同的剪裁比例<strong>单独</strong>剪裁一个卷积层,并观察其在验证数据集上的精度损失,并绘出<strong>图7</strong>中的虚线。虚线上升较慢的,对应的卷积层相对不敏感,我们优先剪不敏感的卷积层的filter.</p>
...@@ -333,7 +333,7 @@ $$ ...@@ -333,7 +333,7 @@ $$
<p>我们将<strong>图7</strong>中的折线拟合为<strong>图8</strong>中的曲线,每在竖坐标轴上选取一个精度损失值,就在横坐标轴上对应着一组剪裁率,如<strong>图8</strong>中黑色实线所示。 <p>我们将<strong>图7</strong>中的折线拟合为<strong>图8</strong>中的曲线,每在竖坐标轴上选取一个精度损失值,就在横坐标轴上对应着一组剪裁率,如<strong>图8</strong>中黑色实线所示。
用户给定一个模型整体的剪裁率,我们通过移动<strong>图5</strong>中的黑色实线来找到一组满足条件的且合法的剪裁率。</p> 用户给定一个模型整体的剪裁率,我们通过移动<strong>图5</strong>中的黑色实线来找到一组满足条件的且合法的剪裁率。</p>
<p align="center"> <p align="center">
<img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/develop/docs/docs/images/algo/pruning_4.png" height=200 width=400 hspace='10'/> <br /> <img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/release/1.0.1/docs/images/algo/pruning_4.png" height=200 width=400 hspace='10'/> <br />
<strong>图8</strong> <strong>图8</strong>
</p></div> </p></div>
<div class="section" id="id21"> <div class="section" id="id21">
...@@ -356,27 +356,24 @@ $$ ...@@ -356,27 +356,24 @@ $$
<dd>第一种是传统的蒸馏方法(参考论文:<a class="reference external" href="https://arxiv.org/pdf/1503.02531.pdf">Distilling the Knowledge in a Neural Network</a></dd> <dd>第一种是传统的蒸馏方法(参考论文:<a class="reference external" href="https://arxiv.org/pdf/1503.02531.pdf">Distilling the Knowledge in a Neural Network</a></dd>
</dl> </dl>
<p>使用复杂的网络作为teacher模型去监督训练一个参数量和运算量更少的student模型。teacher模型可以是一个或者多个提前训练好的高性能模型。student模型的训练有两个目标:一个是原始的目标函数,为student模型输出的类别概率和label的交叉熵,记为hard-target;另一个是student模型输出的类别概率和teacher模型输出的类别概率的交叉熵,记为soft target,这两个loss加权后得到最终的训练loss,共同监督studuent模型的训练。 <p>使用复杂的网络作为teacher模型去监督训练一个参数量和运算量更少的student模型。teacher模型可以是一个或者多个提前训练好的高性能模型。student模型的训练有两个目标:一个是原始的目标函数,为student模型输出的类别概率和label的交叉熵,记为hard-target;另一个是student模型输出的类别概率和teacher模型输出的类别概率的交叉熵,记为soft target,这两个loss加权后得到最终的训练loss,共同监督studuent模型的训练。
第二种是基于FSP的蒸馏方法(参考论文:<a href="#id23"><span class="problematic" id="id24">`</span></a>A Gift from Knowledge Distillation:</p> 第二种是基于FSP的蒸馏方法(参考论文:<a class="reference external" href="http://openaccess.thecvf.com/content_cvpr_2017/papers/Yim_A_Gift_From_CVPR_2017_paper.pdf">A Gift from Knowledge Distillation: Fast Optimization, Network Minimization and Transfer Learning</a>
相比传统的蒸馏方法直接用小模型去拟合大模型的输出,该方法用小模型去拟合大模型不同层特征之间的转换关系,其用一个FSP矩阵(特征的内积)来表示不同层特征之间的关系,大模型和小模型不同层之间分别获得多个FSP矩阵,然后使用L2 loss让小模型的对应层FSP矩阵和大模型对应层的FSP矩阵尽量一致,具体如下图所示。这种方法的优势,通俗的解释是,比如将蒸馏类比成teacher(大模型)教student(小模型)解决一个问题,传统的蒸馏是直接告诉小模型问题的答案,让小模型学习,而学习FSP矩阵是让小模型学习解决问题的中间过程和方法,因此其学到的信息更多。</p>
</div></blockquote> </div></blockquote>
<dl class="docutils">
<dt>Fast Optimization, Network Minimization and Transfer Learning &lt;<a class="reference external" href="http://openaccess.thecvf.com/content_cvpr_2017/papers/Yim_A_Gift_From_CVPR_2017_paper.pdf">http://openaccess.thecvf.com/content_cvpr_2017/papers/Yim_A_Gift_From_CVPR_2017_paper.pdf</a>&gt;`_)</dt>
<dd>相比传统的蒸馏方法直接用小模型去拟合大模型的输出,该方法用小模型去拟合大模型不同层特征之间的转换关系,其用一个FSP矩阵(特征的内积)来表示不同层特征之间的关系,大模型和小模型不同层之间分别获得多个FSP矩阵,然后使用L2 loss让小模型的对应层FSP矩阵和大模型对应层的FSP矩阵尽量一致,具体如下图所示。这种方法的优势,通俗的解释是,比如将蒸馏类比成teacher(大模型)教student(小模型)解决一个问题,传统的蒸馏是直接告诉小模型问题的答案,让小模型学习,而学习FSP矩阵是让小模型学习解决问题的中间过程和方法,因此其学到的信息更多。</dd>
</dl>
<p align="center"> <p align="center">
<img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/develop/docs/docs/images/algo/distillation_0.png" height=300 width=600 hspace='10'/> <br /> <img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/release/1.0.1/docs/images/algo/distillation_0.png" height=300 width=600 hspace='10'/> <br />
<strong>图9</strong> <strong>图9</strong>
</p> </p>
由于小模型和大模型之间通过L2 loss进行监督,必须保证两个FSP矩阵的维度必须相同,而FSP矩阵的维度为M*N,其中M、N分别为输入和输出特征的channel数,因此大模型和小模型的FSP矩阵需要一一对应。</div> 由于小模型和大模型之间通过L2 loss进行监督,必须保证两个FSP矩阵的维度必须相同,而FSP矩阵的维度为M*N,其中M、N分别为输入和输出特征的channel数,因此大模型和小模型的FSP矩阵需要一一对应。</div>
<div class="section" id="id25"> <div class="section" id="id23">
<h2>4. 轻量级模型结构搜索<a class="headerlink" href="#id25" title="永久链接至标题"></a></h2> <h2>4. 轻量级模型结构搜索<a class="headerlink" href="#id23" title="永久链接至标题"></a></h2>
<p>深度学习模型在很多任务上都取得了不错的效果,网络结构的好坏对最终模型的效果有非常重要的影响。手工设计网络需要非常丰富的经验和众多尝试,并且众多的超参数和网络结构参数会产生爆炸性的组合,常规的random search几乎不可行,因此最近几年自动模型搜索技术(Neural Architecture Search)成为研究热点。区别于传统NAS,我们专注在搜索精度高并且速度快的模型结构,我们将该功能统称为Light-NAS.</p> <p>深度学习模型在很多任务上都取得了不错的效果,网络结构的好坏对最终模型的效果有非常重要的影响。手工设计网络需要非常丰富的经验和众多尝试,并且众多的超参数和网络结构参数会产生爆炸性的组合,常规的random search几乎不可行,因此最近几年自动模型搜索技术(Neural Architecture Search)成为研究热点。区别于传统NAS,我们专注在搜索精度高并且速度快的模型结构,我们将该功能统称为Light-NAS.</p>
<div class="section" id="id26"> <div class="section" id="id24">
<h3>4.1 搜索策略<a class="headerlink" href="#id26" title="永久链接至标题"></a></h3> <h3>4.1 搜索策略<a class="headerlink" href="#id24" title="永久链接至标题"></a></h3>
<p>搜索策略定义了使用怎样的算法可以快速、准确找到最优的网络结构参数配置。常见的搜索方法包括:强化学习、贝叶斯优化、进化算法、基于梯度的算法。我们当前的实现以模拟退火算法为主。</p> <p>搜索策略定义了使用怎样的算法可以快速、准确找到最优的网络结构参数配置。常见的搜索方法包括:强化学习、贝叶斯优化、进化算法、基于梯度的算法。我们当前的实现以模拟退火算法为主。</p>
<div class="section" id="id27"> <div class="section" id="id25">
<h4>4.1.1 模拟退火<a class="headerlink" href="#id27" title="永久链接至标题"></a></h4> <h4>4.1.1 模拟退火<a class="headerlink" href="#id25" title="永久链接至标题"></a></h4>
<p>模拟退火算法来源于固体退火原理,将固体加温至充分高,再让其徐徐冷却,加温时,固体内部粒子随温升变为无序状,内能增大,而徐徐冷却时粒子渐趋有序,在每个温度都达到平衡态,最后在常温时达到基态,内能减为最小。</p> <p>模拟退火算法来源于固体退火原理,将固体加温至充分高,再让其徐徐冷却,加温时,固体内部粒子随温升变为无序状,内能增大,而徐徐冷却时粒子渐趋有序,在每个温度都达到平衡态,最后在常温时达到基态,内能减为最小。</p>
<p>鉴于物理中固体物质的退火过程与一般组合优化问题之间的相似性,我们将其用于网络结构的搜索。</p> <p>鉴于物理中固体物质的退火过程与一般组合优化问题之间的相似性,我们将其用于网络结构的搜索。</p>
<p>使用模拟退火算法搜索模型的过程如下:</p> <p>使用模拟退火算法搜索模型的过程如下:</p>
...@@ -393,16 +390,16 @@ end{equation}</p> ...@@ -393,16 +390,16 @@ end{equation}</p>
<p>在我们的NAS任务中,区别于RL每次重新生成一个完整的网络,我们将网络结构映射成一段编码,第一次随机初始化,然后每次随机修改编码中的一部分(对应于网络结构的一部分)生成一个新的编码,然后将这个编码再映射回网络结构,通过在训练集上训练一定的epochs后的精度以及网络延时融合获得reward,来指导退火算法的收敛。</p> <p>在我们的NAS任务中,区别于RL每次重新生成一个完整的网络,我们将网络结构映射成一段编码,第一次随机初始化,然后每次随机修改编码中的一部分(对应于网络结构的一部分)生成一个新的编码,然后将这个编码再映射回网络结构,通过在训练集上训练一定的epochs后的精度以及网络延时融合获得reward,来指导退火算法的收敛。</p>
</div> </div>
</div> </div>
<div class="section" id="id28"> <div class="section" id="id26">
<h3>4.2 搜索空间<a class="headerlink" href="#id28" title="永久链接至标题"></a></h3> <h3>4.2 搜索空间<a class="headerlink" href="#id26" title="永久链接至标题"></a></h3>
<p>搜索空间定义了优化问题的变量,变量规模决定了搜索算法的难度和搜索时间。因此为了加快搜索速度,定义一个合理的搜索空间至关重要。在Light-NAS中,为了加速搜索速度,我们将一个网络划分为多个block,先手动按链状层级结构堆叠c,再 使用搜索算法自动搜索每个block内部的结构。</p> <p>搜索空间定义了优化问题的变量,变量规模决定了搜索算法的难度和搜索时间。因此为了加快搜索速度,定义一个合理的搜索空间至关重要。在Light-NAS中,为了加速搜索速度,我们将一个网络划分为多个block,先手动按链状层级结构堆叠c,再 使用搜索算法自动搜索每个block内部的结构。</p>
<p>因为要搜索出在移动端运行速度快的模型,我们参考了MobileNetV2中的Linear Bottlenecks和Inverted residuals结构,搜索每一个Inverted residuals中的具体参数,包括kernelsize、channel扩张倍数、重复次数、channels number。如图10所示:</p> <p>因为要搜索出在移动端运行速度快的模型,我们参考了MobileNetV2中的Linear Bottlenecks和Inverted residuals结构,搜索每一个Inverted residuals中的具体参数,包括kernelsize、channel扩张倍数、重复次数、channels number。如图10所示:</p>
<p align="center"> <p align="center">
<img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/develop/docs/docs/images/algo/light-nas-block.png" height=300 width=600 hspace='10'/> <br /> <img src="https://raw.githubusercontent.com/PaddlePaddle/PaddleSlim/release/1.0.1/docs/images/algo/light-nas-block.png" height=300 width=600 hspace='10'/> <br />
<strong>图10</strong> <strong>图10</strong>
</p></div> </p></div>
<div class="section" id="id29"> <div class="section" id="id27">
<h3>4.3 模型延时评估<a class="headerlink" href="#id29" title="永久链接至标题"></a></h3> <h3>4.3 模型延时评估<a class="headerlink" href="#id27" title="永久链接至标题"></a></h3>
<p>搜索过程支持 FLOPS 约束和模型延时约束。而基于 Android/iOS 移动端、开发板等硬件平台,迭代搜索过程中不断测试模型的延时不仅消耗时间而且非常不方便,因此我们开发了模型延时评估器来评估搜索得到模型的延时。通过延时评估器评估得到的延时与模型实际测试的延时波动偏差小于 10%。</p> <p>搜索过程支持 FLOPS 约束和模型延时约束。而基于 Android/iOS 移动端、开发板等硬件平台,迭代搜索过程中不断测试模型的延时不仅消耗时间而且非常不方便,因此我们开发了模型延时评估器来评估搜索得到模型的延时。通过延时评估器评估得到的延时与模型实际测试的延时波动偏差小于 10%。</p>
<p>延时评估器分为配置硬件延时评估器和评估模型延时两个阶段,配置硬件延时评估器只需要执行一次,而评估模型延时则在搜索过程中不断评估搜索得到的模型延时。</p> <p>延时评估器分为配置硬件延时评估器和评估模型延时两个阶段,配置硬件延时评估器只需要执行一次,而评估模型延时则在搜索过程中不断评估搜索得到的模型延时。</p>
<ul class="simple"> <ul class="simple">
...@@ -419,8 +416,8 @@ end{equation}</p> ...@@ -419,8 +416,8 @@ end{equation}</p>
</ul> </ul>
</div> </div>
</div> </div>
<div class="section" id="id30"> <div class="section" id="id28">
<h2>5. 参考文献<a class="headerlink" href="#id30" title="永久链接至标题"></a></h2> <h2>5. 参考文献<a class="headerlink" href="#id28" title="永久链接至标题"></a></h2>
<ol class="arabic simple"> <ol class="arabic simple">
<li><a class="reference external" href="https://media.nips.cc/Conferences/2015/tutorialslides/Dally-NIPS-Tutorial-2015.pdf">High-Performance Hardware for Machine Learning</a></li> <li><a class="reference external" href="https://media.nips.cc/Conferences/2015/tutorialslides/Dally-NIPS-Tutorial-2015.pdf">High-Performance Hardware for Machine Learning</a></li>
<li><a class="reference external" href="https://arxiv.org/pdf/1806.08342.pdf">Quantizing deep convolutional networks for efficient inference: A whitepaper</a></li> <li><a class="reference external" href="https://arxiv.org/pdf/1806.08342.pdf">Quantizing deep convolutional networks for efficient inference: A whitepaper</a></li>
......
...@@ -155,7 +155,7 @@ ...@@ -155,7 +155,7 @@
<h1>SA-NAS<a class="headerlink" href="#sa-nas" title="永久链接至标题"></a></h1> <h1>SA-NAS<a class="headerlink" href="#sa-nas" title="永久链接至标题"></a></h1>
<div class="section" id="id1"> <div class="section" id="id1">
<h2>搜索空间参数的配置<a class="headerlink" href="#id1" title="永久链接至标题"></a></h2> <h2>搜索空间参数的配置<a class="headerlink" href="#id1" title="永久链接至标题"></a></h2>
<p>通过参数配置搜索空间。更多搜索空间的使用可以参考: [search_space](../search_space.md)</p> <p>通过参数配置搜索空间。更多搜索空间的使用可以参考: <a class="reference external" href="https://paddlepaddle.github.io/PaddleSlim/api_cn/search_space.html">search_space</a></p>
<p><strong>参数:</strong></p> <p><strong>参数:</strong></p>
<ul class="simple"> <ul class="simple">
<li><strong>input_size(int|None)</strong>:- <code class="docutils literal"><span class="pre">input_size</span></code> 表示输入 <code class="docutils literal"><span class="pre">feature</span> <span class="pre">map</span></code> 的大小。 <code class="docutils literal"><span class="pre">input_size</span></code><code class="docutils literal"><span class="pre">output_size</span></code> 用来计算整个模型结构中下采样次数。</li> <li><strong>input_size(int|None)</strong>:- <code class="docutils literal"><span class="pre">input_size</span></code> 表示输入 <code class="docutils literal"><span class="pre">feature</span> <span class="pre">map</span></code> 的大小。 <code class="docutils literal"><span class="pre">input_size</span></code><code class="docutils literal"><span class="pre">output_size</span></code> 用来计算整个模型结构中下采样次数。</li>
...@@ -257,6 +257,11 @@ ...@@ -257,6 +257,11 @@
<span class="n">sanas</span><span class="o">.</span><span class="n">reward</span><span class="p">(</span><span class="nb">float</span><span class="p">(</span><span class="n">score</span><span class="p">))</span> <span class="n">sanas</span><span class="o">.</span><span class="n">reward</span><span class="p">(</span><span class="nb">float</span><span class="p">(</span><span class="n">score</span><span class="p">))</span>
</pre></div> </pre></div>
</div> </div>
<dl class="method">
<dt id="tokens2arch">
<code class="descname">tokens2arch</code><span class="sig-paren">(</span><em>tokens</em><span class="sig-paren">)</span><a class="headerlink" href="#tokens2arch" title="永久链接至目标"></a></dt>
<dd></dd></dl>
<p>通过一组tokens得到实际的模型结构,一般用来把搜索到最优的token转换为模型结构用来做最后的训练。tokens的形式是一个列表,tokens映射到搜索空间转换成相应的网络结构,一组tokens对应唯一的一个网络结构。</p> <p>通过一组tokens得到实际的模型结构,一般用来把搜索到最优的token转换为模型结构用来做最后的训练。tokens的形式是一个列表,tokens映射到搜索空间转换成相应的网络结构,一组tokens对应唯一的一个网络结构。</p>
<p><strong>参数:</strong></p> <p><strong>参数:</strong></p>
<ul class="simple"> <ul class="simple">
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
...@@ -157,7 +157,7 @@ ...@@ -157,7 +157,7 @@
<div class="section" id="id1"> <div class="section" id="id1">
<h1>图像分类模型量化训练-快速开始<a class="headerlink" href="#id1" title="永久链接至标题"></a></h1> <h1>图像分类模型量化训练-快速开始<a class="headerlink" href="#id1" title="永久链接至标题"></a></h1>
<p>该教程以图像分类模型MobileNetV1为例,说明如何快速使用PaddleSlim的<a class="reference external" href="https://github.com/PaddlePaddle/PaddleSlim/blob/develop/docs/docs/api/quantization_api.md">量化训练接口</a>。 该示例包含以下步骤:</p> <p>该教程以图像分类模型MobileNetV1为例,说明如何快速使用PaddleSlim的<a class="reference external" href="https://paddlepaddle.github.io/PaddleSlim/api_cn/quantization_api.html">量化训练接口</a>。 该示例包含以下步骤:</p>
<ol class="arabic simple"> <ol class="arabic simple">
<li>导入依赖</li> <li>导入依赖</li>
<li>构建模型</li> <li>构建模型</li>
...@@ -238,7 +238,7 @@ ...@@ -238,7 +238,7 @@
</div> </div>
<div class="section" id="id8"> <div class="section" id="id8">
<h2>4. 量化<a class="headerlink" href="#id8" title="永久链接至标题"></a></h2> <h2>4. 量化<a class="headerlink" href="#id8" title="永久链接至标题"></a></h2>
<p>按照<a class="reference external" href="https://paddlepaddle.github.io/PaddleSlim/api/quantization_api/#_1">默认配置</a><code class="docutils literal"><span class="pre">train_program</span></code><code class="docutils literal"><span class="pre">val_program</span></code>中加入量化和反量化op.</p> <p>按照<a class="reference external" href="https://paddlepaddle.github.io/PaddleSlim/api_cn/quantization_api.html#id2">默认配置</a><code class="docutils literal"><span class="pre">train_program</span></code><code class="docutils literal"><span class="pre">val_program</span></code>中加入量化和反量化op.</p>
<div class="highlight-python"><div class="highlight"><pre><span></span><span class="n">quant_program</span> <span class="o">=</span> <span class="n">slim</span><span class="o">.</span><span class="n">quant</span><span class="o">.</span><span class="n">quant_aware</span><span class="p">(</span><span class="n">train_program</span><span class="p">,</span> <span class="n">exe</span><span class="o">.</span><span class="n">place</span><span class="p">,</span> <span class="n">for_test</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span> <div class="highlight-python"><div class="highlight"><pre><span></span><span class="n">quant_program</span> <span class="o">=</span> <span class="n">slim</span><span class="o">.</span><span class="n">quant</span><span class="o">.</span><span class="n">quant_aware</span><span class="p">(</span><span class="n">train_program</span><span class="p">,</span> <span class="n">exe</span><span class="o">.</span><span class="n">place</span><span class="p">,</span> <span class="n">for_test</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
<span class="n">val_quant_program</span> <span class="o">=</span> <span class="n">slim</span><span class="o">.</span><span class="n">quant</span><span class="o">.</span><span class="n">quant_aware</span><span class="p">(</span><span class="n">val_program</span><span class="p">,</span> <span class="n">exe</span><span class="o">.</span><span class="n">place</span><span class="p">,</span> <span class="n">for_test</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span> <span class="n">val_quant_program</span> <span class="o">=</span> <span class="n">slim</span><span class="o">.</span><span class="n">quant</span><span class="o">.</span><span class="n">quant_aware</span><span class="p">(</span><span class="n">val_program</span><span class="p">,</span> <span class="n">exe</span><span class="o">.</span><span class="n">place</span><span class="p">,</span> <span class="n">for_test</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</pre></div> </pre></div>
...@@ -257,7 +257,7 @@ ...@@ -257,7 +257,7 @@
</div> </div>
<div class="section" id="id11"> <div class="section" id="id11">
<h2>6. 保存量化后的模型<a class="headerlink" href="#id11" title="永久链接至标题"></a></h2> <h2>6. 保存量化后的模型<a class="headerlink" href="#id11" title="永久链接至标题"></a></h2>
<p><code class="docutils literal"><span class="pre">4.</span> <span class="pre">量化</span></code>中使用接口<code class="docutils literal"><span class="pre">slim.quant.quant_aware</span></code>接口得到的模型只适合训练时使用,为了得到最终使用时的模型,需要使用<a class="reference external" href="https://paddlepaddle.github.io/PaddleSlim/api/quantization_api/#convert">slim.quant.convert</a>接口,然后使用<a class="reference external" href="https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/api_cn/io_cn/save_inference_model_cn.html#save-inference-model">fluid.io.save_inference_model</a>保存模型。<code class="docutils literal"><span class="pre">float_prog</span></code>的参数数据类型是float32,但是数据范围是int8, 保存之后可使用fluid或者paddle-lite加载使用,paddle-lite在使用时,会先将类型转换为int8。<code class="docutils literal"><span class="pre">int8_prog</span></code>的参数数据类型是int8, 保存后可看到量化后模型大小,不可加载使用。</p> <p><code class="docutils literal"><span class="pre">4.</span> <span class="pre">量化</span></code>中使用接口<code class="docutils literal"><span class="pre">slim.quant.quant_aware</span></code>接口得到的模型只适合训练时使用,为了得到最终使用时的模型,需要使用<a class="reference external" href="https://paddlepaddle.github.io/PaddleSlim/api_cn/quantization_api.html#convert">slim.quant.convert</a>接口,然后使用<a class="reference external" href="https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/api_cn/io_cn/save_inference_model_cn.html#save-inference-model">fluid.io.save_inference_model</a>保存模型。<code class="docutils literal"><span class="pre">float_prog</span></code>的参数数据类型是float32,但是数据范围是int8, 保存之后可使用fluid或者paddle-lite加载使用,paddle-lite在使用时,会先将类型转换为int8。<code class="docutils literal"><span class="pre">int8_prog</span></code>的参数数据类型是int8, 保存后可看到量化后模型大小,不可加载使用。</p>
<div class="highlight-python"><div class="highlight"><pre><span></span><span class="n">float_prog</span><span class="p">,</span> <span class="n">int8_prog</span> <span class="o">=</span> <span class="n">slim</span><span class="o">.</span><span class="n">quant</span><span class="o">.</span><span class="n">convert</span><span class="p">(</span><span class="n">val_quant_program</span><span class="p">,</span> <span class="n">exe</span><span class="o">.</span><span class="n">place</span><span class="p">,</span> <span class="n">save_int8</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span> <div class="highlight-python"><div class="highlight"><pre><span></span><span class="n">float_prog</span><span class="p">,</span> <span class="n">int8_prog</span> <span class="o">=</span> <span class="n">slim</span><span class="o">.</span><span class="n">quant</span><span class="o">.</span><span class="n">convert</span><span class="p">(</span><span class="n">val_quant_program</span><span class="p">,</span> <span class="n">exe</span><span class="o">.</span><span class="n">place</span><span class="p">,</span> <span class="n">save_int8</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="n">target_vars</span> <span class="o">=</span> <span class="p">[</span><span class="n">float_prog</span><span class="o">.</span><span class="n">global_block</span><span class="p">()</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="n">name</span><span class="p">)</span> <span class="k">for</span> <span class="n">name</span> <span class="ow">in</span> <span class="n">outputs</span><span class="p">]</span> <span class="n">target_vars</span> <span class="o">=</span> <span class="p">[</span><span class="n">float_prog</span><span class="o">.</span><span class="n">global_block</span><span class="p">()</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="n">name</span><span class="p">)</span> <span class="k">for</span> <span class="n">name</span> <span class="ow">in</span> <span class="n">outputs</span><span class="p">]</span>
<span class="n">fluid</span><span class="o">.</span><span class="n">io</span><span class="o">.</span><span class="n">save_inference_model</span><span class="p">(</span><span class="n">dirname</span><span class="o">=</span><span class="s1">&#39;./inference_model/float&#39;</span><span class="p">,</span> <span class="n">fluid</span><span class="o">.</span><span class="n">io</span><span class="o">.</span><span class="n">save_inference_model</span><span class="p">(</span><span class="n">dirname</span><span class="o">=</span><span class="s1">&#39;./inference_model/float&#39;</span><span class="p">,</span>
......
...@@ -155,7 +155,7 @@ ...@@ -155,7 +155,7 @@
<div class="section" id="training-aware-quantization-of-image-classification-model-quick-start"> <div class="section" id="training-aware-quantization-of-image-classification-model-quick-start">
<h1>Training-aware Quantization of image classification model - quick start<a class="headerlink" href="#training-aware-quantization-of-image-classification-model-quick-start" title="Permalink to this headline"></a></h1> <h1>Training-aware Quantization of image classification model - quick start<a class="headerlink" href="#training-aware-quantization-of-image-classification-model-quick-start" title="Permalink to this headline"></a></h1>
<p>This tutorial shows how to do training-aware quantization using <a class="reference external" href="https://github.com/PaddlePaddle/PaddleSlim/blob/develop/docs/docs/api/quantization_api.md">API</a> in PaddleSlim. We use MobileNetV1 to train image classification model as example. The tutorial contains follow sections:</p> <p>This tutorial shows how to do training-aware quantization using <a class="reference external" href="https://paddlepaddle.github.io/PaddleSlim/api_en/paddleslim.quant.html#paddleslim.quant.quanter.quant_aware">API</a> in PaddleSlim. We use MobileNetV1 to train image classification model as example. The tutorial contains follow sections:</p>
<ol class="arabic simple"> <ol class="arabic simple">
<li>Necessary imports</li> <li>Necessary imports</li>
<li>Model architecture</li> <li>Model architecture</li>
...@@ -235,7 +235,7 @@ ...@@ -235,7 +235,7 @@
</div> </div>
<div class="section" id="quantization"> <div class="section" id="quantization">
<h2>4. Quantization<a class="headerlink" href="#quantization" title="Permalink to this headline"></a></h2> <h2>4. Quantization<a class="headerlink" href="#quantization" title="Permalink to this headline"></a></h2>
<p>We call <code class="docutils literal"><span class="pre">quant_aware</span></code> API to add quantization and dequantization operators in <code class="docutils literal"><span class="pre">train_program</span></code> and <code class="docutils literal"><span class="pre">val_program</span></code> according to <a class="reference external" href="https://paddlepaddle.github.io/PaddleSlim/api/quantization_api/#_1">default configuration</a>.</p> <p>We call <code class="docutils literal"><span class="pre">quant_aware</span></code> API to add quantization and dequantization operators in <code class="docutils literal"><span class="pre">train_program</span></code> and <code class="docutils literal"><span class="pre">val_program</span></code> according to <a class="reference external" href="https://paddlepaddle.github.io/PaddleSlim/api_cn/quantization_api.html#id2">default configuration</a>.</p>
<div class="highlight-python"><div class="highlight"><pre><span></span><span class="n">quant_program</span> <span class="o">=</span> <span class="n">slim</span><span class="o">.</span><span class="n">quant</span><span class="o">.</span><span class="n">quant_aware</span><span class="p">(</span><span class="n">train_program</span><span class="p">,</span> <span class="n">exe</span><span class="o">.</span><span class="n">place</span><span class="p">,</span> <span class="n">for_test</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span> <div class="highlight-python"><div class="highlight"><pre><span></span><span class="n">quant_program</span> <span class="o">=</span> <span class="n">slim</span><span class="o">.</span><span class="n">quant</span><span class="o">.</span><span class="n">quant_aware</span><span class="p">(</span><span class="n">train_program</span><span class="p">,</span> <span class="n">exe</span><span class="o">.</span><span class="n">place</span><span class="p">,</span> <span class="n">for_test</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
<span class="n">val_quant_program</span> <span class="o">=</span> <span class="n">slim</span><span class="o">.</span><span class="n">quant</span><span class="o">.</span><span class="n">quant_aware</span><span class="p">(</span><span class="n">val_program</span><span class="p">,</span> <span class="n">exe</span><span class="o">.</span><span class="n">place</span><span class="p">,</span> <span class="n">for_test</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span> <span class="n">val_quant_program</span> <span class="o">=</span> <span class="n">slim</span><span class="o">.</span><span class="n">quant</span><span class="o">.</span><span class="n">quant_aware</span><span class="p">(</span><span class="n">val_program</span><span class="p">,</span> <span class="n">exe</span><span class="o">.</span><span class="n">place</span><span class="p">,</span> <span class="n">for_test</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</pre></div> </pre></div>
...@@ -254,7 +254,7 @@ ...@@ -254,7 +254,7 @@
</div> </div>
<div class="section" id="save-model-after-quantization"> <div class="section" id="save-model-after-quantization">
<h2>6. Save model after quantization<a class="headerlink" href="#save-model-after-quantization" title="Permalink to this headline"></a></h2> <h2>6. Save model after quantization<a class="headerlink" href="#save-model-after-quantization" title="Permalink to this headline"></a></h2>
<p>The model in <code class="docutils literal"><span class="pre">4.</span> <span class="pre">Quantization</span></code> after calling <code class="docutils literal"><span class="pre">slim.quant.quant_aware</span></code> API is only suitable to train. To get the inference model, we should use <a class="reference external" href="https://paddlepaddle.github.io/PaddleSlim/api/quantization_api/#convert">slim.quant.convert</a> API to change model architecture and use <a class="reference external" href="https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/api_cn/io_cn/save_inference_model_cn.html#save-inference-model">fluid.io.save_inference_model</a> to save model. <code class="docutils literal"><span class="pre">float_prog</span></code>&#8216;s parameters are float32 dtype but in int8&#8217;s range which can be used in <code class="docutils literal"><span class="pre">fluid</span></code> or <code class="docutils literal"><span class="pre">paddle-lite</span></code>. <code class="docutils literal"><span class="pre">paddle-lite</span></code> will change the parameters&#8217; dtype from float32 to int8 first when loading the inference model. <code class="docutils literal"><span class="pre">int8_prog</span></code>&#8216;s parameters are int8 dtype and we can get model size after quantization by saving it. <code class="docutils literal"><span class="pre">int8_prog</span></code> cannot be used in <code class="docutils literal"><span class="pre">fluid</span></code> or <code class="docutils literal"><span class="pre">paddle-lite</span></code>.</p> <p>The model in <code class="docutils literal"><span class="pre">4.</span> <span class="pre">Quantization</span></code> after calling <code class="docutils literal"><span class="pre">slim.quant.quant_aware</span></code> API is only suitable to train. To get the inference model, we should use <a class="reference external" href="https://paddlepaddle.github.io/PaddleSlim/api_en/paddleslim.quant.html#paddleslim.quant.quanter.convert">slim.quant.convert</a> API to change model architecture and use <a class="reference external" href="https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/api_cn/io_cn/save_inference_model_cn.html#save-inference-model">fluid.io.save_inference_model</a> to save model. <code class="docutils literal"><span class="pre">float_prog</span></code>&#8216;s parameters are float32 dtype but in int8&#8217;s range which can be used in <code class="docutils literal"><span class="pre">fluid</span></code> or <code class="docutils literal"><span class="pre">paddle-lite</span></code>. <code class="docutils literal"><span class="pre">paddle-lite</span></code> will change the parameters&#8217; dtype from float32 to int8 first when loading the inference model. <code class="docutils literal"><span class="pre">int8_prog</span></code>&#8216;s parameters are int8 dtype and we can get model size after quantization by saving it. <code class="docutils literal"><span class="pre">int8_prog</span></code> cannot be used in <code class="docutils literal"><span class="pre">fluid</span></code> or <code class="docutils literal"><span class="pre">paddle-lite</span></code>.</p>
<div class="highlight-python"><div class="highlight"><pre><span></span><span class="n">float_prog</span><span class="p">,</span> <span class="n">int8_prog</span> <span class="o">=</span> <span class="n">slim</span><span class="o">.</span><span class="n">quant</span><span class="o">.</span><span class="n">convert</span><span class="p">(</span><span class="n">val_quant_program</span><span class="p">,</span> <span class="n">exe</span><span class="o">.</span><span class="n">place</span><span class="p">,</span> <span class="n">save_int8</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span> <div class="highlight-python"><div class="highlight"><pre><span></span><span class="n">float_prog</span><span class="p">,</span> <span class="n">int8_prog</span> <span class="o">=</span> <span class="n">slim</span><span class="o">.</span><span class="n">quant</span><span class="o">.</span><span class="n">convert</span><span class="p">(</span><span class="n">val_quant_program</span><span class="p">,</span> <span class="n">exe</span><span class="o">.</span><span class="n">place</span><span class="p">,</span> <span class="n">save_int8</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="n">target_vars</span> <span class="o">=</span> <span class="p">[</span><span class="n">float_prog</span><span class="o">.</span><span class="n">global_block</span><span class="p">()</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="n">name</span><span class="p">)</span> <span class="k">for</span> <span class="n">name</span> <span class="ow">in</span> <span class="n">outputs</span><span class="p">]</span> <span class="n">target_vars</span> <span class="o">=</span> <span class="p">[</span><span class="n">float_prog</span><span class="o">.</span><span class="n">global_block</span><span class="p">()</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="n">name</span><span class="p">)</span> <span class="k">for</span> <span class="n">name</span> <span class="ow">in</span> <span class="n">outputs</span><span class="p">]</span>
<span class="n">fluid</span><span class="o">.</span><span class="n">io</span><span class="o">.</span><span class="n">save_inference_model</span><span class="p">(</span><span class="n">dirname</span><span class="o">=</span><span class="s1">&#39;./inference_model/float&#39;</span><span class="p">,</span> <span class="n">fluid</span><span class="o">.</span><span class="n">io</span><span class="o">.</span><span class="n">save_inference_model</span><span class="p">(</span><span class="n">dirname</span><span class="o">=</span><span class="s1">&#39;./inference_model/float&#39;</span><span class="p">,</span>
......
...@@ -155,7 +155,7 @@ ...@@ -155,7 +155,7 @@
<div class="section" id="id1"> <div class="section" id="id1">
<h1>图像分类模型离线量化-快速开始<a class="headerlink" href="#id1" title="永久链接至标题"></a></h1> <h1>图像分类模型离线量化-快速开始<a class="headerlink" href="#id1" title="永久链接至标题"></a></h1>
<p>该教程以图像分类模型MobileNetV1为例,说明如何快速使用PaddleSlim的<a class="reference external" href="https://github.com/PaddlePaddle/PaddleSlim/blob/develop/docs/docs/api/quantization_api.md">离线量化接口</a>。 该示例包含以下步骤:</p> <p>该教程以图像分类模型MobileNetV1为例,说明如何快速使用PaddleSlim的<a class="reference external" href="https://paddlepaddle.github.io/PaddleSlim/api_cn/quantization_api.html#quant-post">离线量化接口</a>。 该示例包含以下步骤:</p>
<ol class="arabic simple"> <ol class="arabic simple">
<li>导入依赖</li> <li>导入依赖</li>
<li>构建模型</li> <li>构建模型</li>
...@@ -174,7 +174,7 @@ ...@@ -174,7 +174,7 @@
</div> </div>
<div class="section" id="id4"> <div class="section" id="id4">
<h2>2. 构建网络<a class="headerlink" href="#id4" title="永久链接至标题"></a></h2> <h2>2. 构建网络<a class="headerlink" href="#id4" title="永久链接至标题"></a></h2>
<p>该章节构造一个用于对MNIST数据进行分类的分类模型,选用<code class="docutils literal"><span class="pre">MobileNetV1</span></code>,并将输入大小设置为<code class="docutils literal"><span class="pre">[1,</span> <span class="pre">28,</span> <span class="pre">28]</span></code>,输出类别数为10。 为了方便展示示例,我们在<code class="docutils literal"><span class="pre">paddleslim.models</span></code>下预定义了用于构建分类模型的方法,执行以下代码构建分类模型:</p> <p>该章节构造一个用于对MNIST数据进行分类的分类模型,选用<code class="docutils literal"><span class="pre">MobileNetV1</span></code>,并将输入大小设置为<code class="docutils literal"><span class="pre">[1,</span> <span class="pre">28,</span> <span class="pre">28]</span></code>,输出类别数为10。为了方便展示示例,我们在<code class="docutils literal"><span class="pre">paddleslim.models</span></code>下预定义了用于构建分类模型的方法,执行以下代码构建分类模型:</p>
<blockquote> <blockquote>
<div>注意:paddleslim.models下的API并非PaddleSlim常规API,是为了简化示例而封装预定义的一系列方法,比如:模型结构的定义、Program的构建等。</div></blockquote> <div>注意:paddleslim.models下的API并非PaddleSlim常规API,是为了简化示例而封装预定义的一系列方法,比如:模型结构的定义、Program的构建等。</div></blockquote>
<div class="highlight-python"><div class="highlight"><pre><span></span><span class="n">exe</span><span class="p">,</span> <span class="n">train_program</span><span class="p">,</span> <span class="n">val_program</span><span class="p">,</span> <span class="n">inputs</span><span class="p">,</span> <span class="n">outputs</span> <span class="o">=</span> \ <div class="highlight-python"><div class="highlight"><pre><span></span><span class="n">exe</span><span class="p">,</span> <span class="n">train_program</span><span class="p">,</span> <span class="n">val_program</span><span class="p">,</span> <span class="n">inputs</span><span class="p">,</span> <span class="n">outputs</span> <span class="o">=</span> \
......
...@@ -153,7 +153,7 @@ ...@@ -153,7 +153,7 @@
<div class="section" id="post-training-quantization-of-image-classification-model-quick-start"> <div class="section" id="post-training-quantization-of-image-classification-model-quick-start">
<h1>Post-training Quantization of image classification model - quick start<a class="headerlink" href="#post-training-quantization-of-image-classification-model-quick-start" title="Permalink to this headline"></a></h1> <h1>Post-training Quantization of image classification model - quick start<a class="headerlink" href="#post-training-quantization-of-image-classification-model-quick-start" title="Permalink to this headline"></a></h1>
<p>This tutorial shows how to do post training quantization using <a class="reference external" href="https://github.com/PaddlePaddle/PaddleSlim/blob/develop/docs/docs/api/quantization_api.md">API</a> in PaddleSlim. We use MobileNetV1 to train image classification model as example. The tutorial contains follow sections:</p> <p>This tutorial shows how to do post training quantization using <a class="reference external" href="https://paddlepaddle.github.io/PaddleSlim/api_en/paddleslim.quant.html#paddleslim.quant.quanter.quant_post">API</a> in PaddleSlim. We use MobileNetV1 to train image classification model as example. The tutorial contains follow sections:</p>
<ol class="arabic simple"> <ol class="arabic simple">
<li>Necessary imports</li> <li>Necessary imports</li>
<li>Model architecture</li> <li>Model architecture</li>
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册