自然语言推理-文本蕴含识别简介

一 什么是文本蕴含识别

文本间的推理关系,又称为文本蕴含关系 (TextualEntailment),作为一种基本的文本间语义联系,广泛存在于自然语言文本中。简单的来说文本蕴含关系描述的是两个文本之间的推理关系,其中一个文本作为前提(premise),另一个文本作为假设(hypothesis),如果根据前提P能够推理得出假设H,那么就说P蕴含H,记做P\rightarrow H。这跟一阶逻辑中的蕴含关系是类似的。

例子:

这个例子中前提P是“A dog jumping for a Frisbee in the snow”,意思一只狗在雪地中接飞盘玩,同时下面给出了三个假设,这三个假设中前提跟第一个是蕴含关系(entailment),因为这句话描述的是“一个动物正在寒冷室外玩塑料玩具”,这是能够从前提推理出来的;第二句化描述的是“一只猫...”,这跟前提是冲突的(contradiction);第三句话与前提既不是蕴含关系也没有冲突,我们把它定义成中立的(neutral)。

文本蕴含识别(Recognizing Textual Entailment,RTE)主要目标是对前提和假设进行判断,判断其是否具有蕴含关系。文本蕴含识别形式上是一个文本分类的问题,在上面这个例子中是一个三分类的问题,label分别为entailment,contradiction,neutral。

二 文本蕴含识别数据集

2.1 SNLI

SNLI数据主页

The Stanford Natural Language Inference (SNLI) 是斯坦福大学NLP组发布的文本蕴含识别的数据集。SNLI由人工标注的,一共包含570K个文本对,其中训练集550K,验证集10K,测试集10K,一共包含三类entailment,contradiction,neutra,上节提到的例子就是出自此数据集,下图为此数据集例子:

 

2.2 MultiNLI

MultiNLI主页

The Multi-Genre Natural Language Inference (MultiNLI)是一个众包数据集,包含433k个文本对。与SNLI数据集类似,每条数据包含两个文本,第一条文本来从已经存在的语料中获取,例如 Open American National Corpus (OpenANC) 。第二条文本是有人编写的,下面为该数据集的例子:

2.3 其他数据集

Past campaigns data sets

RTE data sets translated in other languages

 

Other data sets

三、文本蕴含识别算法

3.1 基于相似度的方法

构成蕴含关系的两个文本往往比较相似,可以通过计算前提和假设之间的相似度来判断其之间是否构成蕴含关系。这类方法比较直观,在RTE研究领域一度是比较流行的方法,但随着研究的深入,现在更多把相似度作为判别模型中的一个特征。

Jijkoun在论文Recognizing Textual Entailment Using Lexical Similarity中提出了基于词袋模型的文本蕴含识别方法,他的做法时首先对文本进行分词,然后通过词频对单词进行赋权,然后计算Lin-相似度和WordNet相似度,并以此为根据计算相似度。这种方法最终在PASCAL-2005的RTE数据集上accuracy为0.55。

Adams在论文http://u.cs.biu.ac.il/~nlp/RTE2/Proceedings/21.pdf中在Jijkoun词袋模型基础对相似度进行了改造,该方法利用WordNet抽出来的词链来链接前提和假设,并计算两者的编辑距离,最终结合其他特征使用决策树识别蕴含关系。这种方法最终在PASCAL-2005的RTE数据集上accuracy为0.657。

这种基于相似度的方法简单易实现,但这种方法强行假设“相似及蕴含”是有明显缺陷的,这会导致有大量的文本蕴含关系识别错误。

3.2 基于文本对齐的方法

在基于相似度识别方法的基础上演化出了基于文本对齐的方法,这类方法不直接使用相似度判别蕴含关系,这类方法先把前提和假设相似的部分进行对齐,通过对齐的方式和程度作为最后判别是否为蕴含关系的依据。这种方式优点就是能够更好体现两个文本之间的相似度。

Marneffe在论文Finding Contradictions in Text中首先把前提和假设中的词进行对齐,对齐后再加工特征使用逻辑回归进行蕴含分析,这篇论文主要做的是冲突检测,跟前面的蕴含关系识别稍有区别。

基于对齐的方法在相似度的基础删上引入了对齐操作,这样使我们能更加关注前提和假设不相同的部分。对齐方法缺点在于需要引入先验知识进行对齐,并且存在一些一对多、多对多的对齐情况难以操作。

3.3 基于逻辑演算

蕴含关系实际上是一种语义推理关系,而数学届对命题逻辑问题已经有了比较成熟的方法和工具,因此将逻辑演算运用到文本蕴含是非常自然的想法。基于逻辑演算的方法一般是将文本表示成数学逻辑表达式,比如一阶逻辑,构成事实集合,然后用逻辑推理规则判断是否能根据前提推理出假设。

Raina在论文Robust textual inference via learning and abductive reasoning中利用依存关系将前提和假设分别表示成两组子命题的和取形式,然后通过溯因推理机制尝试从前提推理出假设并计算其代价,并因此判别前提和假设是否有蕴含关系

基于逻辑演算的方法把数学界机器证明领域成熟的思想迁移到文本蕴含识别领域,具有一定的理论基础,但文本到逻辑表达式的转换不够鲁棒,容错性较差。而背景知识缺失往往导致推理链条的中断,导致结果召回率偏低。

3.4 基于文本转换

由于基于逻辑演算方法的不足,有的学者提出了基于文本转换的思路。这类方法采用了类似的“演算”思想,却抛弃了严格的数学逻辑表达式,转而利用语言分析技术,例如句法分析,语义角色标注,把前提和假设都表示成某种语言表示形式,如句法树、依存图等。然后利用背景知识设计推理规则将前提和假设进行改写,将其转换成对方的类似的形式,然后再通过子图相似性判别出其蕴含关系。

Bar-Haim在论文Semantic Inference at the Lexical-Syntactic Level的主要方法为把前提和假设都改写成句法树,然后依照规则对前提进行改写,如果前提能够改写成假设的句法树形式则认为存在蕴含关系。

基于转换的方法保留了基于逻辑演算的内核,同时不再要求把前提和假设表示成逻辑表达式,避免了引入噪音,但是该方法严重依赖转换规则。这些转换规则有的来自于知识库有的来自于语料。

3.5 基于混合模型

针对前面所介绍的各类文本蕴含识别方法的优势与不足,有学者提出了基于混合模型的方法.该类方法把诸如前提和假设的词级别相似度(如单词重叠率、同义词、反义词等)、句法树相似度、句法树编辑距离、对齐程度、由T转换为H的代价等等混合在一起作为特征,送入分类器(如支持向量机等)进行分类的方法。

3.6 基于深度学习的模型

1) 基于CNN模型。

Yin在论文中ABCNN: Attention-Based Convolutional Neural Network for Modeling Sentence Pairs提出了基于Attention机制的卷积神经网络来处理RTE问题,由于蕴含关系需要考虑一对文本前提和假设的信息,可以在对其中一个文本(比如假设)建模是同时考虑前提的信息,这种参照机制就是Attention机制。该方法通过在卷积中加入Attention Matrix来实现此目的。

此外,普通的卷积神经网络不能够有效捕获句法信息,而这些信息是判别文本蕴含所需要的重要特征。因此Mou在论文Natural Language Inference by Tree-Based Convolution and Heuristic Matching中提出了基于树结构的卷积神经网络,该网络将句法依存树作为卷积的操作对象,构成子树特征提取器,它能够一次性提取父节点及其子节点间的依存关系,该方法使用两个TBCNN分别对前提和假设进行建模,使用拼接、求差、相乘等启发式特征构造向量代表前提和假设的对的语义信息,最后再使用softmax进行分类。该方法在SNLI数据集上准确率达到0.824.

2) 基于RNN方法

Rocktäschel 在论文 Reasoning about Entailment with Neural Attention提出了使用LSTM进行RTE的方法,主要思想为分别使用两个LSTM对前提和假设进行建模,并使用前提的LSTM的状态来初始化假设LSTM。在建模的过程中引入了Attention机制,即在处理假设时考虑前提的信息。Rocktäschel等人还提出了word by word Attention机制,即在LSTM处理假设文本中的每个词时,都引入前提经过LSTM建模后的信息,这样进一步提升了模型的性能。最后实验通过分析Attention矩阵,发现该机制能很好的发现前提和假设中词之间的关联关系,并且实现了软对齐,较之前的RTE方法有了很大进步,在SNLI数据集上的准确率为0.832。

Wang等人在Rocktäschel基础上在论文Learning Natural Language Inference with LSTM提出了match-LSTM模型,重点关注前提和假设之间各个部分的匹配情况。Wang等人认为Rocktäschel的方法有俩个局限性。第一个是这个模型仅使用了前提的单一向量来跟假设之间做匹配。第二个是这个模型没有对前提和假设之间匹配的部分增加权重,对冲突的部分降低权重。也就是没有很好区分这两种情况。针对这两点Wang对模型进行了改进,他们把对前提和假设进行LSTM建模时的Attention向量进行拼接输入到match-LSTM。此外该方法还在前提中引入特殊单词NULL,当假设中的单词与前提中的单词不构成任何匹配时,match-LSTM就会把这个词跟NULL进行匹配,相当于增加了悬空对齐方式,完善了对齐模型。

Wang在实验中同样对Attention矩阵进行了分析,除此之外还对LSTM中的遗忘门、输入们、输出门分别作了实验分析。该方法在SNLI数据集上的准确率为0.861。

Reference 

https://repeval2017.github.io/shared/

https://aclweb.org/aclwiki/Textual_Entailment_Resource_Pool

郭茂盛, 张宇, 刘挺. 文本蕴含关系识别与知识获取研究进展及展望[J]. 计算机学报, 2017, 40(4):889-910.

  • 16
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
近年来,图像文本建模研究已经成为自然语言处理领域一个重要的硏究方向。图像常被用于增强句子的语义理解与表示。然而也有硏究人员对图像信息用于句子语义理解的必要性提岀质疑,原因是文本本身就能够提供强有力的先验知识,帮助模型取得非常好的效果;甚至在不使用图像的条件下就能得出正确的答案。因此硏究图像文本建模需要首先回答一个问题:图像是否有助于句子语义的理解与表示?为此,本文选择一个典型的不包含图像的自然语言语义理解任务:自然语言推理,并将图像信息引人到该任务中用于验证图像信息的有效性。由于自然语言推理任务是一个单一的自然语言任务,在数据标注过程中没有考虑图像信息,因此选择该任务能够更客观地分析岀图像信息对句子语义理解与表示的影响。具体而言,本文提出一种通用的即插即用框架(generalplugandplayframework)用于图像信息的整合。基于该框架,本文选择目前最先进的五个自然语言推理模型,对比分析这些模型在使用图像信息前后的表现,以及使用不同图像处理模型与不同图像设置时的表现。最后,本文在一个大规模公开数据集上进行了大量实验,实验结果证实图像作为额外知识,确实有助于句子语义的理解与表示。此外,还证实了不同的图像处理模型和使用方法对整个模型的表现也会造成不同的影响。
好的,我可以为您提供一个使用自然推理完成文本蕴含任务的Python代码示例。这个示例使用PyTorch框架和GloVe预训练词向量。这里以SNLI数据集为例,您可以根据自己的需要进行修改。 ``` import torch import torch.nn as nn import torch.nn.functional as F import torch.optim as optim from torchtext.datasets import SNLI from torchtext.data import Field, BucketIterator # 定义Field对象 TEXT = Field(tokenize='spacy', tokenizer_language='en_core_web_sm', include_lengths=True) LABEL = Field(sequential=False, unk_token=None) # 加载数据集 train_data, valid_data, test_data = SNLI.splits(TEXT, LABEL) # 构建词汇表,加载GloVe预训练词向量 TEXT.build_vocab(train_data, vectors="glove.6B.300d") LABEL.build_vocab(train_data) # 定义超参数 BATCH_SIZE = 64 device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') EMBEDDING_DIM = 300 HIDDEN_DIM = 256 OUTPUT_DIM = len(LABEL.vocab) N_LAYERS = 2 BIDIRECTIONAL = True DROPOUT = 0.5 PAD_IDX = TEXT.vocab.stoi[TEXT.pad_token] # 定义模型 class RNN(nn.Module): def __init__(self, embedding_dim, hidden_dim, output_dim, n_layers, bidirectional, dropout, pad_idx): super().__init__() self.embedding = nn.Embedding(len(TEXT.vocab), embedding_dim, padding_idx=pad_idx) self.rnn = nn.LSTM(embedding_dim, hidden_dim, num_layers=n_layers, bidirectional=bidirectional, dropout=dropout) self.fc = nn.Linear(hidden_dim * 2 if bidirectional else hidden_dim, output_dim) self.dropout = nn.Dropout(dropout) def forward(self, text, text_lengths): embedded = self.dropout(self.embedding(text)) packed_embedded = nn.utils.rnn.pack_padded_sequence(embedded, text_lengths.to('cpu')) packed_output, (hidden, cell) = self.rnn(packed_embedded) output, output_lengths = nn.utils.rnn.pad_packed_sequence(packed_output) hidden = self.dropout(torch.cat((hidden[-2,:,:], hidden[-1,:,:]), dim = 1)) return self.fc(hidden) # 初始化模型、优化器和损失函数 model = RNN(EMBEDDING_DIM, HIDDEN_DIM, OUTPUT_DIM, N_LAYERS, BIDIRECTIONAL, DROPOUT, PAD_IDX) optimizer = optim.Adam(model.parameters()) criterion = nn.CrossEntropyLoss() model = model.to(device) criterion = criterion.to(device) # 计算准确率 def categorical_accuracy(preds, y): max_preds = preds.argmax(dim=1, keepdim=True) correct = max_preds.squeeze(1).eq(y) return correct.sum() / torch.FloatTensor([y.shape[0]]) # 训练模型 def train(model, iterator, optimizer, criterion): epoch_loss = 0 epoch_acc = 0 model.train() for batch in iterator: optimizer.zero_grad() text, text_lengths = batch.text predictions = model(text, text_lengths).squeeze(1) loss = criterion(predictions, batch.label) acc = categorical_accuracy(predictions, batch.label) loss.backward() optimizer.step() epoch_loss += loss.item() epoch_acc += acc.item() return epoch_loss / len(iterator), epoch_acc / len(iterator) # 评估模型 def evaluate(model, iterator, criterion): epoch_loss = 0 epoch_acc = 0 model.eval() with torch.no_grad(): for batch in iterator: text, text_lengths = batch.text predictions = model(text, text_lengths).squeeze(1) loss = criterion(predictions, batch.label) acc = categorical_accuracy(predictions, batch.label) epoch_loss += loss.item() epoch_acc += acc.item() return epoch_loss / len(iterator), epoch_acc / len(iterator) # 训练模型并输出准确率 N_EPOCHS = 5 for epoch in range(N_EPOCHS): train_loss, train_acc = train(model, train_iterator, optimizer, criterion) valid_loss, valid_acc = evaluate(model, valid_iterator, criterion) print(f'Epoch: {epoch+1:02}') print(f'\tTrain Loss: {train_loss:.3f} | Train Acc: {train_acc*100:.2f}%') print(f'\t Val. Loss: {valid_loss:.3f} | Val. Acc: {valid_acc*100:.2f}%') # 测试模型 test_loss, test_acc = evaluate(model, test_iterator, criterion) print(f'Test Loss: {test_loss:.3f} | Test Acc: {test_acc*100:.2f}%') ``` 这个代码示例使用了LSTM模型进行文本蕴含任务,并且在SNLI数据集上进行了训练和测试。您可以根据自己的需要进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值