大型语言模型:SBERT — Sentence-BERT

一、介绍
Transformer 在 NLP 方面取得了进化进步,这已经不是什么秘密了。基于转换器,许多其他机器学习模型已经发展起来。其中之一是BERT,它主要由几个堆叠的变压器编码器组成。除了用于情感分析或问答等一系列不同的问题外,BERT在构建词嵌入(表示词的语义含义的数字向量)方面也越来越受欢迎。
以嵌入的形式表示单词具有巨大的优势,因为机器学习算法不能处理原始文本,但可以对向量的向量进行操作。这允许通过使用欧几里得或余弦距离等标准度量来比较不同单词的相似性。
问题在于,在实践中,我们经常需要构造嵌入,而不是为单个单词,而是为整个句子。但是,基本的 BERT 版本仅在单词级别上构建嵌入。因此,后来开发了几种类似 BERT 的方法来解决此问题,本文将对此进行讨论。通过逐步讨论它们,我们将达到称为 SBERT 的最先进的模型。
为了深入了解 SBERT 在后台的工作原理,建议您已经熟悉 BERT。如果没有,本系列文章的前一部分将对此进行详细解释。
二、Bert
首先,让我们提醒一下 BERT 如何处理信息。作为输入,它采用一个 [CLS] 令牌和两个句子,由一个特殊的 [SEP] 标记分隔。根据型号配置,多头注意力块会处理 12 或 24 次此信息。然后,将输出聚合并传递到简单的回归模型以获取最终标签。
BERT架构
有关 BERT 内部工作原理的更多信息,您可以参考本系列文章的前一部分:
2.1 交叉编码器架构
可以使用BERT来计算一对文档之间的相似性。考虑在大型集合中查找最相似的句子对的目标。为了解决这个问题,每个可能的对都被放在BERT模型中。这会导致推理过程中的二次复杂度。例如,处理 n = 10 000 个句子需要 n * (n — 1) / 2 = 49 995 000 次推理 BERT 计算,这实际上不可扩展。
2.2 其他方法
分析交叉编码器架构的低效率,为每个句子独立预计算嵌入似乎是合乎逻辑的。之后,我们可以直接计算所有文档对上所选的距离度量,这比将二次数的句子对提供给 BERT 要快得多。
不幸的是,这种方法在BERT中是不可能的:BERT的核心问题是,每次同时传递和处理两个句子时,很难获得仅独立表示单个句子的嵌入。
研究人员试图通过使用 [CLS] 标记嵌入的输出来消除这个问题,希望它包含足够的信息来表示一个句子。然而,事实证明,[CLS]对这项任务根本没有用,因为它最初是在BERT中预先训练的,用于下一个句子预测。
另一种方法是将单个句子传递给 BERT,然后对输出标记嵌入进行平均。然而,获得的结果甚至比简单地平均GLoVe嵌入还要糟糕。
推导独立的句子嵌入是BERT的主要问题之一。为了缓解这一方面,开发了SBERT。
三、SBERT
SBERT 引入了连体网络概念,这意味着每次两个句子通过同一个 BERT 模型独立传递。在讨论 SBERT 架构之前,让我们先看一下关于连体网络的一个微妙的注释:
大多数时候,在科学论文中,暹罗网络架构被描述为几个模型接收如此多的输入。实际上,可以将其视为具有相同配置和权重的单个模型,这些配置和权重在多个并行输入之间共享。每当为单个输入更新模型权重时,它们也会为其他输入同样更新。
左边是非连体(交叉编码器)架构,右边是连体(双编码器)架构。主要区别在于,在左侧,模型同时接受两个输入。在右侧,模型并行接受两个输入,因此两个输出不相互依赖。
回到 SBERT,在通过 BERT 传递句子后,将池化层应用于 BERT 嵌入以获得其低维表示:最初的 512 个 768 维向量被转换为单个 768 维向量。对于池化层,SBERT的作者建议选择均值池化层作为默认层,尽管他们也提到可以使用最大池化策略,或者简单地采用[CLS]令牌的输出。
当两个句子都通过池化层时,我们有两个 768 维向量 u 和 v。通过使用这两个向量,作者提出了三种优化不同目标的方法,这些方法将在下面讨论。
3.1 分类目标函数
此问题的目标是在几个类之一中正确地对给定的一对句子进行分类。
在生成嵌入 u 和 v 之后,研究人员发现生成从这两个源得出的另一个向量作为元素绝对差 |u-v| 是有用的。他们还尝试了其他特征工程技术,但这种技术显示出最好的结果。
最后,将三个向量 u、v 和 |u-v| 连接起来,乘以可训练的权重矩阵 W,并将乘法结果输入 softmax 分类器,该分类器输出对应于不同类的句子的归一化概率。交叉熵损失函数用于更新模型的权重。
用于分类目标的 SBERT 架构。参数 n 代表嵌入的维度(默认为 768 作为 BERT base),而 k 表示标签的数量。
NLI(自然语言推理)是用于解决该目标的最流行的现有问题之一,其中对于定义假设和前提的给定句子 A 和 B 对,有必要预测假设是真(蕴涵)、假(矛盾)还是未确定(中性)给定前提。对于此问题,推理过程与训练相同。
如本文所述,SBERT模型最初是在SNLI和MultiNLI两个数据集上训练的,这两个数据集包含一百万个句子对,具有相应的标签蕴涵、矛盾或中性。之后,论文研究人员提到了有关SBERT调谐参数的细节:
“我们用一个 3 分 softmax 分类器目标函数对 SBERT 进行微调,用于一个时期。我们使用了 16 个批处理大小、学习率为 2e−5 的 Adam 优化器,以及超过 10% 的训练数据的线性学习率预热。我们默认的池化策略是卑鄙的。
3.2 回归目标函数
在此公式中,在获得向量 u 和 v 后,它们之间的相似性分数由所选的相似性指标直接计算。将预测的相似度分数与真实值进行比较,并使用 MSE 损失函数更新模型。默认情况下,作者选择余弦相似度作为相似度指标。
回归目标的SBERT架构。参数 n 代表嵌入的维数(默认为 768 作为 BERT 基数)。
在推理过程中,可以通过以下两种方式之一使用此体系结构:
- 通过给定的句子对,可以计算相似度分数。推理工作流与训练完全相同。
- 对于给定的句子,可以提取其句子嵌入(在应用池化层之后)以供以后使用。当我们得到大量句子以计算它们之间的成对相似性分数时,这特别有用。通过仅通过 BERT 运行每个句子一次,我们提取了所有必要的句子嵌入。之后,我们可以直接计算所有向量之间选择的相似度指标(毫无疑问,它仍然需要二次比较,但同时我们避免了像以前那样使用 BERT 进行二次推理计算)。
3.3 三重目标函数
三元组目标引入了三元组损失,该损失由三个句子计算,通常称为锚,正和负。假设锚句和肯定句彼此非常接近,而锚句和否定句则非常不同。在训练过程中,模型会评估对(锚,正)与对(锚,负)相比的接近程度。在数学上,以下损失函数最小化:
原始论文中的三元组损失函数。变量 sₐ、sp、sn 分别表示锚嵌入、正嵌入和负嵌入。符号 ||小号||是向量 s 的范数。参数 ε 称为边距。
边距 ε 确保肯定句比否定句更接近锚点至少ε。否则,损失将大于 0。默认情况下,在此公式中,作者选择欧几里得距离作为向量范数,参数 ε 设置为 1。
三元组 SBERT 架构与前两个架构的不同之处在于,该模型现在并行接受三个输入语句(而不是两个)。
回归目标的SBERT架构。参数 n 代表嵌入的维数(默认为 768 作为 BERT 基数)。
四、代码
SentenceTransformers 是一个最先进的 Python 库,用于构建句子嵌入。它包含用于不同任务的多个预训练模型。使用 SentenceTransformer 构建嵌入很简单,下面的代码片段中显示了一个示例。

然后,构造的嵌入可用于相似性比较。每个模型都是针对特定任务进行训练的,因此通过参考文档选择适当的相似度指标进行比较始终很重要。
五、结论
我们已经介绍了一种用于获取句子嵌入的高级 NLP 模型。通过将 BERT 推理执行的二次次数减少到线性,SBERT 在保持高精度的同时实现了速度的大幅增长。
为了最终理解这种差异有多显着,参考论文中描述的例子就足够了,研究人员试图在n = 10000个句子中找到最相似的一对。在现代 V100 GPU 上,使用 BERT 时此过程大约需要 65 小时,使用 SBERT 时只需 5 秒!这个例子表明 SBERT 是 NLP 的巨大进步。
相关文章:

大型语言模型:SBERT — Sentence-BERT
slavahead 一、介绍 Transformer 在 NLP 方面取得了进化进步,这已经不是什么秘密了。基于转换器,许多其他机器学习模型已经发展起来。其中之一是BERT,它主要由几个堆叠的变压器编码器组成。除了用于情感分析或问答等一系列不同的问题外&#…...
高效编写软件测试报告的关键技巧
引言: 软件测试报告是测试团队与开发团队之间沟通的重要工具,它记录了测试过程中的发现、问题和建议。一个清晰、准确、高效的软件测试报告可以帮助开发团队更好地理解测试结果,并及时修复问题。本文将介绍一些高效编写软件测试报告的关键技巧…...
编写CI/CD自动化部署脚本
编写CI/CD自动化部署脚本 什么是CI/CD CI/CD 是现代软件开发过程中的关键实践,它包含两个缩写: CI,或者持续集成(Continuous Integration)CD,可以指持续交付(Continuous Delivery)…...
Pandas实践_分类数据
文章目录 一、cat对象1.cat对象的属性2.类别的增加、删除和修改 二、有序分类1.序的建立2.排序和比较 三、区间类别1.利用cut和qcut进行区间构造2.一般区间的构造3.区间的属性与方法 一、cat对象 1.cat对象的属性 在pandas中提供了category类型,使用户能够处理分类…...

git的使用思维导图
源文件在github主页:study_collection/cpp学习/git at main stu-yzZ/study_collection (github.com)...
Qt 软件界面点击QCombBox控件,造成整个界面移位
Qt 软件界面点击QCombBox控件,造成整个界面移位 最近项目中,遇到了一个问题,在绘制界面的时候,使用了QCombBox控件,在点击QCombBox控件下拉中的item时,会造成整个界面移位的现象。 我重写了下面三个事件函…...

AI Native工程化:百度App AI互动技术实践
作者 | GodStart 导读 随着AI浪潮的兴起,越来越多的应用都在利用大模型重构业务形态,在设计和优化Prompt的过程中,我们发现整个Prompt测评和优化周期非常长,因此,我们提出了一种Prompt生成、评估与迭代的一体化解决方案…...

DDPM推导笔记
各位佬看文章之前,可以先去看看这个视频,并给这位up主点赞投币,这位佬讲解的太好了:大白话AI 1.前置知识的学习 1.1 正态分布特性 (1)正态分布的概率密度函数 f ( x ) 1 2 π σ e − ( x − μ ) …...
【C#/Java】【小白必看】不要只会读写文本文件了!对象序列化助你提高效率
【C#/Java】【小白必看】不要只会读写文本文件了!对象序列化助你提高效率 在编程的世界里,文件的读写操作是我们经常面对的任务之一。 当我们只涉及简单的文本文件时,这个任务似乎并不复杂。但是,当我们处理更为复杂的类对…...

排障启示录-无线终端信号弱
现象:无线终端显示信号弱 信息收集: AP的实际发射功率低。外置天线型AP,天线松动或者没插天线现场环境问题,信号穿透衰减终端接入远端AP终端个体问题 排查步骤: 1、AP的发射功率低 查看AP的射频功率,判…...

gem5 RubyPort: mem_request_port作用与连接 simple-MI_example.py
简介 回答这个问题:RubyPort的口下,一共定义了六个口,分别是mem_request_port,mem_response_port,pio_request_port,pio_response_port,in_ports, interrupt_out_ports,他们分别有什…...

无人机支持的空中无蜂窝大规模MIMO系统中上行链路分布式检测
无人机支持的空中无蜂窝大规模MIMO系统中上行链路分布式检测 无人机支持的空中无蜂窝大规模MIMO系统中上行链路分布式检测介绍题目一. 背景(解决的问题)二. 系统模型信道模型信道系数进行标准化 信道估计 和 数据传输信道估计上行数据传输 三. 具体的流程…...

文献速递:生成对抗网络医学影像中的应用—— CG-3DSRGAN:用于从低剂量PET图像恢复图像质量的分类指导的3D生成对抗网络
文献速递:生成对抗网络医学影像中的应用—— CG-3DSRGAN:用于从低剂量PET图像恢复图像质量的分类指导的3D生成对抗网络 本周给大家分享文献的主题是生成对抗网络(Generative adversarial networks, GANs)在医学影像中的应用。文献…...
前端验收测试驱动开发
我们听说过很多关于测试驱动开发(TDD)的内容。那么什么是ATDD? ATDD代表验收测试驱动开发,这是一种定义验收标准并创建自动化测试来验证是否满足这些标准的软件开发方法。ATDD是一种协作方法,涉及客户、开发人员和测试…...
图像卷积操作
目录 一、互相关运算 二、卷积层 三、图像中目标的边缘检测 四、学习卷积核 五、特征映射和感受野 一、互相关运算 严格来说,卷积层是个错误的叫法,因为它所表达的运算其实是互相关运算(cross-correlation),而不是…...

目标检测入门体验,技术选型,加载数据集、构建机器学习模型、训练并评估
Hi, I’m Shendi 1、目标检测入门体验,技术选型,加载数据集、构建机器学习模型、训练并评估 在最近有了个物体识别的需求,于是开始学习 在一番比较与询问后,最终选择 TensorFlow。 对于编程语言,我比较偏向Java或nod…...

【UE5插件推荐】运行时,通过HTTP / HTTPS下载文件(Runtime Files Downloader)
UE5 github Home gtreshchev/RuntimeFilesDownloader Wiki (github.com)...
信息论安全与概率论
目录 一. Markov不等式 二. 选择引理 三. Chebyshev不等式 四. Chernov上限 4.1 变量大于 4.2 变量小于 信息论安全中会用到很多概率论相关的上界,本文章将梳理几个论文中常用的定理,重点关注如何理解这些定理以及怎么用。 一. Markov不等式 假定…...

各种不同语言分别整理的拿来开箱即用的8个开源免费单点登录(SSO)系统
各种不同语言分别整理的拿来开箱即用的8个开源免费单点登录(SSO)系统。 单点登录(SSO)是一个登录服务层,通过一次登录访问多个应用。使用SSO服务可以提高多系统使用的用户体验和安全性,用户不必记忆多个密…...

Netty Review - 优化Netty通信:如何应对粘包和拆包挑战
文章目录 概述Pre概述场景复现解决办法概览方式一: 特殊分隔符分包 (演示Netty提供的众多方案中的一种)流程分析 方式二: 发送长度(推荐) DelimiterBasedFrameDecoder 源码分析 概述 Pre Netty Review - 借助SimpleTalkRoom初体验…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...

GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...

MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
Webpack性能优化:构建速度与体积优化策略
一、构建速度优化 1、升级Webpack和Node.js 优化效果:Webpack 4比Webpack 3构建时间降低60%-98%。原因: V8引擎优化(for of替代forEach、Map/Set替代Object)。默认使用更快的md4哈希算法。AST直接从Loa…...
探索Selenium:自动化测试的神奇钥匙
目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...

wpf在image控件上快速显示内存图像
wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像(比如分辨率3000*3000的图像)的办法,尤其是想把内存中的裸数据(只有图像的数据,不包…...
鸿蒙(HarmonyOS5)实现跳一跳小游戏
下面我将介绍如何使用鸿蒙的ArkUI框架,实现一个简单的跳一跳小游戏。 1. 项目结构 src/main/ets/ ├── MainAbility │ ├── pages │ │ ├── Index.ets // 主页面 │ │ └── GamePage.ets // 游戏页面 │ └── model │ …...

jdbc查询mysql数据库时,出现id顺序错误的情况
我在repository中的查询语句如下所示,即传入一个List<intager>的数据,返回这些id的问题列表。但是由于数据库查询时ID列表的顺序与预期不一致,会导致返回的id是从小到大排列的,但我不希望这样。 Query("SELECT NEW com…...