first commit
Some checks are pending
Build/Publish Develop Docs / deploy (push) Waiting to run

This commit is contained in:
2025-07-02 08:57:16 +03:00
commit 56532cc9a9
1901 changed files with 457695 additions and 0 deletions

View File

@@ -0,0 +1,60 @@
# PP-OCR模型量化
复杂的模型有利于提高模型的性能,但也导致模型中存在一定冗余,模型量化将全精度缩减到定点数减少这种冗余,达到减少模型计算复杂度,提高模型推理性能的目的。
模型量化可以在基本不损失模型的精度的情况下将FP32精度的模型参数转换为Int8精度减小模型参数大小并加速计算使用量化后的模型在移动端等部署时更具备速度优势。
本教程将介绍如何使用飞桨模型压缩库PaddleSlim做PaddleOCR模型的压缩。
[PaddleSlim](https://github.com/PaddlePaddle/PaddleSlim) 集成了模型剪枝、量化(包括量化训练和离线量化)、蒸馏和神经网络搜索等多种业界常用且领先的模型压缩功能,如果您感兴趣,可以关注并了解。
在开始本教程之前,建议先了解[PaddleOCR模型的训练方法](../../../doc/doc_ch/training.md)以及[PaddleSlim](https://paddleslim.readthedocs.io/zh_CN/latest/index.html)
## 快速开始
量化多适用于轻量模型在移动端的部署,当训练出一个模型后,如果希望进一步的压缩模型大小并加速预测,可使用量化的方法压缩模型。
模型量化主要包括五个步骤:
1. 安装 PaddleSlim
2. 准备训练好的模型
3. 量化训练
4. 导出量化推理模型
5. 量化模型预测部署
### 1. 安装PaddleSlim
```bash
pip3 install paddleslim==2.3.2
```
### 2. 准备训练好的模型
PaddleOCR提供了一系列训练好的[模型](../../../doc/doc_ch/models_list.md),如果待量化的模型不在列表中,需要按照[常规训练](../../../doc/doc_ch/quickstart.md)方法得到训练好的模型。
### 3. 量化训练
量化训练包括离线量化训练和在线量化训练,在线量化训练效果更好,需加载预训练模型,在定义好量化策略后即可对模型进行量化。
量化训练的代码位于slim/quantization/quant.py 中比如训练检测模型以PPOCRv3检测模型为例训练指令如下
```
# 下载检测预训练模型:
wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar
tar xf ch_PP-OCRv3_det_distill_train.tar
python deploy/slim/quantization/quant.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.pretrained_model='./ch_PP-OCRv3_det_distill_train/best_accuracy' Global.save_model_dir=./output/quant_model_distill/
```
如果要训练识别模型的量化,修改配置文件和加载的模型参数即可。
### 4. 导出模型
在得到量化训练保存的模型后我们可以将其导出为inference_model用于预测部署
```bash
python deploy/slim/quantization/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.checkpoints=output/quant_model/best_accuracy Global.save_inference_dir=./output/quant_inference_model
```
### 5. 量化模型部署
上述步骤导出的量化模型参数精度仍然是FP32但是参数的数值范围是int8导出的模型可以通过PaddleLite的opt模型转换工具完成模型转换。
量化模型移动端部署的可参考 [移动端模型部署](../../lite/readme.md)
备注量化训练后的模型参数是float32类型转inference model预测时相对不量化无加速效果原因是量化后模型结构之间存在量化和反量化算子如果要使用量化模型部署建议使用TensorRT并设置precision为INT8加速量化模型的预测时间。

View File

@@ -0,0 +1,65 @@
# PP-OCR Models Quantization
Generally, a more complex model would achieve better performance in the task, but it also leads to some redundancy in the model.
Quantization is a technique that reduces this redundancy by reducing the full precision data to a fixed number,
so as to reduce model calculation complexity and improve model inference performance.
This example uses PaddleSlim provided [APIs of Quantization](https://github.com/PaddlePaddle/PaddleSlim/blob/develop/docs/zh_cn/api_cn/dygraph/quanter/qat.rst) to compress the OCR model.
It is recommended that you could understand following pages before reading this example
- [The training strategy of OCR model](../../../doc/doc_en/quickstart_en.md)
- [PaddleSlim Document](https://github.com/PaddlePaddle/PaddleSlim/blob/develop/docs/zh_cn/api_cn/dygraph/quanter/qat.rst)
## Quick Start
Quantization is mostly suitable for the deployment of lightweight models on mobile terminals.
After training, if you want to further compress the model size and accelerate the prediction, you can use quantization methods to compress the model according to the following steps.
1. Install PaddleSlim
2. Prepare trained model
3. Quantization-Aware Training
4. Export inference model
5. Deploy quantization inference model
### 1. Install PaddleSlim
```bash
pip3 install paddleslim==2.3.2
```
### 2. Download Pre-trained Model
PaddleOCR provides a series of pre-trained [models](../../../doc/doc_en/models_list_en.md).
If the model to be quantified is not in the list, you need to follow the [Regular Training](../../../doc/doc_en/quickstart_en.md) method to get the trained model.
### 3. Quant-Aware Training
Quantization training includes offline quantization training and online quantization training.
Online quantization training is more effective. It is necessary to load the pre-trained model.
After the quantization strategy is defined, the model can be quantified.
The code for quantization training is located in `slim/quantization/quant.py`. For example, the training instructions of slim PPOCRv3 detection model are as follows:
```
# download provided model
wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar
tar xf ch_PP-OCRv3_det_distill_train.tar
python deploy/slim/quantization/quant.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.pretrained_model='./ch_PP-OCRv3_det_distill_train/best_accuracy' Global.save_model_dir=./output/quant_model_distill/
```
If you want to quantify the text recognition model, you can modify the configuration file and loaded model parameters.
### 4. Export inference model
Once we got the model after pruning and fine-tuning, we can export it as an inference model for the deployment of predictive tasks:
```bash
python deploy/slim/quantization/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.checkpoints=output/quant_model/best_accuracy Global.save_inference_dir=./output/quant_inference_model
```
### 5. Deploy
The numerical range of the quantized model parameters derived from the above steps is still FP32, but the numerical range of the parameters is int8.
The derived model can be converted through the `opt tool` of PaddleLite.
For quantitative model deployment, please refer to [Mobile terminal model deployment](../../lite/readme.md)

View File

@@ -0,0 +1,189 @@
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import sys
__dir__ = os.path.dirname(os.path.abspath(__file__))
sys.path.append(__dir__)
sys.path.insert(0, os.path.abspath(os.path.join(__dir__, "..", "..", "..")))
sys.path.insert(0, os.path.abspath(os.path.join(__dir__, "..", "..", "..", "tools")))
import argparse
import paddle
from paddle.jit import to_static
from ppocr.modeling.architectures import build_model
from ppocr.postprocess import build_post_process
from ppocr.utils.save_load import load_model
from ppocr.utils.logging import get_logger
from tools.program import load_config, merge_config, ArgsParser
from ppocr.metrics import build_metric
import tools.program as program
from paddleslim.dygraph.quant import QAT
from ppocr.data import build_dataloader, set_signal_handlers
from ppocr.utils.export_model import export_single_model
def main():
############################################################################################################
# 1. quantization configs
############################################################################################################
quant_config = {
# weight preprocess type, default is None and no preprocessing is performed.
"weight_preprocess_type": None,
# activation preprocess type, default is None and no preprocessing is performed.
"activation_preprocess_type": None,
# weight quantize type, default is 'channel_wise_abs_max'
"weight_quantize_type": "channel_wise_abs_max",
# activation quantize type, default is 'moving_average_abs_max'
"activation_quantize_type": "moving_average_abs_max",
# weight quantize bit num, default is 8
"weight_bits": 8,
# activation quantize bit num, default is 8
"activation_bits": 8,
# data type after quantization, such as 'uint8', 'int8', etc. default is 'int8'
"dtype": "int8",
# window size for 'range_abs_max' quantization. default is 10000
"window_size": 10000,
# The decay coefficient of moving average, default is 0.9
"moving_rate": 0.9,
# for dygraph quantization, layers of type in quantizable_layer_type will be quantized
"quantizable_layer_type": ["Conv2D", "Linear"],
}
FLAGS = ArgsParser().parse_args()
config = load_config(FLAGS.config)
config = merge_config(config, FLAGS.opt)
logger = get_logger()
# build post process
post_process_class = build_post_process(config["PostProcess"], config["Global"])
# build model
if hasattr(post_process_class, "character"):
char_num = len(getattr(post_process_class, "character"))
if config["Architecture"]["algorithm"] in [
"Distillation",
]: # distillation model
for key in config["Architecture"]["Models"]:
if (
config["Architecture"]["Models"][key]["Head"]["name"] == "MultiHead"
): # for multi head
if config["PostProcess"]["name"] == "DistillationSARLabelDecode":
char_num = char_num - 2
# update SARLoss params
assert (
list(config["Loss"]["loss_config_list"][-1].keys())[0]
== "DistillationSARLoss"
)
config["Loss"]["loss_config_list"][-1]["DistillationSARLoss"][
"ignore_index"
] = (char_num + 1)
out_channels_list = {}
out_channels_list["CTCLabelDecode"] = char_num
out_channels_list["SARLabelDecode"] = char_num + 2
config["Architecture"]["Models"][key]["Head"][
"out_channels_list"
] = out_channels_list
else:
config["Architecture"]["Models"][key]["Head"][
"out_channels"
] = char_num
elif config["Architecture"]["Head"]["name"] == "MultiHead": # for multi head
if config["PostProcess"]["name"] == "SARLabelDecode":
char_num = char_num - 2
# update SARLoss params
assert list(config["Loss"]["loss_config_list"][1].keys())[0] == "SARLoss"
if config["Loss"]["loss_config_list"][1]["SARLoss"] is None:
config["Loss"]["loss_config_list"][1]["SARLoss"] = {
"ignore_index": char_num + 1
}
else:
config["Loss"]["loss_config_list"][1]["SARLoss"]["ignore_index"] = (
char_num + 1
)
out_channels_list = {}
out_channels_list["CTCLabelDecode"] = char_num
out_channels_list["SARLabelDecode"] = char_num + 2
config["Architecture"]["Head"]["out_channels_list"] = out_channels_list
else: # base rec model
config["Architecture"]["Head"]["out_channels"] = char_num
if config["PostProcess"]["name"] == "SARLabelDecode": # for SAR model
config["Loss"]["ignore_index"] = char_num - 1
model = build_model(config["Architecture"])
# get QAT model
quanter = QAT(config=quant_config)
quanter.quantize(model)
load_model(config, model)
# build metric
eval_class = build_metric(config["Metric"])
# build dataloader
set_signal_handlers()
valid_dataloader = build_dataloader(config, "Eval", device, logger)
use_srn = config["Architecture"]["algorithm"] == "SRN"
model_type = config["Architecture"].get("model_type", None)
# start eval
metric = program.eval(
model, valid_dataloader, post_process_class, eval_class, model_type, use_srn
)
model.eval()
logger.info("metric eval ***************")
for k, v in metric.items():
logger.info("{}:{}".format(k, v))
save_path = config["Global"]["save_inference_dir"]
arch_config = config["Architecture"]
if (
arch_config["algorithm"] == "SVTR"
and arch_config["Head"]["name"] != "MultiHead"
):
input_shape = config["Eval"]["dataset"]["transforms"][-2]["SVTRRecResizeImg"][
"image_shape"
]
else:
input_shape = None
if arch_config["algorithm"] in [
"Distillation",
]: # distillation model
archs = list(arch_config["Models"].values())
for idx, name in enumerate(model.model_name_list):
sub_model_save_path = os.path.join(save_path, name, "inference")
export_single_model(
model.model_list[idx],
archs[idx],
sub_model_save_path,
logger,
input_shape,
quanter,
)
else:
save_path = os.path.join(save_path, "inference")
export_single_model(model, arch_config, save_path, logger, input_shape, quanter)
if __name__ == "__main__":
config, device, logger, vdl_writer = program.preprocess()
main()

226
deploy/slim/quantization/quant.py Executable file
View File

@@ -0,0 +1,226 @@
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import os
import sys
__dir__ = os.path.dirname(os.path.abspath(__file__))
sys.path.append(__dir__)
sys.path.append(os.path.abspath(os.path.join(__dir__, "..", "..", "..")))
sys.path.append(os.path.abspath(os.path.join(__dir__, "..", "..", "..", "tools")))
import yaml
import paddle
import paddle.distributed as dist
paddle.seed(2)
from ppocr.data import build_dataloader, set_signal_handlers
from ppocr.modeling.architectures import build_model
from ppocr.losses import build_loss
from ppocr.optimizer import build_optimizer
from ppocr.postprocess import build_post_process
from ppocr.metrics import build_metric
from ppocr.utils.save_load import load_model
import tools.program as program
from paddleslim.dygraph.quant import QAT
dist.get_world_size()
class PACT(paddle.nn.Layer):
def __init__(self):
super(PACT, self).__init__()
alpha_attr = paddle.ParamAttr(
name=self.full_name() + ".pact",
initializer=paddle.nn.initializer.Constant(value=20),
learning_rate=1.0,
regularizer=paddle.regularizer.L2Decay(2e-5),
)
self.alpha = self.create_parameter(shape=[1], attr=alpha_attr, dtype="float32")
def forward(self, x):
out_left = paddle.nn.functional.relu(x - self.alpha)
out_right = paddle.nn.functional.relu(-self.alpha - x)
x = x - out_left + out_right
return x
quant_config = {
# weight preprocess type, default is None and no preprocessing is performed.
"weight_preprocess_type": None,
# activation preprocess type, default is None and no preprocessing is performed.
"activation_preprocess_type": None,
# weight quantize type, default is 'channel_wise_abs_max'
"weight_quantize_type": "channel_wise_abs_max",
# activation quantize type, default is 'moving_average_abs_max'
"activation_quantize_type": "moving_average_abs_max",
# weight quantize bit num, default is 8
"weight_bits": 8,
# activation quantize bit num, default is 8
"activation_bits": 8,
# data type after quantization, such as 'uint8', 'int8', etc. default is 'int8'
"dtype": "int8",
# window size for 'range_abs_max' quantization. default is 10000
"window_size": 10000,
# The decay coefficient of moving average, default is 0.9
"moving_rate": 0.9,
# for dygraph quantization, layers of type in quantizable_layer_type will be quantized
"quantizable_layer_type": ["Conv2D", "Linear"],
}
def main(config, device, logger, vdl_writer):
# init dist environment
if config["Global"]["distributed"]:
dist.init_parallel_env()
global_config = config["Global"]
# build dataloader
set_signal_handlers()
train_dataloader = build_dataloader(config, "Train", device, logger)
if config["Eval"]:
valid_dataloader = build_dataloader(config, "Eval", device, logger)
else:
valid_dataloader = None
# build post process
post_process_class = build_post_process(config["PostProcess"], global_config)
# build model
# for rec algorithm
if hasattr(post_process_class, "character"):
char_num = len(getattr(post_process_class, "character"))
if config["Architecture"]["algorithm"] in [
"Distillation",
]: # distillation model
for key in config["Architecture"]["Models"]:
if (
config["Architecture"]["Models"][key]["Head"]["name"] == "MultiHead"
): # for multi head
if config["PostProcess"]["name"] == "DistillationSARLabelDecode":
char_num = char_num - 2
# update SARLoss params
assert (
list(config["Loss"]["loss_config_list"][-1].keys())[0]
== "DistillationSARLoss"
)
config["Loss"]["loss_config_list"][-1]["DistillationSARLoss"][
"ignore_index"
] = (char_num + 1)
out_channels_list = {}
out_channels_list["CTCLabelDecode"] = char_num
out_channels_list["SARLabelDecode"] = char_num + 2
config["Architecture"]["Models"][key]["Head"][
"out_channels_list"
] = out_channels_list
else:
config["Architecture"]["Models"][key]["Head"][
"out_channels"
] = char_num
elif config["Architecture"]["Head"]["name"] == "MultiHead": # for multi head
if config["PostProcess"]["name"] == "SARLabelDecode":
char_num = char_num - 2
# update SARLoss params
assert list(config["Loss"]["loss_config_list"][1].keys())[0] == "SARLoss"
if config["Loss"]["loss_config_list"][1]["SARLoss"] is None:
config["Loss"]["loss_config_list"][1]["SARLoss"] = {
"ignore_index": char_num + 1
}
else:
config["Loss"]["loss_config_list"][1]["SARLoss"]["ignore_index"] = (
char_num + 1
)
out_channels_list = {}
out_channels_list["CTCLabelDecode"] = char_num
out_channels_list["SARLabelDecode"] = char_num + 2
config["Architecture"]["Head"]["out_channels_list"] = out_channels_list
else: # base rec model
config["Architecture"]["Head"]["out_channels"] = char_num
if config["PostProcess"]["name"] == "SARLabelDecode": # for SAR model
config["Loss"]["ignore_index"] = char_num - 1
model = build_model(config["Architecture"])
pre_best_model_dict = dict()
# load fp32 model to begin quantization
pre_best_model_dict = load_model(
config, model, None, config["Architecture"]["model_type"]
)
freeze_params = False
if config["Architecture"]["algorithm"] in ["Distillation"]:
for key in config["Architecture"]["Models"]:
freeze_params = freeze_params or config["Architecture"]["Models"][key].get(
"freeze_params", False
)
act = None if freeze_params else PACT
quanter = QAT(config=quant_config, act_preprocess=act)
quanter.quantize(model)
if config["Global"]["distributed"]:
model = paddle.DataParallel(model)
# build loss
loss_class = build_loss(config["Loss"])
# build optim
optimizer, lr_scheduler = build_optimizer(
config["Optimizer"],
epochs=config["Global"]["epoch_num"],
step_each_epoch=len(train_dataloader),
model=model,
)
# resume PACT training process
pre_best_model_dict = load_model(
config, model, optimizer, config["Architecture"]["model_type"]
)
# build metric
eval_class = build_metric(config["Metric"])
logger.info(
"train dataloader has {} iters, valid dataloader has {} iters".format(
len(train_dataloader), len(valid_dataloader)
)
)
# start train
program.train(
config,
train_dataloader,
valid_dataloader,
device,
model,
loss_class,
optimizer,
lr_scheduler,
post_process_class,
eval_class,
pre_best_model_dict,
logger,
vdl_writer,
)
if __name__ == "__main__":
config, device, logger, vdl_writer = program.preprocess(is_train=True)
main(config, device, logger, vdl_writer)

View File

@@ -0,0 +1,172 @@
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import os
import sys
__dir__ = os.path.dirname(os.path.abspath(__file__))
sys.path.append(__dir__)
sys.path.append(os.path.abspath(os.path.join(__dir__, "..", "..", "..")))
sys.path.append(os.path.abspath(os.path.join(__dir__, "..", "..", "..", "tools")))
import yaml
import paddle
import paddle.distributed as dist
paddle.seed(2)
from ppocr.data import build_dataloader, set_signal_handlers
from ppocr.modeling.architectures import build_model
from ppocr.losses import build_loss
from ppocr.optimizer import build_optimizer
from ppocr.postprocess import build_post_process
from ppocr.metrics import build_metric
from ppocr.utils.save_load import load_model
import tools.program as program
import paddleslim
from paddleslim.dygraph.quant import QAT
import numpy as np
dist.get_world_size()
class PACT(paddle.nn.Layer):
def __init__(self):
super(PACT, self).__init__()
alpha_attr = paddle.ParamAttr(
name=self.full_name() + ".pact",
initializer=paddle.nn.initializer.Constant(value=20),
learning_rate=1.0,
regularizer=paddle.regularizer.L2Decay(2e-5),
)
self.alpha = self.create_parameter(shape=[1], attr=alpha_attr, dtype="float32")
def forward(self, x):
out_left = paddle.nn.functional.relu(x - self.alpha)
out_right = paddle.nn.functional.relu(-self.alpha - x)
x = x - out_left + out_right
return x
quant_config = {
# weight preprocess type, default is None and no preprocessing is performed.
"weight_preprocess_type": None,
# activation preprocess type, default is None and no preprocessing is performed.
"activation_preprocess_type": None,
# weight quantize type, default is 'channel_wise_abs_max'
"weight_quantize_type": "channel_wise_abs_max",
# activation quantize type, default is 'moving_average_abs_max'
"activation_quantize_type": "moving_average_abs_max",
# weight quantize bit num, default is 8
"weight_bits": 8,
# activation quantize bit num, default is 8
"activation_bits": 8,
# data type after quantization, such as 'uint8', 'int8', etc. default is 'int8'
"dtype": "int8",
# window size for 'range_abs_max' quantization. default is 10000
"window_size": 10000,
# The decay coefficient of moving average, default is 0.9
"moving_rate": 0.9,
# for dygraph quantization, layers of type in quantizable_layer_type will be quantized
"quantizable_layer_type": ["Conv2D", "Linear"],
}
def sample_generator(loader):
def __reader__():
for indx, data in enumerate(loader):
images = np.array(data[0])
yield images
return __reader__
def sample_generator_layoutxlm_ser(loader):
def __reader__():
for indx, data in enumerate(loader):
input_ids = np.array(data[0])
bbox = np.array(data[1])
attention_mask = np.array(data[2])
token_type_ids = np.array(data[3])
images = np.array(data[4])
yield [input_ids, bbox, attention_mask, token_type_ids, images]
return __reader__
def main(config, device, logger, vdl_writer):
# init dist environment
if config["Global"]["distributed"]:
dist.init_parallel_env()
global_config = config["Global"]
# build dataloader
set_signal_handlers()
config["Train"]["loader"]["num_workers"] = 0
is_layoutxlm_ser = (
config["Architecture"]["model_type"] == "kie"
and config["Architecture"]["Backbone"]["name"] == "LayoutXLMForSer"
)
train_dataloader = build_dataloader(config, "Train", device, logger)
if config["Eval"]:
config["Eval"]["loader"]["num_workers"] = 0
valid_dataloader = build_dataloader(config, "Eval", device, logger)
if is_layoutxlm_ser:
train_dataloader = valid_dataloader
else:
valid_dataloader = None
paddle.enable_static()
exe = paddle.static.Executor(device)
if "inference_model" in global_config.keys(): # , 'inference_model'):
inference_model_dir = global_config["inference_model"]
else:
inference_model_dir = os.path.dirname(global_config["pretrained_model"])
if not (
os.path.exists(os.path.join(inference_model_dir, "inference.pdmodel"))
and os.path.exists(os.path.join(inference_model_dir, "inference.pdiparams"))
):
raise ValueError(
"Please set inference model dir in Global.inference_model or Global.pretrained_model for post-quantization"
)
if is_layoutxlm_ser:
generator = sample_generator_layoutxlm_ser(train_dataloader)
else:
generator = sample_generator(train_dataloader)
paddleslim.quant.quant_post_static(
executor=exe,
model_dir=inference_model_dir,
model_filename="inference.pdmodel",
params_filename="inference.pdiparams",
quantize_model_path=global_config["save_inference_dir"],
sample_generator=generator,
save_model_filename="inference.pdmodel",
save_params_filename="inference.pdiparams",
batch_size=1,
batch_nums=None,
)
if __name__ == "__main__":
config, device, logger, vdl_writer = program.preprocess(is_train=True)
main(config, device, logger, vdl_writer)