PaddleOCR TIPC Linux 端补充训练功能测试完全指南:覆盖蒸馏、PACT 量化、FPGM 裁剪与自定义 OP 的训练链路验证
【免费下载链接】PaddleOCRTurn any PDF or image document into structured data for your AI. A powerful, lightweight OCR toolkit that bridges the gap between images/PDFs and LLMs. Supports 100+ languages.项目地址: https://gitcode.com/GitHub_Trending/pa/PaddleOCR
导读
本文面向在 PaddleOCR 仓库中需要快速验证"训练到预测"全流程是否走通的开发者,系统讲解 TIPC(Test Infrastructure for PaddlePaddle,飞桨训练预测一体化测试)在 Linux 端的补充训练功能测试。它以 test_train_python.sh 为唯一主程序,通过参数化配置文件驱动基于 Python 的模型训练、评估,并额外覆盖带共享权重的模型结构(Siamese/蒸馏)、自定义 OP(自定义 ReLU)、PACT 量化训练与FPGM 裁剪训练等基础训练链条之外的进阶场景。读完本文,你将掌握补充测试的两种运行模式、配置文件的字段语义、量化与裁剪的调用方式、多机多卡配置方法,以及背后 train.py 与 slim 组件的源码级工作原理。
一、补充训练测试的定位与测试链条
TIPC 的 Linux 端基础训练预测功能测试用于验证基于 Python 的模型训练、评估等基本功能;而补充训练功能测试(即本目录 test_tipc/supplementary 所承载的内容)则面向更复杂的训练形态。原文档明确指出,其测试链条主要覆盖两类内容:
- 带共享权重、自定义 OP 的模型正常训练流程——例如 Siamese 双塔共享结构、通过 JIT 编译加载的自定义 ReLU 算子;
- slim 相关功能训练流程——包括 PACT 量化感知训练(QAT)与 FPGM 滤波器裁剪。
测试链条如上图所示:从配置文件解析训练参数 → 按模式生成具体训练命令 → 执行训练并记录状态 → 将每条命令的成功/失败状态写入结果日志。整个链条通过 common_func.sh 提供的解析与状态检查函数串联,与仓库根目录的test_tipc体系(如 test_train_inference_python.sh)保持一致的设计风格,但针对补充训练场景单独维护了一套配置文件与示例模型(CIFAR-100 分类任务上的 MobileNetV3 系列)。
二、环境与依赖安装
补充训练测试的运行环境要求如下:
- PaddlePaddle >= 2.2:量化与裁剪依赖
paddleslim,其 API 形态(QAT、FPGMFilterPruner)与 Paddle 2.2+ 的动态图接口匹配; - 其他依赖:目录内置了一份最小依赖清单 requirements.txt,内容为:
paddleslim==2.2.1安装命令与仓库其余模块一致:
pip3 install -r requirements.txt由于补充测试会 JIT 编译自定义 OP(见下文),机器还需具备可用的 C++ 编译工具链与 CUDA 环境(若使用 GPU 训练)。注意,示例训练脚本 train.py 在导入阶段就会调用paddle.utils.cpp_extension.load编译custom_relu_op,因此编译环境是运行前置条件,而非可选优化。
三、两种运行模式:lite 快速验证与 whole 全量验证
test_train_python.sh内置两种运行模式,二者的差异体现在配置文件对不同字段给出了按模式区分的取值:
| 模式 | 配置写法 | 目的 | 数据规模 | epoch(以默认配置为例) |
|---|---|---|---|---|
lite_train_lite_infer | lite_train_lite_infer=2 | 使用少量数据训练,快速验证"训练→预测"流程走通,不验证精度和速度 | 小 | 2 |
whole_train_whole_infer | whole_train_whole_infer=1000 | 使用全量数据训练,验证模型最终训练精度 | 全量 | 1000 |
两种模式的启动命令分别为:
bash test_tipc/test_train_python.sh ./test_tipc/train_infer_python.txt 'lite_train_lite_infer' bash test_tipc/test_train_python.sh ./test_tipc/train_infer_python.txt 'whole_train_whole_infer'两个位置参数的含义:
$1:训练参数配置文件路径(如 train_infer_python.txt);$2:运行模式,脚本仅在MODE为lite_train_lite_infer或whole_train_whole_infer时才进入训练分支(见 test_train_python.sh)。
从脚本实现看,whole_train_whole_infer模式并不额外下载数据,而是完全复用同一份示例数据(CIFAR-100),区别仅在 epoch 与批大小等超参——这正是"快速走通流程"与"验证最终精度"的分工。
四、训练配置文件的结构与解析机制
补充训练的配置文件采用"字段:取值"与"字段:模式=取值"两种语法,脚本会读取配置文件前 51 行(awk 'NR==1, NR==51{print}'),并借助 common_func.sh 中的解析函数逐行提取。以 train_infer_python.txt 为例:
===========================train_params=========================== model_name:ch_PPOCRv2_det python:python3.7 gpu_list:0|0,1 use_gpu:True|True AMP.use_amp:True|False epoch:lite_train_lite_infer=2|whole_train_whole_infer=1000 save_model_dir:./output/ TRAIN.batch_size:lite_train_lite_infer=1280|whole_train_whole_infer=1280 pretrained_model:null checkpoints:null use_custom_relu:False|True model_type:cls|cls_distill|cls_distill_multiopt MODEL.siamese:False|True norm_train:train.py -c mv3_large_x0_5.yml -o quant_train:False prune_train:False各字段语义与脚本中的对应关系如下:
| 行号(从 1 计数) | 字段 | 含义 | 脚本解析函数 |
|---|---|---|---|
| 2 | model_name | 测试的模型名标识 | func_parser_value |
| 3 | python | 使用的 Python 解释器 | func_parser_value |
| 4 | gpu_list | GPU 列表;0为单卡、0,1为多卡、xx.xx.xx.xx;0,1为多机多卡 | func_parser_value |
| 5 | use_gpu | 是否使用 GPU,按索引与gpu_list一一对应 | func_parser_key/value |
| 6 | AMP.use_amp | 是否开启自动混合精度,amp时会注入AMP.use_amp=True | func_parser_key/value |
| 7 | epoch | 按模式取 epoch 数 | func_parser_params |
| 8 | save_model_dir | 模型保存目录 | func_parser_key |
| 9 | TRAIN.batch_size | 按模式取批大小 | func_parser_params |
| 10 | pretrained_model | 预训练模型路径,null表示不加载 | func_parser_value |
| 11 | checkpoints | 断点续训路径,null表示不加载 | func_parser_value |
| 12 | use_custom_relu | 是否使用自定义 ReLU OP,False/True二值遍历 | func_parser_value |
| 13 | model_type | 模型形态:cls/cls_distill/cls_distill_multiopt | func_parser_value |
| 14 | MODEL.siamese | 是否使用 Siamese 共享权重结构 | func_parser_value |
| 15 | norm_train | 实际训练命令模板,即train.py -c mv3_large_x0_5.yml -o | func_parser_value |
| 16 | quant_train | 是否量化训练(PACT QAT) | 透传至训练脚本 |
| 17 | prune_train | 是否裁剪训练(FPGM) | 透传至训练脚本 |
脚本按for gpu → for autocast → for custom_op → for model_type → for share_conv的五重循环对配置中的|分隔值做笛卡尔积遍历,每条组合通过func_set_params拼接出完整命令行,再经eval执行,最后调用status_check记录状态(见 test_train_python.sh 与 common_func.sh)。
需要说明的是,该配置模板的model_name沿用了ch_PPOCRv2_det命名,而实际训练的模型是 CIFAR-100 分类任务上的MobileNetV3_large_x0_5(由 mv3_large_x0_5.yml 定义)。补充测试的重点在于验证训练链路本身,而非复现某个具体 OCR 模型的精度。
五、普通训练测试与命令拼接细节
执行普通训练测试即运行上文的lite_train_lite_infer或whole_train_whole_infer命令。以lite_train_lite_infer为例,脚本最终会生成类似如下的训练命令(对应原文档中的成功日志示例):
python3.7 train.py -c mv3_large_x0_5.yml -o use_gpu=True epoch=2 AMP.use_amp=True TRAIN.batch_size=1280 use_custom_relu=False model_type=cls MODEL.siamese=False从 test_train_python.sh 可以看到命令的三档组装规则:
- CPU 或单 GPU(
gpu长度 ≤ 2):直接执行python train.py ...; - 单机多卡(
ips为空、gpu为0,1):python -m paddle.distributed.launch --gpus=${gpu} train.py ...; - 多机多卡:
python -m paddle.distributed.launch --ips=${ips} --gpus=${gpu} train.py ...。
而train.py的入口则依据model_type分发到三个训练实现(train.py):
cls→train():普通分类训练,使用单分支MobileNetV3_large_x0_5;cls_distill→train_distill():双分支蒸馏,共享同一个优化器,损失为两个 student 分支的交叉熵损失 + DML 互蒸馏损失 + KL/JS 散度损失之和;cls_distill_multiopt→train_distill_multiopt():双分支蒸馏 + 每分支独立优化器,反向传播时对第一个损失使用retain_graph=True后分别更新两个优化器。
三种model_type对应的模型构建逻辑位于 mv3.py 的build_model:cls支持 Siamese 双塔结构(MODEL.siamese=True时构造 SiameseMV3,两个共享骨干网络的特征相加后过分类头),cls_distill与cls_distill_multiopt均构造 DistillMV3(内含student与student1两个子网络)。
此外,use_custom_relu=True时,模型的前向传播会在 ReLU 激活处调用 JIT 编译的自定义算子custom_ops.custom_relu(见 mv3.py 与 ConvBNLayer),该算子源码位于 custom_op/custom_relu_op.cc(CPU 实现)与 custom_op/custom_relu_op.cu(CUDA 实现),通过paddle.utils.cpp_extension.load动态编译,这正是"自定义 OP 训练流程"验证的核心对象。
六、量化训练:PACT + QAT
当需要验证量化训练时,不能使用普通配置文件,而应切换到对应的 PACT 配置文件 train_infer_python_PACT.txt。该文件与普通配置的唯一差异在第 15 行:
norm_train:train.py -c mv3_large_x0_5.yml -o quant_train=True即通过命令行向训练脚本注入quant_train=True。对应的测试指令为:
bash test_tipc/test_train_python.sh ./test_tipc/train_infer_python_PACT.txt 'lite_train_lite_infer'quant_train=True会在 train.py 中触发如下量化逻辑:
if "quant_train" in config and config["quant_train"] is True: quanter = QAT(config=quant_config, act_preprocess=PACT) quanter.quantize(model)其中PACT激活预处理层与quant_config量化配置均定义在 slim/slim_quant.py:
- PACT 层:以可学习参数
alpha(初始值 20,带 L2 正则)截断激活值范围,forward中通过relu(x - alpha)与relu(-alpha - x)实现对称截断,从而在训练中自适应学习激活量化范围; - quant_config:默认采用
channel_wise_abs_max权重量化、moving_average_abs_max激活量化、8 bit(weight_bits/activation_bits)、输出int8,可量化的层类型为["Conv2D", "Linear"],滑动平均系数moving_rate=0.9。
量化分支在普通训练、蒸馏训练、多优化器蒸馏训练三条路径中均被支持(见 train.py 与 train.py),因此model_type的三个取值都能与量化组合验证。
七、FPGM 滤波器裁剪训练
FPGM(Filter Pruning via Geometric Median)裁剪训练使用独立的配置文件 train_infer_python_FPGM.txt,其第 15 行注入prune_train=True:
norm_train:train.py -c mv3_large_x0_5.yml -o prune_train=True对应测试指令:
bash test_tipc/test_train_python.sh ./test_tipc/train_infer_python_FPGM.txt 'lite_train_lite_infer'训练脚本中prune_train=True的分支会调用 slim/slim_fpgm.py 的prune_model:
def prune_model(model, input_shape, prune_ratio=0.1): flops = paddle.flops(model, input_shape) pruner = FPGMFilterPruner(model, input_shape) params_sensitive = {} for param in model.parameters(): if "transpose" not in param.name and "linear" not in param.name: # set prune ratio as 10%. The larger the value, the more convolution weights will be cropped params_sensitive[param.name] = prune_ratio plan = pruner.prune_vars(params_sensitive, [0]) flops = paddle.flops(model, input_shape) return model实现要点:除transpose与linear相关参数外,其余参数(主要是卷积核)统一按prune_ratio=0.1(10%)设置裁剪敏感度,prune_vars依据几何中位数准则挑选可裁剪的滤波器,剪枝前后分别调用paddle.flops计算模型 FLOPs 以便对比裁剪收益。该分支同样在三条训练路径中通用(见 train.py、train.py、train.py)。
八、多机多卡训练配置与运行
多机多卡场景对应三份_fleet后缀配置文件:
- train_infer_python_fleet.txt(普通训练)
- train_infer_python_FPGM_fleet.txt(FPGM 裁剪)
- train_infer_python_PACT_fleet.txt(PACT 量化)
与单机配置相比,_fleet配置的关键区别在第 4 行的gpu_list:
gpu_list:xx.xx.xx.xx,yy.yy.yy.yy;0,1其中分号前为节点 IP 列表(xx.xx.xx.xx,yy.yy.yy.yy,多个 IP 用逗号分隔),分号后为每个节点上的 GPU 编号(0,1)。运行时需要把xx.xx.xx.xx替换为实际 IP,并且必须在多机的每个节点上分别执行命令。以多机多卡量化训练为例:
bash test_tipc/test_train_python.sh ./test_tipc/train_infer_python_PACT_fleet.txt 'lite_train_lite_infer'脚本对gpu_list的解析规则见 test_train_python.sh:当gpu串长度超过 15 时按;切分出ips与gpu,随后在命令中注入--ips=${ips} --gpus=${gpu};同时use_gpu取值与gpu_list按索引一一对应(fleet配置中use_gpu:True为单值,索引 0 即对应多机场景)。
九、运行日志与结果校验
执行上述任意指令后,日志会自动写入test_tipc/extra_output目录(该目录由脚本在启动时创建,见 test_train_python.sh),核心结果文件为:
test_tipc/extra_output/ |- results_python.log # 运行指令状态的日志results_python.log记录每条指令的运行状态:命令执行成功时,status_check会向日志追加形如下文的记录(原文档示例,完整覆盖普通训练、蒸馏、多优化器蒸馏与 Siamese 组合):
Run successfully with command - python3.7 train.py -c mv3_large_x0_5.yml -o use_gpu=True epoch=20 AMP.use_amp=True TRAIN.batch_size=1280 use_custom_relu=False model_type=cls MODEL.siamese=False ! Run successfully with command - python3.7 train.py -c mv3_large_x0_5.yml -o use_gpu=True epoch=2 AMP.use_amp=True TRAIN.batch_size=1280 use_custom_relu=False model_type=cls MODEL.siamese=False ! Run successfully with command - python3.7 train.py -c mv3_large_x0_5.yml -o use_gpu=True epoch=2 AMP.use_amp=True TRAIN.batch_size=1280 use_custom_relu=False model_type=cls MODEL.siamese=True ! Run successfully with command - python3.7 train.py -c mv3_large_x0_5.yml -o use_gpu=True epoch=2 AMP.use_amp=True TRAIN.batch_size=1280 use_custom_relu=False model_type=cls_distill MODEL.siamese=False ! Run successfully with command - python3.7 train.py -c mv3_large_x0_5.yml -o use_gpu=True epoch=2 AMP.use_amp=True TRAIN.batch_size=1280 use_custom_relu=False model_type=cls_distill MODEL.siamese=True ! Run successfully with command - python3.7 train.py -c mv3_large_x0_5.yml -o use_gpu=True epoch=2 AMP.use_amp=True TRAIN.batch_size=1280 use_custom_relu=False model_type=cls_distill_multiopt MODEL.siamese=False !其中Run successfully表示退出码为 0,Run failed表示失败(status_check 依据$?判断并同时输出到终端与日志)。日志中每条命令的字段(epoch、TRAIN.batch_size、use_custom_relu、model_type、MODEL.siamese、AMP.use_amp)正是配置文件各字段经笛卡尔积组合后的真实执行命令,可作为排障与追溯的直接依据。
十、补充训练示例的实现细节
补充测试自带一套完整可跑的 CIFAR-100 分类示例,除上述文件外还包含:
- mv3.py:MobileNetV3 large/small 骨干、Siamese 双塔、蒸馏双子网络、自定义 OP 的 JIT 加载与模型工厂
build_model; - loss.py:普通分类损失、蒸馏损失(
LossDistill)、DML 互蒸馏损失与 KL/JS 散度损失; - optimizer.py:优化器与学习率调度器构建(对应配置中
LEARNING_RATE的 Cosine 与OPTIMIZER的 Momentum + L2 正则); - data_loader.py 与 load_cifar.py:训练/验证数据加载;
- config.py:命令行
-c xxx.yml -o key=value的配置合并与解析; - mv3_large_x0_5.yml:模型与训练超参配置(
class_dim: 100、epoch: 1000、AMP.scale_loss: 1024.0、TRAIN.batch_size: 1280等)。
值得留意的是 train.py 中训练循环对 AMP 的处理:当配置开启AMP.use_amp时,会创建paddle.amp.GradScaler,在paddle.amp.auto_cast()上下文中前向,并通过scaler.scale/scaler.minimize完成带动态损失缩放的反向与参数更新;未开启时走普通loss.backward()路径。这也是配置文件中AMP.use_amp:True|False遍历所要覆盖的组合之一。
相关文件索引
| 用途 | 路径 |
|---|---|
| 补充训练主程序 | test_train_python.sh |
| 参数解析与状态检查公共函数 | common_func.sh |
| 普通训练配置 | train_infer_python.txt |
| PACT 量化训练配置 | train_infer_python_PACT.txt |
| FPGM 裁剪训练配置 | train_infer_python_FPGM.txt |
| 多机多卡训练配置 | train_infer_python_fleet.txt 及两份_FPGM_fleet/_PACT_fleet |
| 训练入口脚本 | train.py |
| 模型定义与自定义 OP 加载 | mv3.py |
| PACT 与量化配置 | slim/slim_quant.py |
| FPGM 裁剪实现 | slim/slim_fpgm.py |
| 模型超参配置 | mv3_large_x0_5.yml |
| 依赖清单 | requirements.txt |
【免费下载链接】PaddleOCRTurn any PDF or image document into structured data for your AI. A powerful, lightweight OCR toolkit that bridges the gap between images/PDFs and LLMs. Supports 100+ languages.项目地址: https://gitcode.com/GitHub_Trending/pa/PaddleOCR
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考