赞
踩
项目地址:https://github.com/facebookresearch/nougat
论文地址:Nougat: Neural Optical Understanding for Academic Documents
近日,MetaAI又放了大招,他们提出了一种全新的端到端的OCR模型,该模型基于自回归的方法,旨在实现给定图片后输出对应的Markdown标记。一个模型实现版面分析、文本检测、文本识别、公式识别等功能。笔者从论文、源码、测试对Nougat进行深度学习与理解。下面一起来看Nougat是如何做的吧!
该模型采用了常规的“编码器-解码器”(encoder-decoder)架构,下面对其进行详细说明:
编码器(Encoder):
SwinTransformer
模型1 作为编码器。解码器(Decoder):
mBART
模型的解码器部分2 作为解码器。以上可见Nougat的encoder与decoder都用了较大transformer架构,整体pipeline得参数量达
350
M
350M
350M。
Nougat将OCR的问题定义为: 图片 ⟶ m a r k d o w n \text{图片} \longrightarrow \mathrm{markdown} 图片⟶markdown
核心关键是:如何用一种cheap的方法构造(图片,对应的markdown)pair。于我而言,这是这篇文章最有价值、最值得借鉴学习的地方。
目前并无大规模的pdf图片与对应markdown标记pair的数据集。Nougat从arXiv、PMC (PubMed Central), IDL(Industry Documents Library)三个来源构建数据集。其中PMC与IDL的数据由于语义信息不充足仅用于预训练阶段,来使模型具备基础的ocr能力。arXiv数据有tex源码,能拿到所有需要的语义信息,用于预训练和微调阶段。
数据源 | Pages | 简介 | 使用阶段 |
---|---|---|---|
arXiv | 750w | 有tex源码,信息最充足 | 预训练+微调 |
PMC (PubMed Central) | 53.6w | 有xml源码。但xml文件经常将公式、表格存为图片,导致语义信息不足。 | 预训练 |
IDL3 (Industry Documents Library) | 44.6W | 仅有text信息,缺失format信息,语义信息不充足。 | 预训练 |
图文对构造的整体pipeline由下图所示。从arXiv拿到的Tex源码出发拿到全篇文章的markdown标记,与pdf每页的图片与文本
TEX2HTML转化工具为 LaTeXML http://dlmf.nist.gov/LaTeXML/。(tex源码自定义性过强,转为HTML主要为了消歧)
HTML2markdown 转为代码见源码位置:nougat/dataset/parser/html2md.py
目前我们只能得到全文的markdown标记与pdf图片文本对。剩下需要做的就是根据pdf的page text信息将markdown进行划分得到 p a g e m a r k d o w n \mathrm{page \, markdown} pagemarkdown
代码位置:nougat/nougat/dataset/split_md_to_pages/split_markdown
预处理1 去除PDF中的图片表格:
由于图片表格在PDF的位置和tex源码的位置可能有所差异,因此作者采取的办法是先用pdffigures2工具将PDF的图片和表格移除。当划分完markdown后再在markdown的末尾加入移除的信息。
pdffigures2提取的信息如
{
"figures": [{
"name": "1",
"page": 5,
"figType": "Table",
"regionBoundary": {
"x1": 74.0,
"y1": 72.0,
"x2": 517.0,
"y2": 507.0
},
"caption": "Table 1. Result comparison with representative vision-language pre-training models. † denotes using additional text premise as input.",
"imageText": ["BEIT-3", "[?]", "28M", "MOME", "Transformer", "84.19", "84.03", "91.51", "92.58", "-", "-", "PaLI", "[?]", "1.6B", "VIT-E-224", "84.30", "84.34", "-", "-", "-", "-", "ViLTALARGE", "4M", ...],
"captionBoundary": {
"x1": 50.11199951171875,
"y1": 515.78271484375,
"x2": 527.7859497070312,
"y2": 521.1849975585938
}
}, {
"name": "5",
"page": 14,
"figType": "Figure",
"regionBoundary": {
"x1": 57.0,
"y1": 148.0,
"x2": 538.0,
"y2": 605.803955078125
},
"caption": "Figure 5. Case study of ViLTA on image captioning task.",
"imageText": ["Three", "giraffes", "are", "standing", "in", "a", "grassy", "field.", "A", "street", "game", "controller."],
"captionBoundary": {
"x1": 195.4810028076172,
"y1": 627.4857177734375,
"x2": 399.7445983886719,
"y2": 632.8880004882812
}
},],
"regionless-captions": []
}
预处理2 将pdf的text格式转化:
去除PDF text中的尾注、页码等。
预处理3 将pdf的text格式转化为latex编码:
后续的markdown划分中会依据markdown的序列与pdf text的匹配度,为了更好的匹配,最好将pdf的text用pylatexenc工具转为为latex编码。
叙述核心逻辑,详细细节见源码
STEP1: HTML解析的全文markdown按段落
划分, 得到doc_paragraphs_full, 数据结构: List[str]
, 每一个元素是段落
doc_paragraphs_full: List[str] = doc.split("\n") # 先按换行符切分,doc为markdown全文
doc_paragraph_lengths = [len(p) for p in doc_paragraphs_full if len(p) > 1]
# doc_paragraph_chars为预设的段落字符数, num_lines为段落所占的行数
num_lines = 1 + int(doc_paragraph_chars / np.mean(doc_paragraph_lengths))
doc_paragraphs_full = [
unidecode("\n".join(doc_paragraphs_full[i : i + num_lines]))
for i in range(0, len(doc_paragraphs_full), num_lines)
] # 划分段落
STEP2: 用fitz
以block
拿到每页的text, 得到pdf_content, 数据结构: List[List[str]]
,例:pdf_content[0][0]
为第一页的第一个block的文本信息。
blocks = page.get_text(
"blocks", flags=fitz.TEXT_DEHYPHENATE | fitz.TEXT_PRESERVE_IMAGES
)
STEP3: 基于pdf_content训练page分类器
STEP4: 预测markdown的所有段落文本doc_paragraphs_full所属的页面标签。
STEP5: 根据Gini impurity
来refine预测的doc_paragraphs_full页面标签,使其满足阶梯状分布。
G
[
a
,
b
]
(
i
)
=
(
b
−
a
)
⋅
(
1
−
p
[
a
,
b
]
2
(
i
)
−
p
[
a
,
b
]
2
(
i
+
1
)
)
,
(1)
G _ { [ a , b ] } ( i ) = ( b - a ) \cdot ( 1 - p _ { [ a , b ] } ^ { 2 } ( i ) - p _ { [ a , b ] } ^ { 2 } ( i + 1 ) ) , \tag{1}
G[a,b](i)=(b−a)⋅(1−p[a,b]2(i)−p[a,b]2(i+1)),(1)
t ^ i = arg min t ( G [ a , t ] ( i ) + G [ t , b ] ( i ) ) (2) \hat { t } _ { i } = \mathop{\arg \min} _ { t } ( G _ { [ a , t ] } ( i ) + G _ { [ t , b ] } ( i ) ) \ \tag{2} t^i=argmint(G[a,t](i)+G[t,b](i)) (2)
p [ a , b ] ( i ) p _ { [ a , b ] } ( i ) p[a,b](i)为在 a , b a, b a,b间预测为页面 i i i的概率。 t t t为最好的分割位置。
STEP6: 通过STEP5得到将markdown的段落以页划分。但这是段落级别的划分,字符始末位置与PDF任有差异,需要进一步修正。核心思想为(详细实现参考代码,此处省略了很多细节,仅用于理解):
STEP7: 在每页markdown末尾添加预处理产出的表格、图片信息。
训练中的数据增强没太多可以介绍的,就是一些常规的方式。
Nougat描绘了这么一个愿景,用一个端到端的方式来实现过去繁琐的数据加工pipeline。但目前尝试来看,并不适用实际场景,主要有以下几点缺陷
Liu, Ze, et al. “Swin transformer: Hierarchical vision transformer using shifted windows.” Proceedings of the IEEE/CVF international conference on computer vision. 2021. ↩︎
Liu, Yinhan, et al. “Multilingual denoising pre-training for neural machine translation.” Transactions of the Association for Computational Linguistics 8 (2020): 726-742. ↩︎
Ali Furkan Biten, Rub` en Tito, Lluis Gomez, Ernest Valveny, and Dimosthenis Karatzas. OCR-IDL: OCR Annotations for Industry Document Library Dataset, February 2022. ↩︎
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。