NLP专栏简介:数据增强、智能标注、意图识别算法|多分类算法、文本信息抽取、多模态信息抽取、可解释性分析、性能调优、模型压缩算法等
专栏详细介绍:NLP专栏简介:数据增强、智能标注、意图识别算法|多分类算法、文本信息抽取、多模态信息抽取、可解释性分析、性能调优、模型压缩算法等
前人栽树后人乘凉,本专栏提供资料:数据增强、智能标注、意图识别算法|多分类算法、文本信息抽取、多模态信息抽取、可解释性分析、性能调优、模型压缩算法等项目代码整合,省去你大把时间,效率提升。 帮助你快速完成任务落地,以及科研baseline。
文档级关系抽取:基于结构先验产生注意力偏差SSAN模型
Entity Structure Within and Throughout: Modeling Mention Dependencies for Document-Level Relation Extraction
实体作为关系抽取任务的基本要素,具有一定的结构。在这项工作中,将这种结构表述为提及对之间的独特依赖关系。提出了SSAN (Structured Self-Attention Network) ,它将这些结构依赖性纳入标准的自我注意机制和整个编码阶段。在每个自注意力构建块内设计了两个替代转换模块,以产生注意力偏差,从而自适应地调整其注意力流。实验证明了所提出的实体结构的有用性和 SSAN 的有效性。
参考链接:
https://arxiv.org/abs/2102.10249
https://github.com/PaddlePaddle/Research/tree/master/KG/AAAI2021_SSAN
https://github.com/PaddlePaddle/ERNIE/tree/repro
0.相关知识补充
0.1 信息抽取面临困难
文档级关系抽取主要面临以下三个挑战:
- 相同关系会出现在多个句子。在文档级关系抽取中,单一关系可能出现在多个输入的句子中,因此模型需要依赖多个句子进行关系推断。
- 相同实体会具有多个指称。在复杂的文档中,同一个实体具有各种各样的指称,因此模型需要聚合不同的指称学习实体表示。
- 不同的实体之间的关系需要逻辑推理。文档包含多个实体关系三元组,不同的实体关系三元组之间存在逻辑关联,因此模型需要具备一定的逻辑推理能力。
信息抽取是构建大规模知识图谱的必备关键,先来说一下图谱的三元组形式,在以往常常将三元组以 (head,relation, tail) 的形式表示,在这里以(subject, relation, object)的形式表示,即(S, R,O),为了方便描述,后文将以这种形式阐述。
信息抽取分为两大部分,一部分是命名实体识别,识别出文本中的实体,另外就是关系抽取,对识别出来的实体构建对应的关系,两者便是构建三元组的基本组成。在以往的研究工作中,早期两个任务以pipline的方式进行,先做命名实体识别,然后做关系抽取。但是pipline的流程可能造成实体的识别错误,也就造成关系构建的错误,所以后续的一些研究工作将两者采用联合学习的方式。
但是上述存在很少的研究工作解决三元组重叠的问题:
- Normal: 代表没有重叠的部分。
- EPO(EntityPairOverlap): 关系两端的实体都是一致的,例如 QT 既在电影 DU 中扮演角色,又是电影 DU 的执导。
- SEO(SingleEntityOverlap): 关系两端只有单个实体共享,图中的例子,从小范围来说,JRB 出生在 Washington, 但是 Washington 是 USA 的首都,所以也可以说 JRB 出生在 USA。
以往工作的不足以及重叠三元组出现的挑战:
- 在实体对的组合之中,大多数实体对是没有关系链接的,这便存在很多的负例,也就造成了关系分类的不平衡。
- 重叠三元组的问题更是一个难点,因为其存在共享的实体,甚至两个实体存在多种关系,这便增加了难度,没有足够的训练数据,是难以学习或者根本无法学习这种关系的。
0.2 如何去解决
思想:采用全新的视角代替以往分类的视角,将关系建模为 S 到 O 的映射函数。提出一个全新的框架:CASREL。
ACL2020 关系抽取框架 :A Novel Cascade Binary Tagging Framework for Relational Triple Extraction (一种用于关系三元组提取的新型级联二元标签框架)
论文链接:https://aclanthology.org/2020.acl-main.136/
从非结构化文本中提取关系型三元组对于大规模知识图谱的构建至关重要。然而,现有的工作在解决重叠三联体问题上表现出色,即同一句子中的多个关系三联体共享相同的实体。引入了一个新的视角来重新审视关系型三联体的提取任务,并提出了一个新颖的级联二元标签框架(CasRel),该框架源自一个原则性的问题表述。新框架没有像以前的工作那样将关系视为离散的标签,而是将关系建模为函数,将句子中的主体映射到对象,这就自然地处理了重叠问题。实验表明,即使在其编码器模块使用随机初始化的BERT编码器时,CasRel框架已经超过了最先进的方法,显示了新标签框架的力量。当采用预训练的BERT编码器时,它的性能得到了进一步的提升,在两个公共数据集NYT和WebNLG上的F1分数绝对值分别比最强的基线高出17.5和30.2。
框架详解
CASREL框架抽取三元组(subject, relation, object)主要包含两个步骤,三个部分。
两个步骤:
第一步要识别出句子中的 subject 。
第二部要根据识别出的 subject, 识别出所有有可能的 relation 以及对应的 object。
三个部分:
BERT-based encoder module: 可以替换为不同的编码框架,主要对句子中的词进行编码,论文最终以BERT为主,效果很强。
subject tagging module:目的是识别出句子中的 subject。
relation-specific object tagging module:根据 subject,寻找可能的 relation 和 object。
其中 a 是 Encoder, b 和 c 称为 Cascade Decoder
BERT Encoder
这部分的就是对句子编码,获取每个词的隐层表示,可以采用 BERT 的任意一层,另外这部分是可以替换的,例如用 LSTM 替换 BERT。
Subject Tagger
这部分的主要作用是对 BERT Encoder 获取到的词的隐层表示解码,构建两个二分类分类器预测 subject 的 start 和 end 索引位置,对每一个词计算其作为 start 和 end 的一个概率,并根据某个阈值,大于则标记为1,否则标记为0
如框架图中所示,Jackie 被标记为 start,R 既不是 start 也不是 end, Brown 被标记为 end,其他的类似。在这里采用了最近匹配的原则,即与 jackie 最近的一个 end 词是 Brown, 所以 Jackie R. Brown 被识别为一个subject。文中并未考虑前面位置的情况。
Relation-specific Object Taggers
这部分会同时识别出 subject 的 relation 和相关的 object。
解码的时候比 Subject Tagger 不仅仅考虑了 BERT 编码的隐层向量, 还考虑了识别出来的 subject 特征,即下图。vsub 代表 subject 特征向量,若存在多个词,将其取向量平均,hn 代表 BERT 编码向量。
我们以图中的例子详细说明一下,图中的例子仅仅画出了第一个 subject 的过程,即 Jackie R. Brown,对于这个,在关系 Birth_place 中识别出了两个 object,即 Washington 和 United States Of America,而在其他的关系中未曾识别出相应的 object。当对 Washington 这个 subject 解码时,仅仅在 Capital_of 的关系中识别出 对应的 object: United States Of America。
以上我们便可以得到抽取到的三个三元组如下:
(Jackie R. Brown, Birth_place, Washington)
(Jackie R. Brown, Birth_place, United States Of America)
(Washington, Capital_of, United States Of America)
从以上抽取出来的三元组,确实解决了最开始提到的 SEO 和 EPO 的重叠问题。
实验效果
验证CASREL框架效果采用的是两个公开的数据集,NYT 和 WebNLG。
具体的实验效果如下,其中 CASREL 分别采用了 随机初始化参数的BERT编码端、 LSTM 编码端以及预训练 BERT 编码端,实验结果主要说明以下结论:
- CASREL 框架确实有效,三种编码结构的效果都是要远高于其他的模型性能。
- 采用预训练 BERT 之后,CASREL 框架更是逆天。
0.3相关领域经典文章推荐:
知识图谱 (KGs) 在工业和学术环境中发现了许多应用,这反过来又推动了从各种来源进行大规模信息提取的大量研究工作。尽管做出了这些努力,但众所周知,即使是最先进的 KG 也存在不完整的问题。链接预测 (LP) 是在已经是 KG 的实体中预测缺失事实的任务,是一项有前途且被广泛研究的任务,旨在解决 KG 的不完整性。在最近的 LP 技术中,基于 KG 嵌入的技术在一些基准测试中取得了非常有希望的性能。尽管该主题的文献快速增长,但对这些方法中各种设计选择的影响关注不足。而且,该领域的标准做法是通过汇总大量测试事实来报告准确性,其中某些实体被过度代表;这允许 LP 方法通过只关注包含此类实体的结构属性来展示良好的性能,同时忽略 KG 的剩余大部分。该分析提供了基于嵌入的 LP 方法的全面比较,将分析的维度扩展到了文献中通常可用的范围之外。我们通过实验比较了 16 种最先进方法的有效性和效率,考虑了基于规则的基线,并报告了对文献中最流行的基准的详细分析。这允许 LP 方法通过只关注包含此类实体的结构属性来展示良好的性能,同时忽略 KG 的剩余大部分。该分析提供了基于嵌入的 LP 方法的全面比较,将分析的维度扩展到了文献中通常可用的范围之外。我们通过实验比较了 16 种最先进方法的有效性和效率,考虑了基于规则的基线,并报告了对文献中最流行的基准的详细分析。这允许 LP 方法通过只关注包含此类实体的结构属性来展示良好的性能,同时忽略 KG 的剩余大部分。该分析提供了基于嵌入的 LP 方法的全面比较,将分析的维度扩展到了文献中通常可用的范围之外。我们通过实验比较了 16 种最先进方法的有效性和效率,考虑了基于规则的基线,并报告了对文献中最流行的基准的详细分析。
知识图谱支持广泛的应用,包括问答和信息检索。尽管在它们的创建和维护上投入了巨大的努力,但即使是最大的(例如,Yago、DBPedia 或 Wikidata)仍然不完整。我们引入了关系图卷积网络(R-GCNs)并将它们应用于两个标准的知识库完成任务:链接预测(缺失事实的恢复,即主体-谓词-对象三元组)和实体分类(缺失实体属性的恢复)。R-GCNs 与最近一类在图上运行的神经网络有关,并且是专门为处理现实知识库的高度多关系数据特征而开发的。我们证明了 R-GCNs 作为实体分类的独立模型的有效性。
为了完成上述任务,这篇论文实现:
实体分类模型:图中每个结点使用softmax分类器,分类器接受RGCN提供的结点表示,并且进行预测标签。
链路预测模型:编码器,RGCN产生实体潜在特征表示;解码器,一个张量因子分解模型利用这些表示来预测标记的边缘,因式分解方法:distmult.
主要贡献:
- 1.是第一个证明GCN框架可以应用于关系数据建模的人,特别是链接预测和实体分类任务。
- 2.引入了参数共享和加强稀疏约束的技术,并利用它们将R-GCNs应用于具有大量关系的多图。
- 3.以DistMult为例,作者证明了因子分解模型的性能可以通过在关系图中执行多个信息传播步骤的编码器模型来丰富它们
我们考虑使用神经嵌入方法学习知识库中实体和关系的表示。我们展示了大多数现有模型,包括 NTN (Socher et al., 2013) 和 TransE (Bordes et al., 2013b),可以在统一的学习框架下进行泛化,其中实体是从神经网络学习的低维向量,并且关系是双线性和/或线性映射函数。在这个框架下,我们比较了链接预测任务上的各种嵌入模型。我们展示了一个简单的双线性公式为该任务实现了新的最先进的结果(在 Freebase 上实现了 73.2% 与 54.7% 的前 10 名准确率)。此外,我们引入了一种新颖的方法,该方法利用学习到的关系嵌入来挖掘逻辑规则,例如“BornInCity(a,b) 和 CityInCountry(b,c) => Nationality(a,c)”。我们发现从双线性目标中学习的嵌入特别擅长捕捉关系语义,并且关系的组合以矩阵乘法为特征。更有趣的是,我们证明了我们的基于嵌入的规则提取方法在挖掘涉及组合推理的 Horn 规则时成功地优于最先进的基于置信度的规则挖掘方法。
- 3.1 推理任务一:链接预测
破坏掉三元组,对于测试数据中的每个三元组,我们将每个实体视为要依次预测的目标实体。将为字典中正确的实体和所有损坏的实体计算分数,并按降序排列。采用hit@n,mrr,mr等信息作为评估方式。
其在实现时,提出一些改善
相比于TransE这种模型,引用了非线性函数t a n h tanhtanh函数
使用了预训练的方法进行embedding,通过word2vec方式
- 3.2 推理任务二:规则抽取
规则抽取,这种逻辑规则有四个重要目的,其目的如下:
- 首先,他们可以帮助推断新的事实,完善现有的K B s KBsKBs。
- 其次,它们可以通过只存储规则而不是大量的扩展数据来帮助优化数据存储,并且只在推理时生成事实。
- 第三,它们可以支持复杂的推理。
- 最后,它们可以为推理结果提供解释,例如,我们可以推断人们的职业通常涉及他们研究的领域的专业化,等等。
1.数据集介绍和获取
目前文档级关系抽取有三个公开的学术的数据集,分别是 CDR、GDA 以及清华大学团队发布的 DocRED。
- CDR是生物领域的一个人工标注的一个数据集,其任务是预测化学和疾病概念之间的二元相互作用,包含了 500 多篇训练文章;(20MB)
- GDA 也是一个生物医学领域的大规模数据集,其任务主要是预测基因和疾病概念之间的二元相互作用,由 2 万~3 万篇训练文档组成;相对而言,(568MB)
- DocRED 是一个比较新的大规模的众包数据集。其原始语料主要基于维基百科,包含了 3053 份文章,其中大约存在 7% 的实体,DocRED 还提供了公开的 leaderboard,用户可将模型预测的结果上传,评估文档级关系抽取的各种性能。(160MB)
目前,针对这种文档及关系抽取,主要有两类研究方法,一类是基于文档图的方法;另一类是基于序列的方法,基于 Transformer 等模型来进行文档级的关系抽取。
1.1 DocRED数据集
DocRED: A Large-Scale Document-Level Relation Extraction Dataset:
2019年的ACL上清华大学刘知远团队提出了一个关系抽取数据集DocRED[1],为文档级关系抽取的研究提供了一个非常好的标注数据集。DocRED包含对超过5000篇Wikipedia文章的标注,包括96种关系类型、143,375个实体和56,354个关系事实,这在规模上超越了以往的同类精标注数据集。与传统的基于单句的关系抽取数据集相比,DocRED中超过40%的关系事实只能从多个句子中联合抽取,因此需要模型具备较强的获取和综合文章中信息的能力,尤其是抽取跨句关系的能力。DocRED还有一个在线的Leaderboard
排行榜如下:
下载一下即可。
1.2 CDR&GDA数据集:
CDR是生物医学领域的人类标注的化学疾病关系抽取数据集,由500份文档组成,该数据集的任务是预测化学和疾病概念之间的二元相互作用关系。
GDA是生物医学领域的一个大规模数据集,它包含29192篇文档以供训练,其任务是预测基因和疾病概念之间的二元相互作用。
文档级关系抽取方法归纳-参考链接:
这里为了大家方便,我已经把DocRED和GDA数据集进行挂载了,只需要下载比较小的CDR数据集即可,数据集都在data_1
#DocRED数据集直接上传见文件夹或自行下载:
# https://drive.google.com/drive/folders/1c5-0YwnoJx8NS6CV2f-NoTHR__BdkNqw?usp=sharing
!mkdir data_1 && cd data_1/
!wget https://biocreative.bioinformatics.udel.edu/media/store/files/2016/CDR_Data.zip && unzip CDR_Data.zip && mv CDR_Data CDR
!wget https://bitbucket.org/alexwuhkucs/gda-extraction/get/fd4a7409365e.zip && unzip fd4a7409365e.zip && mv alexwuhkucs-gda-extraction-fd4a7409365e GDA
!cd ..
#注意:如果觉得下载太慢的话,就本地下载完上传即可
#解压挂载数据,已注释
# !unzip -d /home/aistudio/data_1/GDA /home/aistudio/data/data172989/fd4a7409365e.zip
# !unzip -d /home/aistudio/data_1/ /home/aistudio/data/data172987/DocRED-20221017T064209Z-001.zip
!cp -R /home/aistudio/data_1/DocRED/* /home/aistudio/data
!cp -R /home/aistudio/label_map.json /home/aistudio/data
2. 模型训练
2.1加载模型
%cd ./pretrained_lm/
!wget https://ernie.bj.bcebos.com/ERNIE_Base_en_stable-2.0.0.tar.gz
!mkdir -p ./ernie2_base_en && tar -zxvf ERNIE_Base_en_stable-2.0.0.tar.gz -C ./ernie2_base_en
!wget https://ernie.bj.bcebos.com/ERNIE_Large_en_stable-2.0.0.tar.gz
!mkdir -p ./ernie2_large_en && tar -zxvf ERNIE_Large_en_stable-2.0.0.tar.gz -C ./ernie2_large_en
2.2 版本迁移工具
如有需要可以自行修改版本代码:paddle 1.x版本迁移2.x
格式兼容问题可参考:
!pip install paddle_upgrade_tool
#查看需要修改代码
# !paddle_upgrade_tool --inpath /home/aistudio/run_ssan.py
#进入终端迁移代码,执行下面命令即可,1.x----》2.x
# !paddle_upgrade_tool --inpath /home/aistudio/run_ssan.py --write
# paddle_upgrade_tool --inpath /home/aistudio/run_ssan.py --write
# paddle_upgrade_tool --inpath /home/aistudio/relation_extraction.py --write
# paddle_upgrade_tool --inpath /home/aistudio/utils/ --write
# paddle_upgrade_tool --inpath /home/aistudio/model/ --write
# paddle_upgrade_tool --inpath /home/aistudio/dataset.py --write
# paddle_upgrade_tool --inpath /opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/fluid/wrapped_decorator.py --write
# paddle_upgrade_tool --inpath /opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/fluid/framework.py --write
2.3训练模型
开始训练运行train shell脚本 自行修改超参数
#!/bin/bash
export FLAGS_eager_delete_tensor_gb=0.0
export FLAGS_sync_nccl_allreduce=1
export DATA_PATH=./data/
export MODEL_PATH=./pretrained_lm/ernie2_base_en
lr=3e-5
batch_size=4
epoch=60
with_ent_structure=true
CUDA_VISIBLE_DEVICES=0 python ./run_ssan.py \
--use_cuda true \
--use_fast_executor ${e_executor:-"true"} \
--tokenizer ${TOKENIZER:-"FullTokenizer"} \
--use_fp16 ${USE_FP16:-"false"} \
--do_train true \
--do_val true \
--do_test false \
--with_ent_structure ${with_ent_structure} \
--model_path ${MODEL_PATH} \
--init_checkpoint ${MODEL_PATH}/params \
--data_path ${DATA_PATH} \
--batch_size ${batch_size} \
--learning_rate ${lr} \
--warmup_proportion 0.1 \
--epoch ${epoch} \
--save_checkpoints ./checkpoints \
--max_seq_len 512 \
--max_ent_cnt 42 \
--num_labels 97 \
--random_seed 42 \
--skip_steps 50 \
--num_iteration_per_drop_scope 1 \
--verbose true \
--weight_decay 0.0
# cd ..
!sh train.sh
部分结果展示
W1102 16:19:04.590329 1287 gpu_resources.cc:61] Please NOTE: device: 0, GPU Compute Capability: 7.0, Driver API Version: 11.2, Runtime API Version: 11.2
W1102 16:19:04.593858 1287 gpu_resources.cc:91] device: 0, cuDNN Version: 8.2.
[INFO] 2022-11-02 16:19:07,225 [ init.py: 64]: Load model from ./pretrained_lm/ernie2_base_en/params
[INFO] 2022-11-02 16:19:28,135 [ run_ssan.py: 250]: train pyreader queue size: 70, learning rate: 0.000000
[INFO] 2022-11-02 16:19:28,135 [ run_ssan.py: 258]: epoch: 0, progress: 488/3053, step: 50, loss: 0.688332, f1: 0.000323, speed: 2.407797 steps/s
[INFO] 2022-11-02 16:19:46,214 [ run_ssan.py: 250]: train pyreader queue size: 70, learning rate: 0.000001
[INFO] 2022-11-02 16:19:46,214 [ run_ssan.py: 258]: epoch: 0, progress: 688/3053, step: 100, loss: 0.647572, f1: 0.000815, speed: 2.765610 steps/s
[INFO] 2022-11-02 16:20:04,534 [ run_ssan.py: 250]: train pyreader queue size: 70, learning rate: 0.000001
[INFO] 2022-11-02 16:20:04,534 [ run_ssan.py: 258]: epoch: 0, progress: 888/3053, step: 150, loss: 0.373605, f1: 0.000923, speed: 2.729235 steps/s
[INFO] 2022-11-02 16:20:22,699 [ run_ssan.py: 250]: train pyreader queue size: 70, learning rate: 0.000001
[INFO] 2022-11-02 16:20:22,700 [ run_ssan.py: 258]: epoch: 0, progress: 1088/3053, step: 200, loss: 0.125506, f1: 0.000000, speed: 2.752515 steps/s
Train and eval SSAN. Model will be saved in ./checkpoints, and the best threshold for relation prediction will be searched on dev set when evaluation.
By default you are running SSAN based on ERNIE Base, set --with_ent_structure to false and the model will fall back to ERNIE Base Baseline. If you want to train ERNIE Large models, just set model path to ./pretrained_lm/ernie2_large_en.
!python -c "import paddle; print(paddle.fluid.core._get_all_register_op_kernels()['matmul'])"
['{data_type[double]; data_layout[Undefined(AnyLayout)]; place[Place(gpu:0)]; library_type[PLAIN]}', '{data_type[float]; data_layout[Undefined(AnyLayout)]; place[Place(gpu:0)]; library_type[PLAIN]}', '{data_type[::paddle::platform::bfloat16]; data_layout[MKLDNN]; place[Place(cpu)]; library_type[MKLDNN]}', '{data_type[::paddle::platform::float16]; data_layout[Undefined(AnyLayout)]; place[Place(gpu:0)]; library_type[PLAIN]}', '{data_type[float]; data_layout[MKLDNN]; place[Place(cpu)]; library_type[MKLDNN]}', '{data_type[double]; data_layout[Undefined(AnyLayout)]; place[Place(cpu)]; library_type[PLAIN]}', '{data_type[uint8_t]; data_layout[MKLDNN]; place[Place(cpu)]; library_type[MKLDNN]}', '{data_type[int8_t]; data_layout[MKLDNN]; place[Place(cpu)]; library_type[MKLDNN]}', '{data_type[float]; data_layout[Undefined(AnyLayout)]; place[Place(cpu)]; library_type[PLAIN]}']
#模型预测
!sh predict.sh
Set your checkpoint directory and threshold for prediction. The result will be saved as ./data/result.json.
You can compress and upload it to the official competition leaderboard at CodaLab.
# %cd ./data/
# !zip result.zip result.json
2.4异常报错合集:参考这里
详细情况可以参考原论文链接:https://github.com/PaddlePaddle/Research/tree/master/KG/AAAI2021_SSAN
修改:数据格式,具体见源文件
.astype(np.float32)
报错信息:
NotFoundError: Operator (matmul) does not have kernel for data_type[int64_t]:data_layout[ANY_LAYOUT]:place[CUDAPlace(0)]:library_type[PLAIN].
[Hint: Expected kernel_iter != kernels.end(), but received kernel_iter == kernels.end().] (at /paddle/paddle/fluid/framework/operator.cc:1236)
[operator < matmul > error]
paddle.matmul(x, y, transpose_x=False, transpose_y=False, name=None)
该op是计算两个Tensor的乘积,遵循完整的广播规则,关于广播规则,请参考 cn_user_guide_broadcasting 。 并且其行为与 numpy.matmul 一致。目前,输入张量的维数可以是任意数量, matmul 可以用于 实现 dot , matmul 和 batchmatmul 。实际行为取决于输入 x 、输入 y 、 transpose_x , transpose_y 。具体如下:
如果 transpose 为真,则对应 Tensor 的后两维会转置。如果Tensor的一维,则转置无效。假定 x 是一个 shape=[D] 的一维 Tensor,则 x 视为 [1, D]。然而, y 是一个shape=[D]的一维Tensor,则视为[D, 1]。
乘法行为取决于 x 和 y 的尺寸。 具体如下:
如果两个张量均为一维,则获得点积结果。
如果两个张量都是二维的,则获得矩阵与矩阵的乘积。
如果 x 是1维的,而 y 是2维的,则将1放在 x 维度之前,以进行矩阵乘法。矩阵相乘后,将删除前置尺寸。
如果 x 是2维的,而 y 是1维的,获得矩阵与向量的乘积。
如果两个输入至少为一维,且至少一个输入为N维(其中N> 2),则将获得批矩阵乘法。 如果第一个自变量是一维的,则将1放在其维度的前面,以便进行批量矩阵的乘法运算,然后将其删除。 如果第二个参数为一维,则将1附加到其维度后面,以实现成批矩阵倍数的目的,然后将其删除。 根据广播规则广播非矩阵维度(不包括最后两个维度)。 例如,如果输入 x 是(j,1,n,m)Tensor,另一个 y 是(k,m,p)Tensor,则out将是(j,k,n,p)张量。
该API通过已知的 data 来创建一个 tensor,tensor类型为 paddle.Tensor。 data 可以是 scalar,tuple,list,numpy.ndarray,paddle.Tensor。
如果 data 已经是一个tensor,且 dtype 、 place 没有发生变化,将不会发生 tensor 的拷贝并返回原来的 tensor。 否则会创建一个新的tensor,且不保留原来计算图。
参数
data (scalar|tuple|list|ndarray|Tensor) - 初始化tensor的数据,可以是 scalar,list,tuple,numpy.ndarray,paddle.Tensor类型。
dtype (str, optional) - 创建tensor的数据类型,可以是 'bool' ,'float16','float32', 'float64' ,'int8','int16','int32','int64','uint8','complex64','complex128'。 默认值为None,如果 data 为python浮点类型,则从 get_default_dtype 获取类型,如果 data 为其他类型, 则会自动推导类型。
place (CPUPlace|CUDAPinnedPlace|CUDAPlace, optional) - 创建tensor的设备位置,可以是 CPUPlace, CUDAPinnedPlace, CUDAPlace。默认值为None,使用全局的place。
stop_gradient (bool, optional) - 是否阻断Autograd的梯度传导。默认值为True,此时不进行梯度传传导。
import paddle
type(paddle.to_tensor(1))
# <class 'paddle.Tensor'>
paddle.to_tensor(1) # allocate on global default place CUDA:0
# Tensor(shape=[1], dtype=int64, place=CUDAPlace(0), stop_gradient=True,
# [1])
x = paddle.to_tensor(1)
paddle.to_tensor(x, dtype='int32', place=paddle.CPUPlace()) # A new tensor will be constructed due to different dtype or place
# Tensor(shape=[1], dtype=int32, place=CPUPlace, stop_gradient=True,
# [1])
paddle.to_tensor((1.1, 2.2), place=paddle.CUDAPinnedPlace())
# Tensor(shape=[2], dtype=float32, place=CUDAPinnedPlace, stop_gradient=True,
# [1.10000002, 2.20000005])
paddle.to_tensor([[0.1, 0.2], [0.3, 0.4]], place=paddle.CUDAPlace(0), stop_gradient=False)
# Tensor(shape=[2, 2], dtype=float32, place=CUDAPlace(0), stop_gradient=False,
# [[0.10000000, 0.20000000],
# [0.30000001, 0.40000001]])
type(paddle.to_tensor([[1+1j, 2], [3+2j, 4]], dtype='complex64'))
# <class 'paddle.Tensor'>
paddle.to_tensor([[1+1j, 2], [3+2j, 4]], dtype='complex64')
# Tensor(shape=[2, 2], dtype=complex64, place=CUDAPlace(0), stop_gradient=True,
# [[(1+1j), (2+0j)],
# [(3+2j), (4+0j)]])
2.5小结
SSAN文档抽取模型是2019的SOTA,复现时候代码版本兼容会有点问题,已经修正了部分。在F1上显示异常,fork项目的小伙伴可以继续修改一下bug,有问题可以评论区一起交流。
官网论文最终结果展示:
实际结果:
Model | Dev F1 | Test Ign F1 | Test F1 |
---|---|---|---|
ERNIE Base Baseline | 58.54 | 58.58 | 57.71 |
SSANBiaffine | 59.12(+0.58) | 57.07(+1.49) | 59.05(+1.34) |
ERNIE Large Baseline | 60.25 | 57.87 | 60.11 |
SSANBiaffine | 61.58(+1.33) | 58.96(+1.09) | 61.17(+1.06) |
learning rate = 3e-5,
batch size = 4,
and search for the best epochs among (40, 60, 80, 100) on development set.
3.总结
总结一下,当前使用基于图和 GNN 的文档级关系抽取方法非常多,但使用何种类型的节点和边需要精巧的人工设计,这一点并不算优雅,这也是 GNN 当前在非图数据上应用普遍存在的一个问题。
另一方面,基于 transformer 的方法,可以通过设计子任务,将更多的全局依存信息,尤其是与位置相关的信息编码进模型,在实际应用中相对较为方便。
关于文档级关系抽取的未来畅想:
- 一、设计文档实体结构相关的预训练。现有的 MLM 预训练目标并不能很好的建模实体及实体间的隐式关联,因此,一个能够显式建模实体及其包含的语义关系的预训练目标可以增强文档的实体的表达能力。目前已经有工作开始尝试基于对比学习设计更好的实体关系预训练模型。
- 二、减轻关系标签分布不平衡。文档级关系抽取中的关系存在明显的长尾分布,且大量的实体间不存在关系,因此类别分布不平衡在一定程度上影响模型效果。已经有工作针对这一问题提出了动态阈值的方法,然而对于长尾部分的关系仍然缺乏较好的模型进行抽取。
- 三、是引入外部知识。语言模型缺乏对实体知识的认知,先前的工作表明注入实体等事实类型知识可以显著提升知识敏感的任务性能,AAAI2021 上有个工作提出了一个注入 Probase 知识库的关系抽取模型,然而知识库存在稀疏性和噪音,更加高效可靠的知识注入方法仍然值得研究。
- 四、设计更好的实体交互模型。目前关系抽取中仅考虑实体对之间的一阶交互,缺乏对多个实体对之间的高阶交互建模。尽管基于文档图的模型在一定程度上使得模型得学习了实体与实体之间的交互信息,然而对于实体图中相聚较远的节点,实体之间缺乏足够的信息流通,制约模型的逻辑推理能力。
目前在知识图谱这个领域主要研究了知识抽取技术,后面将逐步学习更新图计算等,对实体对齐和知识推理进行研究,尝试构建一个小型的领域知识图谱
项目链接
fork 一下就能运行,含GPU算力
https://aistudio.baidu.com/aistudio/projectdetail/4666541?contributionType=1&sUid=691158&shared=1&ts=1680852734697