PaddleOCR 中的 UniMERNet 通用数学公式识别:从数据准备到训练、评估与推理的完整实战指南
【免费下载链接】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 仓库中的 算法文档 与 UniMERNet 配置文件,系统讲解如何在 PaddleOCR 中复现、训练、评估与推理通用数学公式识别模型 UniMERNet。读完本文,你将掌握:UniMERNet 在 PaddleOCR 中的整体架构与复现精度、四个标准测试集(SPE/CPE/SCE/HWE)的指标含义、从 UniMER-1M 与 HME100K 原始数据到 PaddleOCR 训练格式的完整转换流程,以及单卡/多卡训练、分测试集评估与单图预测的完整命令行操作,并了解其背后的源码实现细节。
1. UniMERNet 算法简介与复现精度
1.1 算法背景
UniMERNet 是一个面向通用数学公式识别(Mathematical Expression Recognition, MER)的端到端模型,原始项目由 OpenDataLab 团队开源。PaddleOCR 将其以模块化方式集成进文本识别(rec)体系:使用Donut Swin作为视觉骨干网络(编码器),配合自研的 UniMERNetHead 解码器,将公式图片端到端转换为 LaTeX 序列。由于 PaddleOCR 对代码做了模块化,训练不同识别模型只需要更换配置文件,因此本文全部操作的核心配置文件是 configs/rec/UniMERNet.yaml。
1.2 复现指标说明
PaddleOCR 使用 UniMERNet 通用公式识别数据集训练、并在对应测试集上评估,复现结果如下表:
| 模型 | 骨干网络 | 配置文件 | SPE-BLEU↑ | SPE-EditDis↓ | CPE-BLEU↑ | CPE-EditDis↓ | SCE-BLEU↑ | SCE-EditDis↓ | HWE-BLEU↑ | HWE-EditDis↓ | 下载链接 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| UniMERNet | Donut Swin | UniMERNet.yaml | 0.9187 | 0.0584 | 0.9252 | 0.0596 | 0.6068 | 0.2297 | 0.9157 | 0.0546 | trained model |
其中:
- SPE(Simple Formulas):简单公式测试集;
- CPE(Complex Formulas):复杂公式测试集;
- SCE(Scanned Captured Formulas):扫描/拍摄公式测试集;
- HWE(Handwritten Formulas):手写公式测试集。
指标方面,BLEU↑ 越高越好,衡量预测 LaTeX 序列与真值之间的 n-gram 相似度;EditDis(Edit Distance,编辑距离)↓ 越低越好,衡量字符级差异。从表中可以看到,SCE 场景(扫描/拍摄)的识别难度明显更高,EditDis 达到 0.2297,这也符合扫描图像噪声多的直觉。
1.3 指标在源码中的定义
复现表中的 BLEU 与编辑距离指标由 ppocr/metrics/rec_metric.py 中的LaTeXOCRMetric计算实现。从源码可见:
- 指标以
exp_rate为主指标(main_indicator="exp_rate"),即公式完全识别正确的比例; - 通过
cal_bleu_score: True开启 BLEU 计算(compute_bleu_score); - 编辑距离采用
Levenshtein.normalized_distance归一化编辑距离,统计每个样本后按样本总数求平均; - 除 BLEU 与编辑距离外,还同时输出
exp_rate<=1/2/3等容忍 1~3 个字符误差的辅助指标。
2. 环境配置与依赖安装
2.1 基础环境
首先参考 运行环境准备 配置 PaddleOCR 运行环境(安装 PaddlePaddle 与 PaddleOCR 依赖),参考 项目克隆 克隆项目代码。
2.2 额外依赖
UniMERNet 的训练链路依赖 Hugging Facetokenizers(加载公式 tokenizer)、imagesize(读取图片尺寸)、ftfy(文本修复)以及Wand(ImageMagick Python 绑定,用于雪景等图像增强),需要额外安装:
sudo apt-get update sudo apt-get install libmagickwand-dev pip install -r docs/version2.x/algorithm/formula_recognition/requirements.txt该依赖清单定义于 docs/version2.x/algorithm/formula_recognition/requirements.txt,当前内容包括:
tokenizers==0.19.1 imagesize ftfy Wand说明:
libmagickwand-dev是系统级依赖,用于Wand库调用 ImageMagick 实现运动模糊(motion blur)等图像特效,缺了它,训练增强中的Snow变换会报错。
3. 数据集准备与格式转换
3.1 数据来源
UniMERNet 训练需要三类数据:
- UniMER-1M.zip与UniMER-Test.zip:来自 OpenDataLab 的 UniMER-Dataset;
- HME100K:来自好未来(TAL)AI 平台的手写公式数据集。
3.2 目录创建与解压
# create the UniMERNet dataset directory mkdir -p train_data/UniMERNet # unzip UniMER-1M.zip, UniMER-Test.zip and HME100K.zip unzip -d train_data/UniMERNet path/UniMER-1M.zip unzip -d train_data/UniMERNet path/UniMER-Test.zip unzip -d train_data/UniMERNet/HME100K train_data/UniMERNet/HME100K/train.zip unzip -d train_data/UniMERNet/HME100K train_data/UniMERNet/HME100K/test.zip3.3 训练集格式转换
UniMER-1M 与 HME100K 的标注格式与 PaddleOCR 的SimpleDataSet不同,必须先用仓库自带的转换脚本 ppocr/utils/formula_utils/unimernet_data_convert.py 统一转换为图片相对路径\tLaTeX标注的制表符分隔格式:
# convert the training set python ppocr/utils/formula_utils/unimernet_data_convert.py \ --image_dir=train_data/UniMERNet \ --datatype=unimernet_train \ --unimernet_txt_path=train_data/UniMERNet/UniMER-1M/train.txt \ --hme100k_txt_path=train_data/UniMERNet/HME100K/train_labels.txt \ --output_path=train_data/UniMERNet/train_unimernet_1M.txt从源码看,datatype=unimernet_train时执行latexocr2paddleocr_train:
- 对 UniMER-1M,按
train.txt行号生成UniMER-1M/images/{i:07d}.png的 7 位数字文件名(如0000000.png),逐行写入UniMER-1M/images/0000000.png\t{LaTeX}; - 对 HME100K,从
train_labels.txt中读取图片名\tLaTeX行,改写为HME100K/train_images/{img_name}\t{LaTeX}。
3.4 测试集格式转换
四个测试子集分别转换(datatype=unimernet_test时执行unimernet2paddleocr_test,同样按spe.txt等标注文件的行号生成 7 位数字图片名):
# SPE python ppocr/utils/formula_utils/unimernet_data_convert.py \ --image_dir=train_data/UniMERNet/UniMER-Test/spe \ --datatype=unimernet_test \ --unimernet_txt_path=train_data/UniMERNet/UniMER-Test/spe.txt \ --output_path=train_data/UniMERNet/test_unimernet_spe.txt # CPE python ppocr/utils/formula_utils/unimernet_data_convert.py \ --image_dir=train_data/UniMERNet/UniMER-Test/cpe \ --datatype=unimernet_test \ --unimernet_txt_path=train_data/UniMERNet/UniMER-Test/cpe.txt \ --output_path=train_data/UniMERNet/test_unimernet_cpe.txt # SCE python ppocr/utils/formula_utils/unimernet_data_convert.py \ --image_dir=train_data/UniMERNet/UniMER-Test/sce \ --datatype=unimernet_test \ --unimernet_txt_path=train_data/UniMERNet/UniMER-Test/sce.txt \ --output_path=train_data/UniMERNet/test_unimernet_sce.txt # HWE python ppocr/utils/formula_utils/unimernet_data_convert.py \ --image_dir=train_data/UniMERNet/UniMER-Test/hwe \ --datatype=unimernet_test \ --unimernet_txt_path=train_data/UniMERNet/UniMER-Test/hwe.txt \ --output_path=train_data/UniMERNet/test_unimernet_hwe.txt转换得到的四个 txt 文件分别对应配置文件中Eval.dataset.data_dir与Eval.dataset.label_file_list的组合,用于后续分场景评估。
3.5 补充工具:math_txt2pkl.py
仓库中另有一个辅助脚本 ppocr/utils/formula_utils/math_txt2pkl.py,它按图片宽高将公式聚合成(divide_w, divide_h) -> [(公式, 图片名)]的 pickle 字典(宽度范围 32~672、高度范围 32~192,并向上取整到 16 的倍数),适用于需要按图像尺寸分桶处理的场景,普通训练流程中可不用。
4. 配置文件全解析
configs/rec/UniMERNet.yaml 是训练/评估/预测共用的唯一配置入口,各模块含义如下:
4.1 Global 全局配置
| 参数 | 值 | 说明 |
|---|---|---|
model_name | UniMERNet | 模型名,用于静态图推理 |
use_gpu | True | 是否使用 GPU |
epoch_num | 40 | 训练轮数 |
save_model_dir | ./output/rec/unimernet/ | 模型保存目录 |
save_epoch_step | 5 | 每 5 个 epoch 保存一次 |
eval_batch_step | [0, 37880] | 第 0 次迭代后每 37880 次迭代评估一次(即每个 epoch 评估 1 次) |
cal_metric_during_train | True | 训练过程中计算评估指标 |
pretrained_model | 空 | 预训练权重路径(训练时通过-o覆盖) |
rec_char_dict_path | ppocr/utils/dict/unimernet_tokenizer | 关键:公式 tokenizer 目录(非普通字符字典文件),内含tokenizer.json与tokenizer_config.json |
input_size | [192, 672] | 模型输入尺寸(高×宽) |
max_seq_len | 1024 | 训练时最大序列长度 |
use_space_char | False | 不额外使用空格字符 |
save_res_path | ./output/rec/predicts_unimernet.txt | 预测结果保存路径 |
4.2 Optimizer 优化器
Optimizer: name: AdamW beta1: 0.9 beta2: 0.999 weight_decay: 0.05 lr: name: LinearWarmupCosine learning_rate: 1e-4 start_lr: 1e-5 min_lr: 1e-8 warmup_steps: 5000采用 AdamW 优化器 + 线性 warmup 余弦退火学习率:峰值学习率1e-4,起始1e-5,最低1e-8,前 5000 步线性预热。
4.3 Architecture 网络结构
Architecture: model_type: rec algorithm: UniMERNet in_channels: 3 Transform: Backbone: name: DonutSwinModel hidden_size : 1024 num_layers: 4 num_heads: [4, 8, 16, 32] add_pooling_layer: True use_mask_token: False Head: name: UniMERNetHead max_new_tokens: 1536 decoder_start_token_id: 0 temperature: 0.2 do_sample: False top_p: 0.95 encoder_hidden_size: 1024 is_export: False length_aware: True- Backbone:
DonutSwinModel视觉编码器,实现位于 ppocr/modeling/backbones/rec_donut_swin.py。从源码可见其内部配置为patch_size=4、embed_dim=128、depths=[2,2,14,2]、window_size=5、image_size=[420,420]的 Swin Transformer 结构,hidden_size=1024输出视觉特征; - Head:
UniMERNetHead自回归解码器,实现位于 ppocr/modeling/heads/rec_unimernet_head.py,其核心是 MBart 风格的因果语言模型(CustomMBartForCausalLM)加lm_head输出 50000 词表上的 logits。解码参数说明:max_new_tokens: 1536:推理时最多新生成 1536 个 token;do_sample: False:默认贪心解码;temperature: 0.2、top_p: 0.95:采样解码参数(do_sample=True时生效);length_aware: True:开启长度感知机制,解码器同时预测公式 token 数,训练时作为辅助损失监督,推理时可辅助约束生成长度。
4.4 Loss 损失函数
Loss: name: UniMERNetLoss实现位于 ppocr/losses/rec_unimernet_loss.py。训练时 Head 输出三元组(logits, count_pred, masked_label),损失由两部分组成:
- word_loss:对解码 logits 与标签(shift 一位后)计算
CrossEntropyLoss(ignore_index=-100屏蔽填充位); - count_loss:当
length_aware=True时,将标签做 one-hot 后按序列求和得到每个公式的 token 计数真值,取log(count+1)后与解码器预测的计数count_pred计算SmoothL1Loss,最终loss = word_loss + 0.5 * count_loss。
4.5 PostProcess 后处理
PostProcess: name: UniMERNetDecode rec_char_dict_path: *rec_char_dict_pathUniMERNetDecode实现位于 ppocr/postprocess/rec_postprocess.py,从rec_char_dict_path指向的目录加载tokenizer.json与tokenizer_config.json,将解码出的 token id 序列还原为 LaTeX 字符串,并处理<s>(bos, id=0)、</s>(eos, id=2)、<pad>(pad, id=1)等特殊 token。
4.6 Metric 评估指标
Metric: name: LaTeXOCRMetric main_indicator: exp_rate cal_bleu_score: True即前文 1.3 节所述的LaTeXOCRMetric,主指标为公式完全正确率exp_rate,同时计算 BLEU 与编辑距离。
4.7 Train / Eval 数据管线
训练与评估均使用SimpleDataSet,关键差异在于 transforms:
- Train:
UniMERNetImgDecode(裁边→resize→居中 padding 到 192×672)→UniMERNetTrainTransform(数据增强)→UniMERNetImageFormat(通道压缩为单通道、padding 到 32 的倍数并转[1,H,W])→UniMERNetLabelEncode(tokenizer 编码标签,max_seq_len=1024)→KeepKeys保留['image', 'label', 'attention_mask']; - Eval:将
UniMERNetTrainTransform替换为无增强的UniMERNetTestTransform,其余一致; - 两者均使用
UniMERNetCollator作为collate_fn,batch_size_per_card训练为 7、评估为 30。
训练增强UniMERNetTrainTransform的实现位于 ppocr/data/imaug/unimernet_aug.py,包含:腐蚀/膨胀(Erosion/Dilation)、雾/霜/雪/雨/阴影(Fog/Frost/Snow/Rain/Shadow,其中雪景使用Wand做运动模糊)、ShiftScaleRotate、GridDistortion、RGBShift、高斯噪声、RandomBrightnessContrast、JPEG 压缩,最后统一转灰度并以mean=0.7931, std=0.1738归一化;测试变换仅做灰度化与归一化(见 unimernet_aug.py)。
5. 模型训练
5.1 下载预训练模型
训练前需下载Texify预训练权重作为初始化(UniMERNetHead解码器结构对齐自 Texify 的 MBart 解码器):
# download the Texify pre-trained model wget -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/pretrained/texify.pdparams5.2 单卡训练
# Single GPU training python3 tools/train.py -c configs/rec/UniMERNet.yaml \ -o Global.pretrained_model=./pretrain_models/texify.pdparams5.3 多卡训练
通过--gpus参数指定卡号:
# Multi GPU training, specify the gpu number through the --gpus parameter python3 -m paddle.distributed.launch --gpus '0,1,2,3' --ips=127.0.0.1 tools/train.py -c configs/rec/UniMERNet.yaml \ -o Global.pretrained_model=./pretrain_models/texify.pdparams5.4 调整评估频率
配置默认每训练 1 个 epoch(37880 次 iteration)评估 1 次。若你修改了batch_size或更换了数据集,评估间隔应相应调整,可按下式计算并覆盖:
python3 -m paddle.distributed.launch --gpus '0,1,2,3' --ips=127.0.0.1 tools/train.py -c configs/rec/UniMERNet.yaml \ -o Global.eval_batch_step=[0,{length_of_dataset//batch_size//4}] \ Global.pretrained_model=./pretrain_models/texify.pdparams其中{length_of_dataset//batch_size//4}表示“数据集样本数 ÷ batch size ÷ 4”对应的迭代步数。训练过程中的完整通用说明可参考 文本识别训练教程。
5.5 训练入口与模块注册
训练入口为 tools/train.py,PaddleOCR 按algorithm: UniMERNet自动装配 backbone(DonutSwinModel)、head(UniMERNetHead)、loss(UniMERNetLoss)、postprocess(UniMERNetDecode)与 metric(LaTeXOCRMetric),注册表分别位于 ppocr/modeling/backbones、ppocr/modeling/heads、ppocr/losses 与 ppocr/postprocess 的__init__.py中。
6. 模型评估
下载已训练完成的 模型文件(或使用自训练保存的best_accuracy.pdparams),解压后按四个测试集分别评估。注意将Global.pretrained_model设置为本地路径:
# GPU evaluation # SPE test set evaluation python3 tools/eval.py -c configs/rec/UniMERNet.yaml -o \ Eval.dataset.data_dir=./train_data/UniMERNet/UniMER-Test/spe \ Eval.dataset.label_file_list=["./train_data/UniMERNet/test_unimernet_spe.txt"] \ Global.pretrained_model=./rec_unimernet_train/best_accuracy.pdparams # CPE test set evaluation python3 tools/eval.py -c configs/rec/UniMERNet.yaml -o \ Eval.dataset.data_dir=./train_data/UniMERNet/UniMER-Test/cpe \ Eval.dataset.label_file_list=["./train_data/UniMERNet/test_unimernet_cpe.txt"] \ Global.pretrained_model=./rec_unimernet_train/best_accuracy.pdparams # SCE test set evaluation python3 tools/eval.py -c configs/rec/UniMERNet.yaml -o \ Eval.dataset.data_dir=./train_data/UniMERNet/UniMER-Test/sce \ Eval.dataset.label_file_list=["./train_data/UniMERNet/test_unimernet_sce.txt"] \ Global.pretrained_model=./rec_unimernet_train/best_accuracy.pdparams # HWE test set evaluation python3 tools/eval.py -c configs/rec/UniMERNet.yaml -o \ Eval.dataset.data_dir=./train_data/UniMERNet/UniMER-Test/hwe \ Eval.dataset.label_file_list=["./train_data/UniMERNet/test_unimernet_hwe.txt"] \ Global.pretrained_model=./rec_unimernet_train/best_accuracy.pdparams每条命令通过-o覆盖Eval.dataset.data_dir(图片目录)与Eval.dataset.label_file_list(3.4 节转换出的标注文件),即可在对应场景上输出exp_rate、bleu_score、edit distance等指标,与第 1.2 节复现表一一对应。评估入口为 tools/eval.py。
7. 模型预测
使用与训练一致的配置文件进行单张图片预测:
# The configuration file used for prediction must match the training python3 tools/infer_rec.py -c configs/rec/UniMERNet.yaml \ -o Global.infer_img='./docs/datasets/images/pme_demo/0000099.png' \ Global.pretrained_model=./rec_unimernet_train/best_accuracy.pdparams要点说明:
Global.infer_img支持单张图片路径;若想预测目录下所有图像,可将其改为文件夹路径,如Global.infer_img='./doc/datasets/pme_demo/';- 预测使用的配置文件必须与训练一致,保证字典(tokenizer)、输入尺寸等设置匹配;
- 预测结果默认写入
Global.save_res_path指定的./output/rec/predicts_unimernet.txt。
推理入口为 tools/infer_rec.py。从 rec_unimernet_head.py 的forward实现可见:推理模式下 Head 以视觉编码器输出为条件,通过generate/generate_export执行自回归解码(配合use_cache=True缓存 KV,加速逐 token 生成),再经UniMERNetDecode还原为 LaTeX 文本。
8. 常见问题(FAQ)
UniMERNet 数据集从哪来?训练所用的 UniMER-1M / UniMER-Test 与 HME100K 数据来自 UniMERNet 源项目及好未来平台,PaddleOCR 侧仅提供数据转换工具(unimernet_data_convert.py)与训练配置,不随仓库分发数据本身。
为什么需要安装 libmagickwand-dev?训练数据增强中的
Snow(雪景)变换通过Wand(ImageMagick 绑定)实现motion_blur,缺少该系统库会导致增强阶段报错,因此必须在pip install之前完成apt-get install libmagickwand-dev。为什么
rec_char_dict_path指向一个目录而不是 .txt 字典?UniMERNet 使用 Hugging Facetokenizers的 BPE/Unigram tokenizer 而非普通字符表,目录内包含tokenizer.json与tokenizer_config.json,由UniMERNetLabelEncode(label_ops.py)与UniMERNetDecode共同加载。改 batch_size 后如何保持评估频率合理?按 5.4 节公式通过
-o Global.eval_batch_step=[0,{length_of_dataset//batch_size//4}]覆盖评估间隔。推理速度慢怎么办?推理默认贪心解码(
do_sample=False);若模型已导出为静态图,可将Global.model_name: UniMERNet与is_export: True配合使用(代码中为静态图导出提供了generate_export分支),以获得更稳定的部署推理路径。
总结
本文完整覆盖了 PaddleOCR 中 UniMERNet 公式识别从环境搭建、数据转换、配置解析到训练、评估、预测的全链路,并深入源码印证了 Donut Swin 编码器、MBart 风格自回归解码器、长度感知损失(UniMERNetLoss)、tokenizer 加载(UniMERNetLabelEncode/UniMERNetDecode)与LaTeXOCRMetric指标计算等关键实现。按文中命令逐步操作,即可在四个标准测试集上复现文档给出的 SPE/CPE/SCE/HWE 精度,并将任意公式图片转换为 LaTeX 序列。
【免费下载链接】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),仅供参考