【机器学习】--- 自然语言推理(NLI)
引言
随着自然语言处理(NLP)的迅速发展,**自然语言推理(Natural Language Inference, NLI)**已成为一项重要的研究任务。它的目标是判断两个文本片段之间的逻辑关系。这一任务广泛应用于机器阅读理解、问答系统、对话生成等场景。
NLI 是通过判断两个句子之间的关系,确定第二个句子是否是第一个句子的蕴含(entailment)、矛盾(contradiction)或中立(neutral)。比如给定句子对:
- 前提:“所有的鸟都会飞。”
- 假设:“企鹅不能飞。”
我们可以推断出这两个句子是“矛盾”的。本文将从NLI的基础概念出发,深入探讨其挑战、模型架构、常用方法及其实现,最后简要展望未来的发展方向。
1. 什么是自然语言推理(NLI)
1.1 NLI定义
NLI任务的目标是判断给定的一对句子,即前提(premise)和假设(hypothesis),是否具有以下三种关系之一:
- 蕴含(Entailment):假设可以从前提中推断出。
- 矛盾(Contradiction):假设与前提相矛盾。
- 中立(Neutral):假设与前提既不矛盾也无法从前提中推断出。
1.2 NLI的实际应用
NLI作为自然语言理解的核心任务之一,有着广泛的应用场景:
- 机器阅读理解:NLI可以帮助系统从一篇文章中推断出事实。
- 智能问答:通过推理用户提问与答案的关系,来提高问答系统的准确性。
- 对话系统:帮助对话系统理解上下文之间的逻辑关系,从而生成合理的回复。
2. NLI的挑战
NLI任务的主要挑战在于:
- 多样化的语言表达:自然语言具有高度的灵活性,同样的意思可以用多种不同的方式表达,增加了推理的复杂性。
- 常识推理:有时判断两个句子之间的关系需要依赖外部常识,而这对模型是很大的挑战。
- 模糊性和歧义性:语言中充满了歧义和不确定性,例如代词指代不明或双关语等。
- 领域知识依赖:某些情况下,推理需要特定的领域知识。
2.1 示例
前提:所有的医生都接受了医学培训。
假设:医生具备专业知识。
- 在这种情况下,假设可以从前提中推断出,因此是蕴含关系。
前提:所有的医生都接受了医学培训。
假设:教师具备专业知识。
- 这里假设与前提没有直接关系,因此是中立关系。
前提:所有的医生都接受了医学培训。
假设:没有医生接受过医学培训。
- 这种情况下,假设与前提直接矛盾,因此是矛盾关系。
3. NLI的主流方法
3.1 基于传统方法的NLI模型
早期的NLI方法主要依赖于手工构建的特征和经典的机器学习方法,如支持向量机(SVM)或逻辑回归。传统方法的局限性在于它们无法有效处理语言的多样性和上下文依赖性。
3.1.1 基于词向量的方法
词向量(Word Embeddings)是将单词映射为低维稠密向量空间的方法。常见的词向量技术包括Word2Vec、GloVe等。通过使用词向量将前提和假设表示为向量,可以计算它们之间的相似度或使用这些表示作为输入特征。
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.metrics.pairwise import cosine_similarity# 简单的基于词向量的相似度计算
vectorizer = CountVectorizer()
X = vectorizer.fit_transform(["所有的医生都接受了医学培训", "医生具备专业知识"])
similarity = cosine_similarity(X[0], X[1])
print(similarity)
3.2 基于神经网络的NLI模型
随着深度学习的兴起,基于神经网络的模型在NLI任务中取得了显著进展。典型的神经网络方法包括:
- 双向LSTM(BiLSTM):用于捕获前提和假设的上下文依赖性。
- 注意力机制(Attention):用于聚焦前提和假设之间的相关部分。
- 预训练语言模型(如BERT、GPT):通过大规模语料库的预训练学习到更丰富的语义表示。
3.2.1 BiLSTM模型
双向LSTM是一种常用的序列模型,它通过前向和后向两个方向的LSTM单元来捕捉句子中每个单词的上下文信息。用于NLI时,前提和假设会分别通过BiLSTM进行编码,然后进行合并和分类。
import tensorflow as tf
from tensorflow.keras.layers import LSTM, Bidirectional, Dense, Embedding# 简单的BiLSTM模型
def create_bilstm_model(vocab_size, embedding_dim, max_length):model = tf.keras.Sequential([Embedding(vocab_size, embedding_dim, input_length=max_length),Bidirectional(LSTM(64)),Dense(64, activation='relu'),Dense(3, activation='softmax') # 3类输出:entailment, contradiction, neutral])model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])return model
3.2.2 注意力机制
在自然语言推理中,前提和假设之间的某些部分可能存在强关联。注意力机制可以有效识别出这些相关部分,并加权聚焦。通过这种方式,模型可以更精确地进行推理。
from tensorflow.keras.layers import Attention# 示例:将前提和假设的LSTM输出结合注意力机制
premise_lstm_output = Bidirectional(LSTM(64, return_sequences=True))(premise_input)
hypothesis_lstm_output = Bidirectional(LSTM(64, return_sequences=True))(hypothesis_input)# 使用注意力机制结合前提和假设
attention_output = Attention()([premise_lstm_output, hypothesis_lstm_output])
3.3 基于预训练语言模型的NLI
自从BERT等预训练语言模型被引入以来,NLI的性能得到了显著提高。预训练模型通过在大规模无标注文本上进行语言建模任务,学习了丰富的语言表示,然后在NLI任务上进行微调(fine-tuning)。
3.3.1 BERT模型在NLI中的应用
BERT通过双向编码器捕获上下文中的双向依赖信息。使用BERT进行NLI任务时,前提和假设可以被拼接为一个输入序列,分别标记为[CLS] 前提 [SEP] 假设 [SEP]
。然后模型的输出表示会被用于分类。
from transformers import BertTokenizer, TFBertForSequenceClassification# 加载BERT模型
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = TFBertForSequenceClassification.from_pretrained('bert-base-uncased', num_labels=3)# 将前提和假设转换为BERT输入格式
inputs = tokenizer("所有的医生都接受了医学培训", "医生具备专业知识", return_tensors='tf', truncation=True, padding=True)
outputs = model(inputs)
3.3.2 RoBERTa和其他模型
除了BERT之外,其他基于变压器(Transformer)的模型如RoBERTa、ALBERT、XLNet等也在NLI任务中表现优异。这些模型大多是通过对训练过程的改进和更大的数据集训练得到的。
from transformers import RobertaTokenizer, TFRobertaForSequenceClassification# 加载RoBERTa模型
tokenizer = RobertaTokenizer.from_pretrained('roberta-base')
model = TFRobertaForSequenceClassification.from_pretrained('roberta-base', num_labels=3)inputs = tokenizer("所有的医生都接受了医学培训", "医生具备专业知识", return_tensors='tf', truncation=True, padding=True)
outputs = model(inputs)
4. NLI的主流数据集
在NLI领域中,有一些常用的数据集来训练和评估模型的性能。以下是几个广泛使用的数据集:
4.1 SNLI(Stanford Natural Language Inference)
SNLI 是斯坦福大学推出的第一个大规模的NLI数据集,包含了570,000个人工标注的句子对。它的规模和标注质量为NLI任务的研究提供了极大的帮助。
# SNLI 数据集的读取示例
import datasetssnli = datasets.load_dataset("snli")
print(snli["train"][0]) # 输出第一个样本
4.2 MultiNLI(Multi-Genre Natural Language Inference)
MultiNLI 是SNLI的扩展版本,覆盖了更多的领域(例如新闻、小说、学术论文等),并引入了更具挑战性的句子对,使模型能够更好地泛化到不同领域的推理任务。
4.3 XNLI(Cross-lingual Natural Language Inference)
XNLI 是一个跨语言的NLI数据集,涵盖了15种不同的语言。XNLI数据集推动了跨语言自然语言推理的研究,为开发多语言模型提供了数据支持。
5. 实现一个NLI系统
接下来,我们将基于BERT模型实现一个简单的NLI系统,并使用SNLI数据集进行训练和评估。
5.1 数据预处理
首先,我们需要将前提和假设拼接成适合BERT输入的格式,并将它们标注为三类之一:蕴含(entailment)、矛盾(contradiction)或中立(neutral)。
from transformers import BertTokenizer
from sklearn.preprocessing import LabelEncoder# 数据集示例
premises = ["所有的医生都接受了医学培训"]
hypotheses = ["医生具备专业知识"]
labels = ["entailment"]# 将标签编码为数字
label_encoder = LabelEncoder()
labels_encoded = label_encoder.fit_transform(labels)# 加载BERT分词器
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')# 将前提和假设拼接,并转换为BERT输入格式
inputs = tokenizer(premises, hypotheses, return_tensors='tf', truncation=True, padding=True)
5.2 模型训练
接下来我们将使用 TFBertForSequenceClassification
模型进行训练。模型的输出层将被修改为三类输出,用于NLI任务。
from transformers import TFBertForSequenceClassification# 加载BERT模型,设置输出为3类
model = TFBertForSequenceClassification.from_pretrained('bert-base-uncased', num_labels=3)# 编译模型
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])# 训练模型
model.fit(inputs, labels_encoded, epochs=3, batch_size=16)
5.3 模型评估
训练完成后,我们可以在验证集上对模型进行评估,查看其在NLI任务上的表现。
# 模型评估
eval_results = model.evaluate(inputs, labels_encoded)
print(f"Evaluation Results: {eval_results}")
5.4 模型预测
模型训练完毕后,可以使用该模型对新的前提和假设对进行推理。
# 进行推理
new_premise = "所有的鸟都会飞"
new_hypothesis = "企鹅不能飞"new_inputs = tokenizer(new_premise, new_hypothesis, return_tensors='tf', truncation=True, padding=True)
predictions = model.predict(new_inputs)# 输出预测结果
predicted_label = label_encoder.inverse_transform([predictions.argmax()])
print(f"推理结果: {predicted_label}")
6. NLI的前沿发展
6.1 跨语言NLI
随着跨语言NLP的发展,NLI的研究也逐渐扩展到多语言和跨语言领域。例如,使用XNLI数据集可以训练多语言模型来处理不同语言之间的推理任务。这对于全球化的应用场景非常重要,例如构建能够跨越语言障碍的智能对话系统。
6.2 常识推理与外部知识库的结合
NLI任务中,有时需要借助常识知识来做出准确的推理。未来的NLI模型可能会结合外部知识库(如ConceptNet、Wikidata),通过注入更多的常识性知识来提升推理的准确性。
6.3 领域自适应
目前的NLI模型在训练时主要依赖于通用语料库,而在特定领域中的表现往往不如预期。未来的发展方向之一是让模型能够自适应不同的领域,通过迁移学习或领域自适应技术使得模型在特定领域中也能保持高性能。
7. 总结
自然语言推理(NLI)作为自然语言理解任务中的一个重要问题,不仅在理论研究中具有重要意义,还在许多实际应用中扮演了关键角色。随着深度学习和预训练语言模型的飞速发展,NLI模型的性能取得了巨大提升。未来,跨语言推理、常识推理以及领域自适应将是NLI领域进一步研究的重要方向。
通过本文的介绍,你应该已经对NLI有了深入的理解,并掌握了使用BERT模型进行自然语言推理的基本方法。
相关文章:

【机器学习】--- 自然语言推理(NLI)
引言 随着自然语言处理(NLP)的迅速发展,**自然语言推理(Natural Language Inference, NLI)**已成为一项重要的研究任务。它的目标是判断两个文本片段之间的逻辑关系。这一任务广泛应用于机器阅读理解、问答系统、对话…...
大话C++:第11篇 类的定义与封装
1 类的定义 在C中,类的定义通常使用class关键字开始,后面紧跟类的名称。类可以包含数据成员(变量)和成员函数(方法)。 在C中,类可以更加详细地展开,包括数据成员(变量&…...

六种主流ETL工具的比较与Kettle的实践练习指南--MySQL、hive、hdfs等之间的数据迁移
在数据集成和数据仓库建设中,ETL(Extract, Transform, Load)工具扮演着至关重要的角色。本文将对六种主流ETL工具进行比较,并深入探讨Kettle的实践应用。 一、六种主流ETL工具比较 1. DataPipeline 设计及架构:专为…...
一天一道算法题day07
找出字符中第一个匹配的下标 题目描述 给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。 示例 1&#…...

电机学习-有感BLDC开环控制(六步换相)
文章目录 1. 简介2. 六步换向控制3. 机械角度和电角度4.转子位置获取5.霍尔传感器读取测试6.速度开环控制6.1 PWM设置6.2死区时间 1. 简介 BLDC的反电动势一般是梯形的反电动势,所以采用方波控制。如图2-1所示,是一个简化的内转子无刷直流电机。我们通过…...

《深度学习》PyTorch框架 优化器、激活函数讲解
目录 一、深度学习核心框架的选择 1、TensorFlow 1)概念 2)优缺点 2、PyTorch 1)概念 2)优缺点 3、Keras 1)概念 2)优缺点 4、Caffe 1)概念 2)优缺点 二、pytorch安装 1、安装 2、…...

Linux:进程(四)
目录 一、进程优先级 二、Linux调度与切换 1.背景 2.进程切换 一、进程优先级 背景:在计算机中,软硬件资源是有限的,而进程想要访问某一种资源,就得通过排队来保证访问资源的过程是有条不紊的。 Linux下对优先级的定义。执行命…...

CTC loss 博客转载
论文地址: https://www.cs.toronto.edu/~graves/icml_2006.pdf 为了对应这个图,我们假设一种符合的模型情况: 英文OCR,37个类别(26个小写字母10个汉字空格),最大输出长度8个字符 模型预测结果…...

TryHackMe 第3天 | Pre Security (中)
该学习路径讲解了网络安全入门的必备技术知识,比如计算机网络、网络协议、Linux命令、Windows设置等内容。上一篇中简短介绍了计算机网络相关的知识,本篇博客将记录 网络协议 部分。 How the web works? DNS in detail DNS (Domain name system&…...
c语言中“qsort函数”和“结构体成员访问变量”
qsort函数: qsort是c语言中的库函数,这个函数是对数据进行排序(对任意) 冒泡排序中排列整数顺序用的函数只适用于整形,而qsort函数适用与所有数据 排序算法 冒泡排序 插入 选择 快速 void qsort{ void * base&…...
【MySQL】在MySQL中STR_TO_DATE()
1.在MySQL中STR_TO_DATE() 在MySQL中,STR_TO_DATE() 函数用于将字符串转换为日期格式。这个函数非常有用,当你需要将文本数据转换为可由MySQL日期和时间函数处理的格式时。 1.1 语法 STR_TO_DATE() 函数的基本语法如下: STR_TO_DATE(date…...

PCIE集成验证(五)MSI/MSI-X中断
PCI 总线最早采用的中断机制是 INTx,这是基于边带信号的。后续的 PCI/PCI-X版本,为了消除边带信号,降低系统的硬件设计复杂度,逐渐采用了 MSI(Message Signaled Interrupt)/MSI-X(消息信号中断)的中断机制。…...
leetcode 380.O(1) 时间插入、删除和获取随机元素
实现RandomizedSet 类: RandomizedSet() 初始化 RandomizedSet 对象bool insert(int val) 当元素 val 不存在时,向集合中插入该项,并返回 true ;否则,返回 false 。bool remove(int val) 当元素 val 存在时࿰…...
基于MicroPython的ESP8266控制PS2摇杆模块的设计方案
以下是一个基于MicroPython的ESP8266控制PS2摇杆模块的设计方案: 一、硬件准备: 1. 一块ESP8266开发板,如NodeMCU 2. 一个带有X、Y轴模拟输出和Z轴(按钮)数字输出的PS2摇杆模块 3. 杜邦线若干 4. 3.3V直流电源 二、硬件连接:…...

Spring Boot 3项目使用Swagger3教程
Spring Boot 3项目使用Swagger3教程 Swagger:自动生成接口文档 添加依赖(pom.xml) <dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId><version>4.1…...
linux-系统备份与恢复-系统恢复
Linux 系统备份与恢复:系统恢复 1. 概述 Linux 系统的恢复是系统管理的重要组成部分,它指的是在系统崩溃、硬件故障、误操作或安全问题后,恢复系统到可用状态的过程。良好的系统恢复计划可以有效避免数据丢失和业务中断,并确保系…...
【Rust语言】std::collections::HashMap用法
HashMap用法文档 文章目录 创建键的要求 增删改查增: insert删: remove/remove_entry改单点修改 get_mut整体修改 values_mut/iter_mut 查集增改于一身的entry 遍历只读遍历into_values() 与 into_keys()容量、实际长度、判空导出清除重定容量 use std::collections::HashMap;创…...

使用SoapUI、Postman工具调用Webservice方法
SoapUI工具更适合调用Webservice使用。 1.使用SoapUI工具调用Webservice 创建“New SOAP Project” 自行定义一个项目名称,输入wsdl地址: 在左侧列表找到方法名,双击“Request 1”, 在请求数据中,添加对应的参数,然…...
js 与 C++引用和指针的关系
js 与 C引用和指针的关系 js 中既有引用的影子, 也有指针的影子。 1、引用用法 这里相当于C 中的引用, b是a的引用, 修改b ,a也改变。 var a { 1: 1 }var b a;a null;b[2] 2;console.error(b); // { 1: 1, 2: 2 }2、指针用法 这里 a,b应该按照指针理解。 var a undef…...

python --PyAibote自动化
官文: https://www.pyaibote.com/ 下载安卓集成环境: 可以看到开发的一些信息...
计算机总线技术深度解析:从系统架构到前沿演进
计算机系统中的总线是连接多个部件的信息传输线,是各部件间传输信息的公共通道。以下将从总线的定义、功能、分类、性能指标等方面进行详细介绍: 一、总线的定义与功能 1.定义:总线是一组能为多个部件分时共享的公共信息传送线路࿰…...

实验一:PyTorch基本操作实验
import torch # PyTorch中初始化矩阵常见有以下几种方法 # 1. 直接使用固定值初始化 # M torch.tensor([[1.0, 2.0, 3.0]]) # 1x3矩阵 # 2. 随机初始化 # M torch.rand(1, 3) # 1x3矩阵,元素在0-1之间均匀分布 # M torch.randn(1, 3) # 1x3矩阵,元…...

《操作系统真相还原》——中断
可以毫不夸张的说,操作系统离不开中断 此时我们将中断处理程序放在了汇编文件中了,很显然我们不能很方便的编写中断处理程序,不如在汇编程序里调用c函数。 在这个感觉过可以在c语言中直接内联汇编完成这些。 定时器 将时钟中断的频率提高后…...

MySQL强化关键_018_MySQL 优化手段及性能分析工具
目 录 一、优化手段 二、SQL 性能分析工具 1.查看数据库整体情况 (1)语法格式 (2)说明 2.慢查询日志 (1)说明 (2)开启慢查询日志功能 (3)实例 3.s…...
gcc符号表生成机制
符号表生成机制 我们以C语言的编译链接过程为例,详细讲解符号表(Symbol Table)的流程,涵盖编译和链接两个阶段。理解符号表是理解链接器如何解决符号引用(如函数、变量)的关键。 符号表分为两种ÿ…...

【QT控件】QWidget 常用核心属性介绍 -- 万字详解
目录 一、控件概述 二、QWidget 核心属性 2.1 核心属性概览 2.2 enabled 编辑 2.3 geometry 2.4 windowTitle 2.5 windowIcon 使用qrc文件管理资源 2.6 windowOpacity 2.7 cursor 2.8 font 编辑 2.9 toolTip 2.10 focusPolicy 2.11 styleSheet QT专栏&…...
Java垃圾回收算法及GC触发条件
一、引言 在Java编程语言的发展历程中,内存管理一直是其核心特性之一。与C/C等需要手动管理内存的语言不同,Java通过自动垃圾回收(Garbage Collection,简称GC)机制,极大地减轻了开发人员的负担,…...

Android Native 之 adbd进程分析
目录 1、adbd守护进程 2、adbd权限降级 3、adbd命令解析 1)adb shell 2)adb root 3)adb reboot 4、案例 1)案例之实现不需要执行adb root命令自动具有root权限 2)案例之实现不需要RSA认证直接能够使用adb she…...
6个月Python学习计划 Day 12 - 字符串处理 文件路径操作
第一周 Day 1 - Python 基础入门 & 开发环境搭建 Day 2 - 条件判断、用户输入、格式化输出 Day 3 - 循环语句 range 函数 Day 4 - 列表 & 元组基础 Day 5 - 字典(dict)与集合(set) Day 6 - 综合实战:学生信息…...

ubuntu安装devkitPro
建议开个魔法 wget https://apt.devkitpro.org/install-devkitpro-pacman chmod x ./install-devkitpro-pacman sudo ./install-devkitpro-pacman(下面这句如果报错也没事) sudo ln -s /proc/self/mounts /etc/mtab往~.bashrc添加 export DEVKITPRO/o…...