From a7fe788cb47a24015e7ea7bc5aa8a4ba565cf482 Mon Sep 17 00:00:00 2001
From: baiyfbupt 示例: paddleslim.analysis.model_size(program) 源代码 示例: 返回:
一个SANAS类的实例 示例代码:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
import paddle.fluid as fluid
+
import paddle.fluid as fluid
from paddle.fluid.param_attr import ParamAttr
from paddleslim.analysis import flops
@@ -312,7 +260,6 @@
print("FLOPs: {}".format(flops(main_program)))
model_size#
1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
import paddle.fluid as fluid
+
import paddle.fluid as fluid
from paddle.fluid.param_attr import ParamAttr
from paddleslim.analysis import model_size
@@ -416,7 +319,6 @@
print("FLOPs: {}".format(model_size(main_program)))
TableLatencyEvaluator#
diff --git a/api/nas_api/index.html b/api/nas_api/index.html
index bcdf09d1..4a442562 100644
--- a/api/nas_api/index.html
+++ b/api/nas_api/index.html
@@ -205,13 +205,10 @@
1
-2
-3
from paddleslim.nas import SANAS
+
from paddleslim.nas import SANAS
config = [('MobileNetV2Space')]
sanas = SANAS(config=config)
-
返回: 根据传入的token得到一个模型结构实例。
示例代码: -
1 -2 -3 -4 -5 -6 | import paddle.fluid as fluid + |
返回: 返回模型结构实例的列表,形式为list。
示例代码: -
1 -2 -3 -4 -5 -6 | import paddle.fluid as fluid + |
返回: 一个Pruner类的实例
示例代码:
-1 -2 | from paddleslim.prune import Pruner + |
params(list
1 -2 -3 | for block in program.blocks: + |
ratios(listparams
的剪切率,类型为列表。该列表长度必须与params
的长度一致。
示例:
点击AIStudio执行以下示例代码。 -
1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 | import paddle.fluid as fluid + |
param_names(list
1 -2 -3 | for block in program.blocks: + |
1 -2 -3 -4 -5 -6 -7 -8 -9 | {"weight_0": + |
其中,weight_0
是卷积层参数的名称,sensitivities['weight_0']的value
为剪裁比例,value
为精度损失的比例。
示例:
点击AIStudio运行以下示例代码。
-1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 | import paddle + |
1 -2 -3 -4 -5 -6 -7 -8 -9 | {"weight_0": + |
其中,weight_0
是卷积层参数的名称,sensitivities['weight_0']的value
为剪裁比例,value
为精度损失的比例。
示例:
diff --git a/api/quantization_api/index.html b/api/quantization_api/index.html index aceb0b11..2d777bb3 100644 --- a/api/quantization_api/index.html +++ b/api/quantization_api/index.html @@ -185,44 +185,7 @@通过字典配置量化参数
-1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 | TENSORRT_OP_TYPES = [ + |
参数:
因为该接口会对op
和Variable
做相应的删除和修改,所以此接口只能在训练完成之后调用。如果想转化训练的中间模型,可加载相应的参数之后再使用此接口。
代码示例
-1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 | #encoding=utf8 + |
更详细的用法请参考 量化训练demo。
-注: 此示例不能直接运行,因为需要加载
${model_dir}
下的模型,所以不能直接运行。
1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 -10 -11 -12 -13 -14 -15 -16 -17 | import paddle.fluid as fluid + |
返回类型
fluid.Program
代码示例 -
1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 | import paddle.fluid as fluid + |
更详细的用法请参考 Embedding量化demo。
diff --git a/api/single_distiller_api/index.html b/api/single_distiller_api/index.html index 1a7863b1..91b0d4a1 100644 --- a/api/single_distiller_api/index.html +++ b/api/single_distiller_api/index.html @@ -205,24 +205,7 @@data_name_map 是 teacher_var name到student_var name的映射,如果写反可能无法正确进行merge
使用示例:
-1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 -10 -11 -12 -13 -14 -15 -16 -17 -18 | import paddle.fluid as fluid + |
返回: 由teacher_var1, teacher_var2, student_var1, student_var2组合得到的fsp_loss
使用示例:
-1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 | import paddle.fluid as fluid + |
返回: 由teacher_var, student_var组合得到的l2_loss
使用示例:
-1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 | import paddle.fluid as fluid + |
返回: 由teacher_var, student_var组合得到的soft_label_loss
使用示例:
-1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 | import paddle.fluid as fluid + |
返回:自定义的损失函数loss
使用示例:
-1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 | import paddle.fluid as fluid + |
注意事项
diff --git a/extra.css b/extra.css index 2d501897..2a1e1c74 100644 --- a/extra.css +++ b/extra.css @@ -1,4 +1,115 @@ -.codehilite { - width: 590px; - overflow: auto; -} +.codehilite code, .codehilite pre{color:#3F3F3F;background-color:#F7F7F7; +overflow: auto; +box-sizing: border-box; + + padding: 0.01em 16px; + padding-top: 0.5em; + padding-right-value: 16px; + padding-bottom: 0.5em; + padding-left-value: 16px; + padding-left-ltr-source: physical; + padding-left-rtl-source: physical; + padding-right-ltr-source: physical; + padding-right-rtl-source: physical; + +border-radius: 10px !important; + border-top-left-radius: 16px; + border-top-right-radius: 16px; + border-bottom-right-radius: 16px; + border-bottom-left-radius: 16px; + +border: 2px solid #CCC !important; + border-top-width: 1px; + border-right-width-value: 1px; + border-right-width-ltr-source: physical; + border-right-width-rtl-source: physical; + border-bottom-width: 1px; + border-left-width-value: 1px; + border-left-width-ltr-source: physical; + border-left-width-rtl-source: physical; + border-top-style: solid; + border-right-style-value: solid; + border-right-style-ltr-source: physical; + border-right-style-rtl-source: physical; + border-bottom-style: solid; + border-left-style-value: solid; + border-left-style-ltr-source: physical; + border-left-style-rtl-source: physical; + border-top-color: #CCC; + border-right-color-value: #CCC; + border-right-color-ltr-source: physical; + border-right-color-rtl-source: physical; + border-bottom-color: #CCC; + border-left-color-value: #CCC; + border-left-color-ltr-source: physical; + border-left-color-rtl-source: physical; + -moz-border-top-colors: none; + -moz-border-right-colors: none; + -moz-border-bottom-colors: none; + -moz-border-left-colors: none; + border-image-source: none; + border-image-slice: 100% 100% 100% 100%; + border-image-width: 1 1 1 1; + border-image-outset: 0 0 0 0; + border-image-repeat: stretch stretch;} +.codehilite .hll { background-color: #ffffcc } +.codehilite .c { color: #999988; font-style: italic } /* Comment */ +.codehilite .err { color: #a61717; background-color: #e3d2d2 } /* Error */ +.codehilite .k { color: #008800; font-weight: bold } /* Keyword */ +.codehilite .o { color: #000000; font-weight: bold } /* Operator */ +.codehilite .cm { color: #999988; font-style: italic } /* Comment.Multiline */ +.codehilite .cp { color: #999999; font-weight: bold; font-style: italic } /* Comment.Preproc */ +.codehilite .c1 { color: #999988; font-style: italic } /* Comment.Single */ +.codehilite .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */ +.codehilite .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ +.codehilite .ge { color: #000000; font-style: italic } /* Generic.Emph */ +.codehilite .gr { color: #aa0000 } /* Generic.Error */ +.codehilite .gh { color: #999999 } /* Generic.Heading */ +.codehilite .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ +.codehilite .go { color: #888888 } /* Generic.Output */ +.codehilite .gp { color: #555555 } /* Generic.Prompt */ +.codehilite .gs { font-weight: bold } /* Generic.Strong */ +.codehilite .gu { color: #aaaaaa } /* Generic.Subheading */ +.codehilite .gt { color: #aa0000 } /* Generic.Traceback */ +.codehilite .kc { color: #000000; font-weight: bold } /* Keyword.Constant */ +.codehilite .kd { color: #000000; font-weight: bold } /* Keyword.Declaration */ +.codehilite .kn { color: #000000; font-weight: bold } /* Keyword.Namespace */ +.codehilite .kp { color: #000000; font-weight: bold } /* Keyword.Pseudo */ +.codehilite .kr { color: #000000; font-weight: bold } /* Keyword.Reserved */ +.codehilite .kt { color: #445588; font-weight: bold } /* Keyword.Type */ +.codehilite .m { color: #009999 } /* Literal.Number */ +.codehilite .s { color: #d01040 } /* Literal.String */ +.codehilite .na { color: #008080 } /* Name.Attribute */ +.codehilite .nb { color: #0086B3 } /* Name.Builtin */ +.codehilite .nc { color: #445588; font-weight: bold } /* Name.Class */ +.codehilite .no { color: #008080 } /* Name.Constant */ +.codehilite .nd { color: #3c5d5d; font-weight: bold } /* Name.Decorator */ +.codehilite .ni { color: #800080 } /* Name.Entity */ +.codehilite .ne { color: #990000; font-weight: bold } /* Name.Exception */ +.codehilite .nf { color: #990000; font-weight: bold } /* Name.Function */ +.codehilite .nl { color: #990000; font-weight: bold } /* Name.Label */ +.codehilite .nn { color: #555555 } /* Name.Namespace */ +.codehilite .nt { color: #000080 } /* Name.Tag */ +.codehilite .nv { color: #008080 } /* Name.Variable */ +.codehilite .ow { color: #000000; font-weight: bold } /* Operator.Word */ +.codehilite .w { color: #bbbbbb } /* Text.Whitespace */ +.codehilite .mf { color: #009999 } /* Literal.Number.Float */ +.codehilite .mh { color: #009999 } /* Literal.Number.Hex */ +.codehilite .mi { color: #009999 } /* Literal.Number.Integer */ +.codehilite .mo { color: #009999 } /* Literal.Number.Oct */ +.codehilite .sb { color: #d01040 } /* Literal.String.Backtick */ +.codehilite .sc { color: #d01040 } /* Literal.String.Char */ +.codehilite .sd { color: #d01040 } /* Literal.String.Doc */ +.codehilite .s2 { color: #d01040 } /* Literal.String.Double */ +.codehilite .se { color: #d01040 } /* Literal.String.Escape */ +.codehilite .sh { color: #d01040 } /* Literal.String.Heredoc */ +.codehilite .si { color: #d01040 } /* Literal.String.Interpol */ +.codehilite .sx { color: #d01040 } /* Literal.String.Other */ +.codehilite .sr { color: #009926 } /* Literal.String.Regex */ +.codehilite .s1 { color: #d01040 } /* Literal.String.Single */ +.codehilite .ss { color: #990073 } /* Literal.String.Symbol */ +.codehilite .bp { color: #999999 } /* Name.Builtin.Pseudo */ +.codehilite .vc { color: #008080 } /* Name.Variable.Class */ +.codehilite .vg { color: #008080 } /* Name.Variable.Global */ +.codehilite .vi { color: #008080 } /* Name.Variable.Instance */ +.codehilite .il { color: #009999 } /* Literal.Number.Integer.Long */ diff --git a/index.html b/index.html index 58a03322..876c0480 100644 --- a/index.html +++ b/index.html @@ -212,20 +212,16 @@1 -2 -3 | git clone https://github.com/PaddlePaddle/PaddleSlim.git + |
1 | pip install paddleslim -i https://pypi.org/simple + |
range_table
函数),tokens中每个token的索引范围。token2arch
函数),根据搜索到的tokens列表产生模型结构。 以新增reset block为例说明如何构造自己的search space。自定义的search space不能和已有的search space同名。
-1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 | ### 引入搜索空间基类函数和search space的注册类函数 + |
操作信息字段之间以逗号分割。操作信息与延迟信息之间以制表符分割。
格式
-1 | op_type,flag_bias,flag_relu,n_in,c_in,h_in,w_in,c_out,groups,kernel,padding,stride,dilation\tlatency + |
字段解释
格式
-1 | op_type,n_in,c_in,h_in,w_in\tlatency + |
字段解释
格式
-1 | op_type,active_type,n_in,c_in,h_in,w_in\tlatency + |
字段解释
格式
-1 | op_type,n_in,c_in,h_in,w_in\tlatency + |
字段解释
格式
-1 | op_type,flag_global_pooling,n_in,c_in,h_in,w_in,kernel,padding,stride,ceil_mode,pool_type\tlatency + |
字段解释
格式
-1 | op_type,axis,n_in,c_in,h_in,w_in\tlatency + |
字段解释
一般情况下,模型参数量越多,结构越复杂,其性能越好,但运算量和资源消耗也越大。知识蒸馏 就是一种将大模型学习到的有用信息(Dark Knowledge)压缩进更小更快的模型,而获得可以匹敌大模型结果的方法。
在本示例中精度较高的大模型被称为teacher,精度稍逊但速度更快的小模型被称为student。
1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 -10 -11 | student_program = fluid.Program() + |
在定义好teacher_program
后,可以一并加载训练好的pretrained_model。
在teacher_program
内需要加上with fluid.unique_name.guard():
,保证teacher的变量命名不被student_program
影响,从而能够正确地加载预训练参数。
1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 -10 -11 -12 -13 -14 -15 -16 -17 -18 | teacher_program = fluid.Program() + |
定义好student_program
和teacher_program
后,我们需要从中两两对应地挑选出若干个特征图,留待后续为其添加知识蒸馏损失函数。
1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 -10 -11 -12 -13 -14 -15 -16 -17 -18 | # get all student variables + |
PaddlePaddle使用Program来描述计算图,为了同时计算student和teacher两个Program,这里需要将其两者合并(merge)为一个Program。
merge过程操作较多,具体细节请参考merge API文档。
-1 -2 | data_name_map = {'data': 'image'} + |
在添加蒸馏loss的过程中,可能还会引入部分变量(Variable),为了避免命名重复这里可以使用with fluid.name_scope("distill"):
为新引入的变量加一个命名作用域。
另外需要注意的是,merge过程为teacher_program
的变量统一加了名称前缀,默认是"teacher_"
, 这里在添加l2_loss
时也要为teacher的变量加上这个前缀。
1 -2 -3 -4 -5 -6 -7 -8 -9 | with fluid.program_guard(student_program, student_startup): + |
至此,我们就得到了用于蒸馏训练的student_program
,后面就可以使用一个普通program一样对其开始训练和评估。
请参考。
详细的搜索空间配置可以参考神经网络搜索API文档。 -
1 | config = [('MobileNetV2Space')] - |
config = [('MobileNetV2Space')] +
1 -2 -3 -4 -5 -6 -7 -8 -9 | from paddleslim.nas import SANAS + |
1 | archs = sa_nas.next_archs() + |
1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 | import paddle.fluid as fluid + |
1 -2 -3 -4 | from paddleslim.analysis import flops + |
1 | sa_nas.reward(score) + |
该示例使用了paddleslim.Pruner
工具类,用户接口使用介绍请参考:API文档
不同模型的参数命名不同,在剪裁前需要确定待裁卷积层的参数名称。可通过以下方法列出所有参数名:
-1 -2 | for param in program.global_block().all_parameters(): + |
在train.py
脚本中,提供了get_pruned_params
方法,根据用户设置的选项--model
确定要裁剪的参数。
通过以下命令启动裁剪任务:
-1 -2 | export CUDA_VISIBLE_DEVICES=0 + |
执行python train.py --help
查看更多选项。
请参考 量化API文档。
1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 -10 -11 -12 | quant_config = { + |
1 -2 -3 | val_program = quant_aware(val_program, place, quant_config, scope=None, for_test=True) + |
1 -2 -3 -4 -5 -6 -7 -8 | build_strategy = fluid.BuildStrategy() + |
1 -2 -3 -4 -5 | float_program, int8_program = convert(val_program, + |
1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 -10 -11 -12 -13 -14 -15 | fluid.io.save_inference_model( + |
以下将以 基于skip-gram的word2vector模型
为例来说明如何使用quant_embedding
接口。首先介绍 基于skip-gram的word2vector模型
的正常训练和测试流程。
以下是本例的简要目录结构及说明:
-1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 -10 | . + |
本例实现了skip-gram模式的word2vector模型。
同时推荐用户参考 IPython Notebook demo
全量数据集使用的是来自1 Billion Word Language Model Benchmark的(http://www.statmt.org/lm-benchmark) 的数据集.
-1 -2 -3 -4 | mkdir data + |
备用数据地址下载命令如下
-1 -2 -3 -4 | mkdir data + |
为了方便快速验证,我们也提供了经典的text8样例数据集,包含1700w个词。 下载命令如下
-1 -2 -3 -4 | mkdir data + |
以样例数据集为例进行预处理。全量数据集注意解压后以training-monolingual.tokenized.shuffled 目录为预处理目录,和样例数据集的text目录并列。
词典格式: 词<空格>词频。注意低频词用'UNK'表示
可以按格式自建词典,如果自建词典跳过第一步。 -
1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 -10 | the 1061396 + |
第一步根据英文语料生成词典,中文语料可以通过修改text_strip方法自定义处理方法。
-1 | python preprocess.py --build_dict --build_dict_corpus_dir data/text/ --dict_path data/test_build_dict + |
第二步根据词典将文本转成id, 同时进行downsample,按照概率过滤常见词, 同时生成word和id映射的文件,文件名为词典+"word_to_id"。
-1 | python preprocess.py --filter_corpus --dict_path data/test_build_dict --input_corpus_dir data/text --output_corpus_dir data/convert_text8 --min_count 5 --downsample 0.001 + |
具体的参数配置可运行
-1 | python train.py -h + |
单机多线程训练 -
1 | OPENBLAS_NUM_THREADS=1 CPU_NUM=5 python train.py --train_data_dir data/convert_text8 --dict_path data/test_build_dict --num_passes 10 --batch_size 100 --model_output_dir v1_cpu5_b100_lr1dir --base_lr 1.0 --print_batch 1000 --with_speed --is_sparse - |
OPENBLAS_NUM_THREADS=1 CPU_NUM=5 python train.py --train_data_dir data/convert_text8 --dict_path data/test_build_dict --num_passes 10 --batch_size 100 --model_output_dir v1_cpu5_b100_lr1dir --base_lr 1.0 --print_batch 1000 --with_speed --is_sparse +
本地单机模拟多机训练
-1 | sh cluster_train.sh + |
本示例中按照单机多线程训练的命令进行训练,训练完毕后,可看到在当前文件夹下保存模型的路径为: v1_cpu5_b100_lr1dir
, 运行 ls v1_cpu5_b100_lr1dir
可看到该文件夹下保存了训练的10个epoch的模型文件。
-
1 | pass-0 pass-1 pass-2 pass-3 pass-4 pass-5 pass-6 pass-7 pass-8 pass-9 - |
pass-0 pass-1 pass-2 pass-3 pass-4 pass-5 pass-6 pass-7 pass-8 pass-9 +
测试集下载命令如下
-1 -2 -3 -4 | #全量数据集测试集 + |
预测命令,注意词典名称需要加后缀"word_to_id", 此文件是预处理阶段生成的。 -
1 | python infer.py --infer_epoch --test_dir data/test_mid_dir --dict_path data/test_build_dict_word_to_id_ --batch_size 20000 --model_dir v1_cpu5_b100_lr1dir/ --start_index 0 --last_index 9 + |
1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 | ('start index: ', 0, ' last_index:', 9) + |
基于skip-gram的word2vector模型
#量化配置为: -
1 -2 -3 -4 | config = { + |
运行命令为:
-1 | python infer.py --infer_epoch --test_dir data/test_mid_dir --dict_path data/test_build_dict_word_to_id_ --batch_size 20000 --model_dir v1_cpu5_b100_lr1dir/ --start_index 0 --last_index 9 --emb_quant True + |
运行输出为:
-1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 | ('start index: ', 0, ' last_index:', 9) + |
量化后的模型保存在./output_quant
中,可看到量化后的参数'emb.int8'
的大小为3.9M, 在./v1_cpu5_b100_lr1dir
中可看到量化前的参数'emb'
的大小为16M。
在当前文件夹下创建'pretrain'
文件夹,将mobilenetv1
模型在该文件夹下解压,解压后的目录为pretrain/MobileNetV1_pretrained
通过运行以下命令可将模型转化为离线量化接口可用的模型: -
1 | python export_model.py --model "MobileNet" --pretrained_model ./pretrain/MobileNetV1_pretrained --data imagenet + |
inference_model/MobileNet/
文件夹下,可看到该文件夹下有'model'
, 'weights'
两个文件。
接下来对导出的模型文件进行离线量化,离线量化的脚本为quant_post.py,脚本中使用接口paddleslim.quant.quant_post
对模型进行离线量化。运行命令为:
-
1 | python quant_post.py --model_path ./inference_model/MobileNet --save_path ./quant_model_train/MobileNet --model_filename model --params_filename weights - |
python quant_post.py --model_path ./inference_model/MobileNet --save_path ./quant_model_train/MobileNet --model_filename model --params_filename weights +
model_path
: 需要量化的模型坐在的文件夹save_path
: 量化后的模型保存的路径使用eval.py脚本对量化前后的模型进行测试,得到模型的分类精度进行对比。
首先测试量化前的模型的精度,运行以下命令: -
1 | python eval.py --model_path ./inference_model/MobileNet --model_name model --params_name weights + |
1 | top1_acc/top5_acc= [0.70913923 0.89548034] - |
top1_acc/top5_acc= [0.70913923 0.89548034] +
使用以下命令测试离线量化后的模型的精度:
-1 | python eval.py --model_path ./quant_model_train/MobileNet + |
精度输出为 -
1 | top1_acc/top5_acc= [0.70141864 0.89086477] + |
mobilenet
在imagenet
上的分类模型进行离线量化后 top1
精度损失为0.77%
, top5
精度损失为0.46%
.
diff --git a/tutorials/sensitivity_demo/index.html b/tutorials/sensitivity_demo/index.html
index 4aafeebd..3e5fc373 100644
--- a/tutorials/sensitivity_demo/index.html
+++ b/tutorials/sensitivity_demo/index.html
@@ -177,11 +177,9 @@
在路径PaddleSlim/demo/sensitive
下执行以下代码运行示例:
1 -2 | export CUDA_VISIBLE_DEVICES=0 + |
通过python train.py --help
查看更多选项。
调用paddleslim.prune.sensitivity
接口计算敏感度。敏感度信息会追加到sensitivities_file
选项所指定的文件中,如果需要重新计算敏感度,需要先删除sensitivities_file
文件。
如果模型评估速度较慢,可以通过多进程的方式加速敏感度计算过程。比如在进程1中设置pruned_ratios=[0.1, 0.2, 0.3, 0.4]
,并将敏感度信息存放在文件sensitivities_0.data
中,然后在进程2中设置pruned_ratios=[0.5, 0.6, 0.7]
,并将敏感度信息存储在文件sensitivities_1.data
中。这样每个进程只会计算指定剪切率下的敏感度信息。多进程可以运行在单机多卡,或多机多卡。
代码如下:
-1 -2 -3 -4 -5 -6 -7 -8 | # 进程1 + |
1 -2 -3 -4 -5 -6 -7 -8 | # 进程2 + |
如果用户通过上一节多进程的方式生成了多个存储敏感度信息的文件,可以通过paddleslim.prune.merge_sensitive
将其合并,合并后的敏感度信息存储在一个dict
中。代码如下:
1 | sens = merge_sensitive(["./sensitivities_0.data", "./sensitivities_1.data"]) + |
调用paddleslim.prune.get_ratios_by_loss
接口计算一组剪裁率。
1 | ratios = get_ratios_by_loss(sens, 0.01) + |
其中,0.01
为一个阈值,对于任意卷积层,其剪裁率为使精度损失低于阈值0.01
的最大剪裁率。
用户在计算出一组剪裁率之后可以通过接口paddleslim.prune.Pruner
剪裁网络,并用接口paddleslim.analysis.flops
计算FLOPs
。如果FLOPs
不满足要求,调整阈值重新计算出一组剪裁率。