Hugging Face Transformers 中的 BROS 模型面向文档关键信息抽取KIE的文本与布局联合预训练语言模型【免费下载链接】transformers Transformers: the model-definition framework for state-of-the-art machine learning models in text, vision, audio, and multimodal models, for both inference and training.项目地址: https://gitcode.com/GitHub_Trending/tra/transformers导读BROSBERT Relying On Spatially是一个仅编码器encoder-only的 Transformer 预训练语言模型专门为文档图像上的关键信息抽取Key Information Extraction, KIE设计它接收「文本 token 序列 每个 token 的边界框bounding box」作为输入输出一系列隐藏状态并通过相对空间位置编码与区域掩码语言建模Area-Masked Language Modeling, AMLM两大核心机制在不依赖显式视觉特征的前提下理解二维空间中的文档语义。本文以 Transformers 仓库中的 BROS 官方文档为主体结合 模型实现、配置定义、处理器 与 测试用例 源码系统讲解 BROS 的架构设计、预训练目标、三种下游任务头Token 分类、SPADE-EE 实体抽取、SPADE-EL 实体链接、边界框预处理与box_first_token_mask构造方法以及完整的代码级使用示例帮助读者在发票、收据、表单等文档理解任务中直接落地 BROS。一、BROS 是什么从论文到仓库实现BROS 模型由 Teakgyu Hong、Donghyun Kim、Mingi Ji、Wonseok Hwang、Daehyun Nam、Sungrae Park 在论文《BROS: A Pre-trained Language Model Focusing on Text and Layout for Better Key Information Extraction from Documents》中提出仓库文档记录其论文发布于 2021-08-10并在 2023-09-15 由 jinho8345 贡献到 Hugging Face Transformers。模型代码由BrosModel、BrosForTokenClassification、BrosSpadeEEForTokenClassification、BrosSpadeELForTokenClassification四部分组成全部实现在 modeling_bros.py 中此外仓库还提供了 checkpoint 转换脚本用于将原始 clovaai/bros 的权重转换到 Transformers 格式。1.1 核心思想编码相对空间信息BROS 全称BERT Relying On Spatiality。与传统 LayoutLM 系列直接把绝对坐标拼接进 embedding 的做法不同BROS 在自注意力计算内部编码 token 之间的相对空间关系每个 token 与其余 token 构成两两相对坐标对再通过正弦位置编码sinusoid embedding与线性投影生成空间偏置项直接叠加到注意力分数上。从源码可以看到这一机制的完整链路modeling_bros.pyBrosPositionalEmbedding1DL67-L85参考 Transformer-XL 的相对位置编码思路对一维坐标序列计算正弦/余弦嵌入BrosPositionalEmbedding2DL88-L104将边界框的 8 个坐标分量交替送入 x/y 一维编码器偶数维走 x、奇数维走 y拼接出二维空间位置嵌入BrosBboxEmbeddingsL107-L119计算bbox的转置差分bbox_t[None, :, :, :] - bbox_t[:, None, :, :]即得到 token i 与 token j 的相对坐标差再经正弦编码与线性投影bbox_projection产出最终的空间偏置BrosSelfAttention.forwardL231-L237通过torch.einsum(bnid,bijd-bnij, (query_layer, bbox_pos_emb))计算空间偏置分数并叠加到原始注意力分数上attention_scores attention_scores bbox_pos_scores。由此BROS 的注意力分数同时包含「语义相关性」与「空间相对位置」模型可以学会「同一列/同一行的 token 更相关」这类二维布局语义。1.2 两个预训练目标TMLM 与 AMLMBROS 使用两个目标进行预训练TMLMToken-Masked Language Modeling与 BERT 相同的 token 掩码语言建模。随机掩码部分 token模型利用空间信息与其他未掩码 token 预测被掩码 token。AMLMArea-Masked Language ModelingTMLM 的 2D 版本。区别在于 AMLM 掩码的单位是**文本块区域**而非单个 token——整块区域的文本被掩码模型再基于周围文本与布局进行预测。这种掩码策略迫使模型学习区块级如「发票号」这类字段区域的语义结构与文档 KIE 任务中「按区域抽取字段」的需求天然对齐。论文摘要指出BROS 通过「文本 布局的有效组合」这一回归本质的思路在 FUNSD、SROIE*、CORD、SciTSR 四个 KIE 基准上在不依赖视觉特征的情况下取得了与以往方法相当或更好的结果并揭示了 KIE 的两大现实挑战——(1) 错误文本排序带来的误差最小化(2) 从少量下游样本中高效学习。注意以上论文结论来自仓库文档对论文摘要的引用属于论文声明内容具体数值请以论文原文为准仓库源码本身不包含基准测试数据。二、模型家族三种下游任务头BROS 在仓库中提供了 4 个类围绕 KIE 的三个子任务展开modeling_bros.py 中均有完整实现并在 test_modeling_bros.py 中有对应测试覆盖。2.1 BrosModel骨干编码器BrosModel是 BROS 的基础模型由三部分组成modeling_bros.py L509-L513BrosTextEmbeddings文本 embeddingword / position / token_type 三路求和 LayerNorm Dropout结构与 BERT 一致BrosBboxEmbeddings相对边界框位置编码模块见上文BrosEncoder堆叠num_hidden_layers层BrosLayer每层包含带空间偏置的BrosSelfAttention与 FFN。forward接受input_ids、bbox、attention_mask、token_type_ids、position_ids、inputs_embeds等输入。其中bbox是必填项不传会直接抛出ValueError(You have to specify bbox)L563-L564若bbox每个 token 只有 4 个坐标x0, y0, x1, y1forward内部会通过bbox[:, :, [0, 1, 2, 1, 2, 3, 0, 3]]自动扩展为 8 个坐标左上、右上、右下、左下四角用于二维位置编码L594-L595坐标会乘以config.bbox_scale默认 100.0后再送入位置编码L596。2.2 BrosForTokenClassification经典序列标注BrosForTokenClassification在BrosModel之上加一个简单的线性分类层modeling_bros.py L620-L708为每个 token 预测标签对应文档 NER/序列标注任务。它假设输入 token 已被完美串行化perfectly serialized——即按正确的二维阅读顺序排好这对于存在于 2D 空间的文档文本是很有挑战性的前置条件。损失计算时L692-L701若提供了bbox_first_token_mask则只对每个边界框的首 token计算交叉熵损失从而避免同一框内因分词产生的子 token 重复计损。2.3 BrosSpadeEEForTokenClassificationSPADE 实体抽取BrosSpadeEEForTokenClassificationEE Entity Extraction采用 SPADE 的两阶段解码思想modeling_bros.py L720-L854initial_token_classifier预测每个实体的首 token两层 MLP 结构源码 L736-L741subsequent_token_classifier基于BrosRelationExtractor预测实体内部「下一个 token」的链接关系L744。前向时initial_token_logits与subsequent_token_logits分别输出损失为两者之和L846loss initial_token_loss subsequent_token_loss。由于它是「从一个 token 预测下一个连接 token」对文本排序错误具有更强的鲁棒性——这正是它与BrosForTokenClassification的本质区别后者依赖完美串行化前者通过 token 到 token 的链接逐步构建实体。2.4 BrosSpadeELForTokenClassificationSPADE 实体链接BrosSpadeELForTokenClassificationEL Entity Linking在BrosModel之上放置一个entity_linker同样是BrosRelationExtractormodeling_bros.py L876用于实体间关系预测当两个实体共享某种关系时预测从一个实体的某个 token 指向另一个实体某个 token 的链接即完成文档关系抽取如「供应商」→「发票号」。BrosRelationExtractorL406-L437是 SPADE 两个头共用的核心组件其内部包含query、key两个线性层以及一个可学习的dummy_node哑节点用于支持「无关系/指向空」的预测输出形状为(n_relations, batch, seq, seq)的关系分数矩阵推理时计算 query 与 key拼接 dummy node 后的矩阵乘。2.5 三个分类头的选择建议模型类任务对串行化错误的鲁棒性输出BrosForTokenClassification每 token 打标签经典序列标注低依赖完美串行化logitsBrosSpadeEEForTokenClassification实体抽取首 token 后续 token 链接高逐 token 链接构建实体initial_token_logitssubsequent_token_logitsBrosSpadeELForTokenClassification实体间关系/链接预测高关系分数矩阵logits三、输入准备边界框归一化与 box_first_token_mask3.1 边界框的获取与归一化BrosModel.forward需要input_ids与bbox两个核心输入modeling_bros.py L527-L564。每个边界框采用(x0, y0, x1, y1)格式即左上角与右下角。边界框的获取依赖外部 OCR 系统Transformers 仓库本身不提供 OCR 能力文档要求坐标满足归一化约束x坐标用文档图像宽度归一化y坐标用文档图像高度归一化归一化后坐标落在0 ~ 1区间。原文档给出的归一化函数如下注意原文档代码中width/height为外部传入变量实际使用时请以函数入参doc_width/doc_height为准def expand_and_normalize_bbox(bboxes, doc_width, doc_height): # here, bboxes are numpy array # Normalize bbox - 0 ~ 1 bboxes[:, [0, 2]] bboxes[:, [0, 2]] / doc_width bboxes[:, [1, 3]] bboxes[:, [1, 3]] / doc_height从实现看归一化后的坐标会被config.bbox_scale默认 100.0放大modeling_bros.py L596因此输入坐标并不强制为 0~1只要全序列尺度一致即可但遵循文档的 0~1 归一化约定是与预训练 checkpoint 保持行为一致的最稳妥做法。3.2 构造 box_first_token_mask对于BrosForTokenClassification、BrosSpadeEEForTokenClassification、BrosSpadeELForTokenClassification损失计算需要第三个关键输入box_first_token_maskmodeling_bros.py 中三个 forward 均有该参数L643、L755、L887。它的作用是把每个边界框内除首 token 之外的子 token 排除在损失之外——因为一个词一个框可能被分词器切成多个子 token只有框首 token 携带该词的完整语义标签。文档给出了标准的构造方法对每个词单独encode不加特殊 token累加各词 token 数得到每个框的起止索引再截断到max_seq_length范围内把「框首 token 位置」置为 Truedef make_box_first_token_mask(bboxes, words, tokenizer, max_seq_length512): box_first_token_mask np.zeros(max_seq_length, dtypenp.bool_) # encode(tokenize) each word from words (list[str]) input_ids_list: list[list[int]] [tokenizer.encode(e, add_special_tokensFalse) for e in words] # get the length of each box tokens_length_list: list[int] [len(l) for l in input_ids_list] box_end_token_indices np.array(list(itertools.accumulate(tokens_length_list))) box_start_token_indices box_end_token_indices - np.array(tokens_length_list) # filter out the indices that are out of max_seq_length box_end_token_indices box_end_token_indices[box_end_token_indices max_seq_length - 1] if len(box_start_token_indices) len(box_end_token_indices): box_start_token_indices box_start_token_indices[: len(box_end_token_indices)] # set box_start_token_indices to True box_first_token_mask[box_start_token_indices] True return box_first_token_mask该 mask 在三个头中的用法与源码位置BrosForTokenClassification损失只统计被 mask 选中的 tokenL695-L699BrosSpadeEEForTokenClassificationinitial_token_loss只在框首 token 上计算L831-L838subsequent_token_loss通过subsequent_token_mask即 attention_mask统计L840-L844BrosSpadeELForTokenClassification用 mask 过滤「非框首 token 不能作为关系起点/终点」并对自环self-token做掩码L943-L956。四、BrosConfig关键配置项BrosConfig继承自PreTrainedConfig定义在 configuration_bros.pymodel_type bros。除 BERT 风格的标准超参数vocab_size30522、hidden_size768、num_hidden_layers12、num_attention_heads12、intermediate_size3072、hidden_actgelu、max_position_embeddings512、type_vocab_size2、pad_token_id0等外BROS 特有配置如下配置项默认值说明dim_bbox8边界框坐标维度即每个 token 的 8 个坐标值x0, y1, x1, y0, x1, y1, x0, y1 四角展开bbox_scale100.0边界框坐标的缩放系数前向时scaled_bbox bbox * bbox_scalemodeling_bros.py L596n_relations1SPADE-EE / SPADE-EL 头的关系数量classifier_dropout_prob0.1分类头 dropout 概率此外__post_init__会自动派生三个内部维度configuration_bros.py L70-L74dim_bbox_sinusoid_emb_2d hidden_size // 4 192dim_bbox_sinusoid_emb_1d dim_bbox_sinusoid_emb_2d // dim_bbox 24dim_bbox_projection hidden_size // num_attention_heads 64即注意力头维度空间嵌入投影到与 attention head 相同的维度以便相加。配置类自带的标准用法与BrosModel配合 from transformers import BrosConfig, BrosModel # Initializing a BROS jinho8345/bros-base-uncased style configuration configuration BrosConfig() # Initializing a model from the jinho8345/bros-base-uncased style configuration model BrosModel(configuration) # Accessing the model configuration configuration model.config五、BrosProcessor文本预处理入口BrosProcessor定义在 processing_bros.py继承ProcessorMixin本质是对 tokenizer 的轻量封装构造时必须传入tokenizer否则抛出ValueError(You need to specify a tokenizer.)。默认的文本处理参数为add_special_tokensTrue、paddingFalse、stride0、return_overflowing_tokensFalse等。注意BrosProcessor 只负责文本侧tokenize处理边界框 bbox 需要用户自行组织。官方使用示例中通过torch.tensor(...).repeat(...)手工构造与 token 序列等长的 bbox 张量。六、完整使用示例6.1 从预训练 checkpoint 加载并使用 BrosModel以下代码来自BrosModel.forward的 docstring 示例modeling_bros.py L545-L559可直接运行 import torch from transformers import BrosProcessor, BrosModel processor BrosProcessor.from_pretrained(jinho8345/bros-base-uncased) model BrosModel.from_pretrained(jinho8345/bros-base-uncased) encoding processor(Hello, my dog is cute, add_special_tokensFalse, return_tensorspt) bbox torch.tensor([[[0, 0, 1, 1]]]).repeat(1, encoding[input_ids].shape[-1], 1) encoding[bbox] bbox outputs model(**encoding) last_hidden_states outputs.last_hidden_state6.2 使用三种分类头三个分类头的加载方式与输入组织完全一致区别仅在输出字段 import torch from transformers import BrosProcessor, BrosForTokenClassification processor BrosProcessor.from_pretrained(jinho8345/bros-base-uncased) model BrosForTokenClassification.from_pretrained(jinho8345/bros-base-uncased) encoding processor(Hello, my dog is cute, add_special_tokensFalse, return_tensorspt) bbox torch.tensor([[[0, 0, 1, 1]]]).repeat(1, encoding[input_ids].shape[-1], 1) encoding[bbox] bbox outputs model(**encoding)将BrosForTokenClassification替换为BrosSpadeEEForTokenClassification可得到initial_token_logits与subsequent_token_logitsBrosSpadeOutput结构见 modeling_bros.py L49-L64替换为BrosSpadeELForTokenClassification则输出实体链接的关系分数矩阵。训练时分别传入labelsToken 分类 / EL或initial_token_labelssubsequent_token_labelsEE即可自动计算损失。6.3 真实文档的完整数据管线将以上要素组合一个真实的 BROS 文档 KIE 数据管线为OCR用外部 OCR 系统如 Tesseract、PaddleOCR 等识别文档图像得到words词文本列表与bboxes每词边界框像素坐标归一化用expand_and_normalize_bbox按图像宽高把坐标缩放到 0~1序列化按阅读顺序通常按 y 行、x 列排序把词串成序列分词用 tokenizer 把每个词编码为子 token拼接成input_ids同时记录每词的 token 起止索引构造 mask用make_box_first_token_mask生成box_first_token_mask组织 bbox把每个词的边界框按 token 展开对齐到序列长度一个词的所有子 token 共享同一 bbox前向/训练model(input_ids, bbox..., attention_mask..., bbox_first_token_mask..., labels...)。七、源码级验证测试覆盖与 checkpoint 转换7.1 测试覆盖test_modeling_bros.py 提供了完整的模型测试套件BrosModelTester对 bbox 的合法性做了约束保证 x1 x0、y1 y0见 L91-L102并默认启用bbox_first_token_mask、token_type_ids、labels等输入测试覆盖BrosModel、BrosForTokenClassification、BrosSpadeEEForTokenClassification、BrosSpadeELForTokenClassification四个类的前向与损失计算可作为自定义微调时的输入格式参照。7.2 checkpoint 转换convert_bros_to_pytorch.py 演示了从原始 clovaai/bros 仓库权重转换到 Transformers 格式的关键步骤键名重命名如embeddings.bbox_projection.weight→bbox_embeddings.bbox_projection.weight、剔除无需加载的键如embeddings.bbox_sinusoid_emb.inv_freq因为inv_freq作为 buffer 由模型自行初始化随后load_state_dict并验证输出一致性。如果你需要把自训练的原始 BROS 权重接入 Transformers 生态可参考该脚本。八、适用场景与局限8.1 适用场景文档 NER / 序列标注发票、收据、表单、证件等扫描件的字段抽取BrosForTokenClassification实体抽取对文本排序错误鲁棒的端到端实体识别BrosSpadeEEForTokenClassification实体链接 / 关系抽取字段之间关系的预测如「开票方」与「发票号」的关联BrosSpadeELForTokenClassification文档理解研究作为文本 布局联合建模的基线模型对比 LayoutLM 等视觉-文本多模态方案。8.2 局限与前提依赖外部 OCRbbox 必须由外部 OCR 系统提供模型本身不做版面分析或文字识别序列化假设BrosForTokenClassification依赖 token 的完美串行化实际使用时需配合稳健的阅读顺序排序输入约束坐标需按文档宽高归一化bbox 为必填输入序列长度受max_position_embeddings默认 512限制论文结论边界FUNSD / SROIE / CORD / SciTSR 上的性能结论来自论文原文声明仓库源码不内置这些基准的复现数据。参考资源仓库内模型实现四类模型完整 PyTorch 实现与空间位置编码细节配置定义BrosConfig及 BROS 特有超参数处理器BrosProcessor文本预处理checkpoint 转换脚本原始权重到 Transformers 格式的转换参考模型测试四个模型类的输入输出与损失计算验证英文官方文档与本文同源的其他语言版本【免费下载链接】transformers Transformers: the model-definition framework for state-of-the-art machine learning models in text, vision, audio, and multimodal models, for both inference and training.项目地址: https://gitcode.com/GitHub_Trending/tra/transformers创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考