【机器学习】--- 自然语言推理(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/ 下载安卓集成环境: 可以看到开发的一些信息...

利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...

代码规范和架构【立芯理论一】(2025.06.08)
1、代码规范的目标 代码简洁精炼、美观,可持续性好高效率高复用,可移植性好高内聚,低耦合没有冗余规范性,代码有规可循,可以看出自己当时的思考过程特殊排版,特殊语法,特殊指令,必须…...

打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用
一、方案背景 在现代生产与生活场景中,如工厂高危作业区、医院手术室、公共场景等,人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式,存在效率低、覆盖面不足、判断主观性强等问题,难以满足对人员打手机行为精…...
NPOI操作EXCEL文件 ——CAD C# 二次开发
缺点:dll.版本容易加载错误。CAD加载插件时,没有加载所有类库。插件运行过程中用到某个类库,会从CAD的安装目录找,找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库,就用插件程序加载进…...
Bean 作用域有哪些?如何答出技术深度?
导语: Spring 面试绕不开 Bean 的作用域问题,这是面试官考察候选人对 Spring 框架理解深度的常见方式。本文将围绕“Spring 中的 Bean 作用域”展开,结合典型面试题及实战场景,帮你厘清重点,打破模板式回答,…...

wpf在image控件上快速显示内存图像
wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像(比如分辨率3000*3000的图像)的办法,尤其是想把内存中的裸数据(只有图像的数据,不包…...