PaddleOCR 印刷数学公式识别:LaTeX-OCR 算法从训练到部署完整实战指南
【免费下载链接】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 仓库中 LaTeX-OCR 印刷数学公式识别算法文档,系统讲解从数据集准备、模型训练与评估,到 Python 推理部署的完整流程。读者将掌握 LaTeX-OCR 的 Hybrid ViT 骨干网络与自回归解码原理、pickle 标签文件生成方法、配置文件关键参数含义,以及如何将公式图片准确转换为 LaTeX 代码供下游任务使用。
1. 算法简介
LaTeX-OCR 是开源社区著名的印刷数学公式识别(Image-to-Markup)方案,原始项目由 lukas-blecher 维护。PaddleOCR 使用 LaTeX-OCR 印刷公式数据集 训练该算法,并在其测试集上完成评估与复现。算法在 PaddleOCR 中的复现效果如下:
| 模型 | 骨干网络 | 配置文件 | BLEU score | normed edit distance | ExpRate | 下载链接 |
|---|---|---|---|---|---|---|
| LaTeX-OCR | Hybrid ViT | LaTeX_OCR_rec.yaml | 0.8821 | 0.0823 | 40.01% | 训练模型 |
表中三个指标分别衡量:
- BLEU score(0.8821):预测 LaTeX 序列与标注序列的 n-gram 重合度,数值越高越好;
- normed edit distance(0.0823):归一化编辑距离,反映字符级差异,数值越低越好;
- ExpRate(40.01%):整条公式完全识别正确的比例(Exact Match Rate),是 LaTeXOCRMetric 中定义的
main_indicator。
2. 环境准备
2.1 基础环境
首先参考《运行环境准备》配置 PaddleOCR 运行环境,再参考《项目克隆》克隆项目代码。
2.2 额外依赖安装
LaTeX-OCR 训练与推理依赖以下额外 Python 包(见 requirements.txt):
pip install -r docs/version2.x/algorithm/formula_recognition/requirements.txt该文件声明了四类关键依赖:
tokenizers==0.19.1:用于加载 latex_ocr_tokenizer.json 分词器。后处理类 LaTeXOCRDecode 在初始化时通过TokenizerFast.from_file()加载该词典,并设置TOKENIZERS_PARALLELISM=false以避免多进程分叉时出现死锁告警;imagesize:在生成 pickle 标签文件时读取 PNG 图片的宽高(不实际解码像素),用于按尺寸分组;ftfy、Wand:文本修复与 Wand 图像库,用于标签清洗和图像预处理链路。
3. 数据准备:pickle 标签文件生成
LaTeX-OCR 的训练/验证/测试数据以 pickle(.pkl)格式组织,将不同尺寸的公式图像按缩放后的宽高分组,从而在训练时对同组图片做批内拼接(batch 内多张图沿宽方向拼接为一张图送入网络)。
3.1 下载并解压原始数据
从 Google Drive 下载formulae.zip和math.txt,其中formulae.zip内含train、val、test三个子目录的公式 PNG 图片,math.txt为与图片索引对应的 LaTeX 标注文件。然后执行:
# 创建 LaTeX-OCR 数据集目录 mkdir -p train_data/LaTeXOCR # 解压 formulae.zip,并拷贝 math.txt unzip -d train_data/LaTeXOCR path/formulae.zip cp path/math.txt train_data/LaTeXOCR3.2 执行 txt2pkl 转换
转换脚本为 math_txt2pkl.py,核心逻辑是txt2pickle()函数:遍历--image_dir下的全部 PNG,用imagesize读取宽高,过滤掉超出min_dimensions=(32,32)与max_dimensions=(672,192)的图片,然后将高度/宽度向上取整到 16 的倍数(divide_w, divide_h)作为 key,把(LaTeX标注, 图片文件名)追加到对应分组。
# 训练集转换 python ppocr/utils/formula_utils/math_txt2pkl.py --image_dir=train_data/LaTeXOCR/train --mathtxt_path=train_data/LaTeXOCR/math.txt --output_dir=train_data/LaTeXOCR/ # 验证集转换 python ppocr/utils/formula_utils/math_txt2pkl.py --image_dir=train_data/LaTeXOCR/val --mathtxt_path=train_data/LaTeXOCR/math.txt --output_dir=train_data/LaTeXOCR/ # 测试集转换 python ppocr/utils/formula_utils/math_txt2pkl.py --image_dir=train_data/LaTeXOCR/test --mathtxt_path=train_data/LaTeXOCR/math.txt --output_dir=train_data/LaTeXOCR/生成的 pickle 文件按输入目录名命名,例如latexocr_train.pkl、latexocr_val.pkl、latexocr_test.pkl,并保存在--output_dir指定的目录下,与 LaTeX_OCR_rec.yaml 中Train.dataset.data/Eval.dataset.data的默认配置对应。
3.3 数据集加载机制
从源码看,LaTeXOCRDataSet 负责读取 pickle:
- 加载时使用受限反序列化(
_RestrictedDatasetUnpickler),仅允许dict/list/tuple/set/str/int/float/bool/bytes等基础类型,防止恶意 pickle 载荷执行任意代码; - 按
batch_size_per_pair(训练 56、评估 10)在同一尺寸分组内取样本构成 pair,训练时不足一批的残余样本在keep_smaller_batches=False时被丢弃,评估时keep_smaller_batches=True予以保留; __getitem__中先对批内每张图执行变换(含 LatexTrainTransform 的随机bitmap_prob位图化增强),再沿宽方向np.concatenate拼接成一张图,形状为[N, 1, H, W],随后由LatexOCRLabelEncode将 LaTeX 序列编码为 token 序列与 attention mask。
4. 配置文件解析
LaTeX_OCR_rec.yaml 是 LaTeX-OCR 训练与推理的唯一配置入口,PaddleOCR 对代码进行了模块化,训练该模型只需更换配置文件即可。核心参数如下:
| 配置段 | 关键参数 | 默认值 | 说明 |
|---|---|---|---|
| Global | model_name | LaTeX_OCR_rec | 模型名,静态图推理时使用 |
| Global | epoch_num | 500 | 最大训练轮数 |
| Global | max_seq_len | 512 | 模型输出最大 token 长度(静态图推理上限亦为 512) |
| Global | eval_batch_step | [0, 60000] | 每 60000 次迭代(约 22 epoch,batch_size=56)评估一次 |
| Global | rec_char_dict_path | ppocr/utils/dict/latex_ocr_tokenizer.json | 分词器词典路径 |
| Global | d2s_train_image_shape | [1,256,256] | 训练动态图输入形状 |
| Optimizer | name/lr | AdamW/ Const0.0001 | 优化器与恒定学习率 |
| Architecture.Backbone | name | HybridTransformer | 骨干网络 |
| Architecture.Backbone | img_size | [192, 672] | 输入图像尺寸(H, W) |
| Architecture.Backbone | embed_dim/depth/num_heads | 256/4/8 | ViT 嵌入维度、层数与注意力头数 |
| Architecture.Head | name | LaTeXOCRHead | 自回归解码头,支持attn_on_attn、cross_attend、ff_glu等 x-transformers 风格配置 |
| Loss | name | LaTeXOCRLoss | 交叉熵损失 |
| PostProcess | name | LaTeXOCRDecode | token 序列解码为 LaTeX 字符串 |
| Metric | name/main_indicator | LaTeXOCRMetric/exp_rate | 评估指标,cal_bleu_score: True同时计算 BLEU |
| Train.dataset | data_dir/data | ./train_data/LaTeXOCR/train/latexocr_train.pkl | 训练数据路径 |
| Train.dataset | min_dimensions/max_dimensions | [32,32]/[672,192] | 尺寸过滤与缩放范围 |
| Train.loader | batch_size_per_card/collate_fn | 1/LaTeXOCRCollator | 每卡 loader 批大小(pair 内拼接) |
4.1 网络结构(Hybrid ViT + Transformer 解码器)
从 rec_hybridvit.py 与 rec_latexocr_head.py 的源码结构看:
- 编码器:
HybridTransformer由ResNetV2(backbone_layers=[2,3,7],使用StdConv2dSame卷积与 same padding)作为 stem 提取特征,再由HybridEmbed将特征图切分为 patch 并线性投影为embed_dim=256的 token 序列,随后送入 4 层、8 头的标准 ViT Block(含 cls token 与可学习位置编码),最终输出[N, 1, H//16, W//16]的特征; - 解码器:
LaTeXOCRHead实现自回归 Transformer 解码器,配置项attn_on_attn(注意力叠加)、cross_attend(跨模态注意力)、ff_glu(GLU 前馈)等均对应 x-transformers 的实现方式,训练时使用 teacher forcing 生成 token 序列。
4.2 损失函数
LaTeXOCRLoss 将解码器输出的词表概率word_probsreshape 为[-1, vocab_size],与右移一位的标签batch[1][:, 1:]计算带ignore_index=-100的交叉熵,返回{"loss": loss}供训练器使用。
5. 模型训练
5.1 单卡 / 多卡训练
在完成数据准备后,即可启动训练:
# 单卡训练(默认训练方式) python3 tools/train.py -c configs/rec/LaTeX_OCR_rec.yaml # 多卡训练,通过 --gpus 参数指定卡号 python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/rec/LaTeX_OCR_rec.yaml训练日志、中间权重将按Global.save_model_dir(默认./output/rec/latex_ocr/)保存,save_epoch_step: 5表示每 5 个 epoch 保存一次 checkpoint。
5.2 评估节奏调整
配置默认每训练 22 个 epoch(60000 次 iteration,对应 batch_size=56)进行一次评估。若您更改了训练 batch_size 或更换数据集,请在训练时通过-o覆盖评估步长:
python3 tools/train.py -c configs/rec/LaTeX_OCR_rec.yaml -o Global.eval_batch_step=[0,{length_of_dataset//batch_size*22}]即用“数据集样本数 ÷ 批大小 × 22”重新计算每次评估的迭代间隔。
6. 模型评估
可下载已训练完成的 模型文件,解压后得到rec_latex_ocr_train/目录,使用如下命令评估(注意将pretrained_model路径改为本地实际路径;若使用自行训练的模型,请修改路径与文件名为{path/to/weights}/{model_name}):
# GPU 评估,验证集 python3 tools/eval.py -c configs/rec/LaTeX_OCR_rec.yaml -o Global.pretrained_model=./rec_latex_ocr_train/best_accuracy.pdparams # 测试集评估:通过 -o 覆盖 Eval 数据路径 python3 tools/eval.py -c configs/rec/LaTeX_OCR_rec.yaml -o Global.pretrained_model=./rec_latex_ocr_train/best_accuracy.pdparams Eval.dataset.data_dir=./train_data/LaTeXOCR/test Eval.dataset.data=./train_data/LaTeXOCR/latexocr_test.pkl评估过程由 LaTeXOCRMetric 完成:逐条比较预测与标签是否完全一致累计exp_rate,同时基于compute_edit_distance与Levenshtein.normalized_distance统计编辑距离,并在cal_bleu_score=True时用compute_bleu_score累计 BLEU 分数,最终返回exp_rate、edit_distance、bleu_score等指标(其中exp_rate是配置指定的主指标)。
7. 单张图片预测
使用训练好的模型对单张图片进行预测(配置必须与训练一致):
python3 tools/infer_rec.py -c configs/rec/LaTeX_OCR_rec.yaml -o Global.infer_img='./docs/datasets/images/pme_demo/0000013.png' Global.pretrained_model=./rec_latex_ocr_train/best_accuracy.pdparams预测文件夹下所有图像时,可将infer_img改为文件夹路径,如Global.infer_img='./docs/datasets/images/pme_demo/'。
注意事项:
- 预测图像须为白底黑字,即公式笔画为黑色、背景为白色;
- 图片宽高建议在
[32,32]与[672,192](宽 672、高 192)范围内,超出范围时推理代码会先做 pad 与等比缩放处理(见 predict_rec.py 的norm_img_latexocr); - 若修改了字典或预处理方法,需同步调整配置文件中的
rec_char_dict_path以及 predict_rec.py 中 LaTeX-OCR 的预处理逻辑。
8. 推理部署
8.1 Python 推理(动态图转静态图)
首先将训练保存的 best 模型转换为 inference model。这里以官方训练好的模型为例:
python3 tools/export_model.py -c configs/rec/LaTeX_OCR_rec.yaml -o Global.pretrained_model=./rec_latex_ocr_train/best_accuracy.pdparams Global.save_inference_dir=./inference/rec_latex_ocr_infer/ # 静态图模型支持的最大输出长度为 512注意:
- 若您在自己的数据集上训练并调整了字典文件,请检查配置中的
rec_char_dict_path是否为所需词典; - 官方同时提供 转换后推理模型下载。
转换成功后,./inference/rec_latex_ocr_infer/目录下应包含三个文件:
/inference/rec_latex_ocr_infer/ ├── inference.pdiparams # 识别 inference 模型的参数文件 ├── inference.pdiparams.info # 识别 inference 模型的参数信息,可忽略 └── inference.pdmodel # 识别 inference 模型的 program 文件8.2 执行推理
使用 predict_rec.py 进行静态图推理:
python3 tools/infer/predict_rec.py --image_dir='./docs/datasets/images/pme_demo/0000295.png' --rec_algorithm="LaTeXOCR" --rec_batch_num=1 --rec_model_dir="./inference/rec_latex_ocr_infer/" --rec_char_dict_path="./ppocr/utils/dict/latex_ocr_tokenizer.json"预测文件夹下所有图像时,可将image_dir改为文件夹路径,如--image_dir='./docs/datasets/images/pme_demo/'。
从源码调用链看,推理路径为:
- predict_rec.py 对每张图调用
norm_img_latexocr预处理(灰度化 → 按 0.7931/0.1738 归一化 → 补零到 16 的倍数并转[1,1,H,W]); - 将预处理后的图像送入
rec_model_dir指定的静态图模型,得到 token 序列(predict_rec.py 中LaTeXOCR分支); - 由
LaTeXOCRDecode后处理解码:先用TokenizerFast将 token 还原为子词,再拼接去空格、移除[EOS]/[BOS]/[PAD]特殊 token,最后通过post_process中的正则规则压缩\operatorname、\mathrm等命令与相邻字符间的多余空格(rec_postprocess.py)。
执行命令后,识别的 LaTeX 公式会打印到屏幕上。官方文档给出的 0000295.png 预测结果示例为:
Predicts of ./docs/datasets/images/pme_demo/0000295.png: \zeta_{0}(\nu)=-{\frac{\nu\varrho^{-2\nu}}{\pi}}\int_{\mu}^{\infty}d\omega\int_{C_{+}}d z{\frac{2z^{2}}{(z^{2}+\omega^{2})^{\nu+1}}}{\tilde{\Psi}}(\omega;z)e^{i\epsilon z}~~~,8.3 C++ 推理 / Serving / 更多部署
- C++ 推理部署:由于 C++ 端预处理与后处理尚未支持 LaTeX-OCR,暂不支持;
- Serving 服务化部署:暂不支持;
- 更多推理部署:暂不支持。
9. FAQ
- LaTeX-OCR 数据集来源?数据集来自 LaTeXOCR 原始仓库(lukas-blecher/LaTeX-OCR),PaddleOCR 复现训练与评估均使用该数据集,测试集上的 BLEU 0.8821、normed edit distance 0.0823、ExpRate 40.01% 为官方复现结果。
- 预测结果异常时优先检查什么?确认输入为白底黑字公式图、尺寸在 [32,32]–[672,192] 范围内,且
--rec_char_dict_path指向的词典与训练时一致。 - 为何需要生成 pickle 文件?公式图像尺寸差异大,pkl 将同尺度图像分组并允许批内横向拼接,从而在保证批大小的同时避免大量 padding 带来的计算浪费,这与 math_txt2pkl.py 和 LaTeXOCRDataSet 的实现一致。
相关资源速查
- 配置文件:LaTeX_OCR_rec.yaml
- 数据转换脚本:math_txt2pkl.py
- 数据集实现:latexocr_dataset.py
- 骨干网络:rec_hybridvit.py
- 解码头:rec_latexocr_head.py
- 损失函数:rec_latexocr_loss.py
- 后处理:rec_postprocess.py
- 评估指标:rec_metric.py
- 词典:latex_ocr_tokenizer.json
- 推理工具:predict_rec.py
- 训练/评估/导出入口:
tools/train.py、tools/eval.py、tools/export_model.py
【免费下载链接】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),仅供参考