【Bert101】变压器模型背后的复杂数学【02/4】

一、说明

        众所周知,变压器架构是自然语言处理(NLP)领域的突破。它克服了 seq-to-seq 模型(如 RNN 等)无法捕获文本中的长期依赖性的局限性。变压器架构被证明是革命性架构(如 BERT、GPT 和 T5 及其变体)的基石。正如许多人所说,NLP正处于黄金时代,说变压器模型是一切开始的地方并没有错。

二、对变压器架构的需求

        如前所述,需求是发明之母。传统的 seq-to-seq 模型在处理长文本时并不好。这意味着模型在处理输入序列的后半部分时,往往会忘记输入序列前半部分的学习。这种信息丢失是不可取的。

        尽管像 LSTM 和 GRU 这样的门控架构通过丢弃在记住重要信息的过程中无用的信息,在处理长期依赖关系方面表现出一些改进,但这仍然不够。世界需要更强大的东西,2015年,Bahdanau等人引入了“注意力机制”。 它们与RNN / LSTM结合使用,以模仿人类行为,专注于选择性事物,而忽略其余事物。Bahdanau建议为句子中的每个单词分配相对重要性,以便模型专注于重要的单词而忽略其余单词。它被认为是对神经机器翻译任务的编码器-解码器模型的巨大改进,很快,注意力机制的应用也在其他任务中推广。

变压器模型时代

        变压器模型完全基于一种注意力机制,也称为“自我注意”。这种架构在 2017 年的论文“注意力是你所需要的一切”中向世界介绍。它由编码器-解码器架构组成。

无花果。高级转换器模型体系结构(来源:作者)

在高层次上,

  • 编码器负责接受输入的句子并将其转换为隐藏的表示形式,丢弃所有无用的信息。
  • 解码器接受此隐藏表示形式并尝试生成目标句子。

在本文中,我们将深入研究变压器模型的编码器组件的详细细分。在下一篇文章中,我们将详细介绍解码器组件。让我们开始吧!

三、变压器编码器

        变压器的编码器块由一堆按顺序工作的N个编码器组成。一个编码器的输出是下一个编码器的输入,依此类推。最后一个编码器的输出是馈送到解码器块的输入句子的最终表示形式。

无花果。带堆叠编码器的Enoder模块(来源:作者)

如下图所示,每个编码器块可以进一步分成两个组件。

        无花果。编码器层的组件(来源:作者)

        让我们逐一详细研究这些组件中的每一个,以了解编码器块的工作原理。编码器模块中的第一个组成部分是多头注意力,但在我们进入细节之前,让我们先了解一个基本概念:自我注意

3. 1 自我注意机制

        每个人脑海中可能出现的第一个问题:注意力和自我注意力是不同的概念吗? 是的,他们是。(咄!

        传统上,注意力机制是为神经机器翻译任务而存在的,如上一节所述。因此,本质上应用了注意力机制来映射源句和目标句。当 seq-to-seq 模型逐个令牌执行翻译任务时,注意机制可帮助我们在为目标句子生成标记 x 时识别源句子中的哪些标记需要更多关注。为此,它利用编码器和解码器的隐藏状态表示来计算注意力分数,并根据这些分数生成上下文向量作为解码器的输入。如果您想了解有关注意力机制的更多信息,请跳到这篇文章(精彩的解释!

        回到自我注意,主要思想是计算注意力分数,同时将源句子映射到自身。如果你有这样的句子,

“男孩没有过马路因为它太宽了。

        我们人类很容易理解上面句子中的“它”一词指的是“道路”,但是我们如何使我们的语言模型也理解这种关系呢?这就是自我关注的地方!

在高层次上,将句子中的每个单词与句子中的每个其他单词进行比较,以量化关系并理解上下文。出于表示目的,您可以参考下图。

让我们详细看看这种自我注意是如何计算的(真实)。

  • 为输入句子生成嵌入

查找所有单词的嵌入并将它们转换为输入矩阵。这些嵌入可以通过简单的标记化和独热编码生成,也可以通过嵌入算法(如BERT等)生成。输入矩阵的维度将等于句子长度 x 嵌入维度。我们称此输入矩阵为 X 以供将来参考。

  • 将输入矩阵转换为Q,K和V

为了计算自我注意,我们需要将X(输入矩阵)转换为三个新矩阵:
- 查询 (Q)- 键 (K)- 值 (V)

 

为了计算这三个矩阵,我们将随机初始化三个权重矩阵,即Wq,Wk和Wv。输入矩阵X将与这些权重矩阵Wq,Wk和Wv相乘,分别获得Q,K和V的值。在此过程中将学习权重矩阵的最佳值,以获得更准确的Q,K和V值。

  • 计算 Q 和 K 转置的点积

从上图中,我们可以暗示 qi、ki 和 vi 表示句子中第 i 个单词的 Q、K 和 V 的值。

无花果。Q 和 K 转置的点积示例(来源:作者)

输出矩阵的第一行将告诉您由 q1 表示的 word1 如何与使用点积的句子中的其余单词相关。点积的值越高,单词越相关。为了直观地了解计算此点积的原因,您可以在信息检索方面理解 Q(查询)和 K(键)矩阵。所以在这里,
- Q 或查询 = 您正在搜索的术语
- K 或 Key = 搜索引擎中的一组关键字,与 Q 进行比较和匹配。

  • 缩放点积

与上一步一样,我们正在计算两个矩阵的点积,即执行乘法运算,该值有可能爆炸。为了确保这种情况不会发生并且梯度稳定,我们将 Q 和 K 转置的点积除以嵌入维度 (dk) 的平方根。

  • 使用 softmax 规范化值

使用 softmax 函数进行归一化将产生介于 0 和 1 之间的值。具有高比例点积的单元格将进一步升高,而低值将减少,使匹配的单词对之间的区别更加清晰。生成的输出矩阵可以视为分数矩阵S

  • 计算注意力矩阵 Z

        将值矩阵或V乘以从上一步获得的分数矩阵S,以计算注意力矩阵Z。

        但是等等,为什么要乘法?

        假设 Si = [0.9, 0.07, 0.03] 是句子中第 i 个单词的分数矩阵值。将此向量与 V 矩阵相乘以计算 Zi(第 i 个单词的注意力矩阵)。

Zi = [0.9 * V1 + 0.07 * V2 + 0.03 * V3]

        我们是否可以说,为了理解第 i 个单词的上下文,我们应该只关注 word1(即 V1),因为注意力分数值的 90% 来自 V1?我们可以清楚地定义重要的单词,在这些单词中,应该更加注意理解第i个单词的上下文。

        因此,我们可以得出结论,一个词在Zi表示中的贡献越高,单词之间的批判性和相关性就越大。

        现在我们知道了如何计算自我注意力矩阵,让我们了解多头注意力机制的概念。

3.2 多头注意力机制

        如果您的分数矩阵偏向于特定的单词表示,会发生什么?它会误导您的模型,结果不会像我们预期的那样准确。让我们看一个例子来更好地理解这一点。

        S1:“一切都很好

        Z(井) = 0.6 * V(全部) + 0.0 * v(是) + 0.4 * V(井)

        S2:“狗吃了食物,因为它饿了

        Z(它) = 0.0 * V(的) + 1.0 * V(狗) + 0.0 * V(吃) + ...... + 0.0 * V(饥饿)

        在 S1 情况下,在计算 Z(well) 时,对 V(all) 给予了更多的重要性。它甚至比V(好吧)本身还要多。无法保证这有多准确。

        在 S2 的情况下,在计算 Z(it) 时,所有的重要性都给了 V(dog),而其余单词的分数也是 0.0,包括 V(it)。这看起来可以接受,因为“it”这个词是模棱两可的。将它更多地与另一个词联系起来而不是将这个词本身联系起来是有意义的。这就是计算自我注意力的全部目的。处理输入句子中歧义单词的上下文。

        换句话说,我们可以说,如果当前单词是模棱两可的,那么在计算自我注意时可以更加重视其他单词,但在其他情况下,这可能会对模型产生误导。那么,我们现在该怎么办?

        如果我们计算多个注意力矩阵而不是计算一个注意力矩阵并从中导出最终的注意力矩阵会怎样?

        这正是多头注意力的全部意义所在!我们计算注意力矩阵z1,z2,z3,.....,zm的多个版本,并将它们连接起来以得出最终的注意力矩阵。这样我们就可以对自己的注意力矩阵更有信心。

        转到下一个重要概念,

3.3 位置编码

        在seq-to-seq模型中,输入的句子被逐字输入到网络,这允许模型跟踪单词相对于其他单词的位置。

        但在变压器模型中,我们遵循不同的方法。它们不是逐字逐句地输入,而是并行馈送,这有助于减少训练时间和学习长期依赖性。但是使用这种方法,单词顺序就丢失了。但是,要正确理解句子的含义,词序非常重要。为了克服这个问题,引入了一种称为“位置编码”(P)的新矩阵。

        该矩阵 P 与输入矩阵 X 一起发送,以包含与词序相关的信息。出于显而易见的原因,X 和 P 矩阵的维度是相同的。

        为了计算位置编码,使用下面给出的公式。

        fig。计算位置编码的公式(来源:作者)

在上面的公式中,

  • pos = 单词在句子中的位置
  • d = 字/标记嵌入的维度
  • i = 表示嵌入中的每个维度

在计算中,d 是固定的,但 pos 和 i 会有所不同。如果 d=512,则 i ∈ [0, 255],因为我们取 2i。

如果您想了解更多信息,本视频将深入介绍位置编码。

转换器神经网络可视化指南 — (第 1 部分)位置嵌入

我正在使用上述视频中的一些视觉效果来用我的话来解释这个概念。

无花果。位置编码向量表示(来源:作者)

上图显示了位置编码向量的示例以及不同的变量值。

无花果。具有常数 i 和 d 的位置编码向量(来源:作者)

fig。具有常数 i 和 d 的位置编码向量(来源:作者)

上图显示了如果 i 是常量并且只有 pos 变化,PE(pos, 2i) 的值将如何变化。众所周知,正弦波是一个周期函数,倾向于在固定间隔后重复。我们可以看到 pos = 0 和 pos = 6 的编码向量是相同的。这是不可取的,因为我们需要不同的位置编码向量来表示不同的 pos 值

这可以通过改变正弦波的频率来实现。

无花果。具有不同 pos 和 i 的位置编码向量(来源:作者)

随着i的值变化,正弦波的频率也随之变化,导致不同的波,因此,导致每个位置编码向量的值不同。这正是我们想要实现的目标。

位置编码矩阵(P)被添加到输入矩阵(X)并馈送到编码器。

无花果。将位置编码添加到输入嵌入(来源:作者)

编码器的下一个组件是前馈网络

3.4 前馈网络

        编码器块中的这个子层是具有两个密集层和 ReLU 激活的经典神经网络。它接受来自多头注意力层的输入,对同一层执行一些非线性变换,最后生成上下文化向量。全连接层负责考虑每个注意力头并从中学习相关信息。由于注意力向量彼此独立,因此它们可以以并行方式传递到变压器网络。

        编码器块的最后一个也是最后一个组件是Add&Norm组件

3.5 添加和规范组件

这是一个残差层,然后是层归一化。残差层确保在处理过程中不会丢失与子层输入相关的重要信息。而规范化层可促进更快的模型训练并防止值发生大量变化。

无花果。包含添加和规范层的编码器组件(来源:作者)

        在编码器中,有两个添加层和规范层:

  • 将多头注意力子层的输入连接到其输出
  • 将前馈网络子图层的输入连接到其输出

        至此,我们总结编码器的内部工作。总结本文,让我们快速回顾一下编码器使用的步骤:

  • 生成输入句子的嵌入或标记化表示。这将是我们的输入矩阵 X。
  • 生成位置嵌入以保留与输入句子的词序相关的信息,并将其添加到输入矩阵 X 中。
  • 随机初始化三个矩阵:Wq,Wk和Wv,即查询,键和值的权重。这些权重将在变压器模型训练期间更新。
  • 将输入矩阵X与Wq,Wk和Wv中的每一个相乘,以生成Q(查询),K(键)和V(值)矩阵。
  • 计算 Q 和 K 转置的点积,通过将其除以 dk 的平方根或嵌入维数来缩放乘积,最后使用 softmax 函数对其进行归一化。
  • 通过将 V 或值矩阵乘以 softmax 函数的输出来计算注意力矩阵 Z。
  • 将此注意力矩阵传递给前馈网络以执行非线性转换并生成上下文化嵌入。

四、后记 

        在下一篇文章中,我们将了解转换器模型的解码器组件的工作原理。这就是本文的全部内容。我希望你觉得它有用。如果你这样做了,请不要忘记鼓掌并与您的朋友分享。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/34813.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【阵列信号处理】空间匹配滤波器、锥形/非锥形最佳波束成形器、样本矩阵反演 (SMI) 研究(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

九耶丨阁瑞钛伦特-产品经理面试题

在产品上线后,会着重观察6类指标: 1、活跃用户指标 衡量APP用户规模的指标,一个产品是否成功,如果只看一个指标,那么这个指标一定是活跃用户数。 日活(DAU):一天内日均活跃设备数(去重,每个公…

关于使用pycharm遇到只能使用unittest方式运行,无法直接选择Run

相信大家可能都遇到过这个问题,使用pycharm直接运行脚本的时候,只能选择unittest的方式,能愁死个人 经过几次各种尝试无果之后,博主就放弃死磕了,原谅博主是个菜鸟 后来遇到这样的问题,往往也就直接使用cm…

Python爬虫-抓取的目标数据为#x开头,怎么解决?

前言 本文是该专栏的第4篇,后面会持续分享python爬虫案例干货,记得关注。 在做爬虫项目的时候,有时候抓取的平台目标数据为&#x开头,如下图所示: 浏览器显示的正常数据,但通过爬虫协议获取到的网页源码数据却是以&#x开头的隐藏数据,遇到这种情况,爬虫需要怎么处…

【Linux从入门到精通】文件I/O操作(C语言vs系统调用)

文章目录 一、C语言的文件IO相关函数操作 1、1 fopen与fclose 1、2 fwrite 1、3 fprintf与fscanf 1、4 fgets与fputs 二、系统调用相关接口 2、1 open与close 2、2 write和read 三、简易模拟实现cat指令 四、总结 🙋‍♂️ 作者:Ggggggtm 🙋‍…

Golang bitset 基本使用

安装: go get github.com/bits-and-blooms/bitset下面代码把fmtx换成fmt就行 //------------基本操作------------//构建一个64bit长度的bitsetb : bitset.New(64)//放入一个数b.Set(10)fmtx.Println("add-10:", b.DumpAsBits()) // 0000000…

针对英特尔酷睿 CPU 优化,Canonical 发布 Ubuntu 实时内核

导读Canonical 今天宣布针对支持时序协调运算(TCC)和时间敏感网络(IEEE TSN)的英特尔酷睿处理器,推出优化版实时 Ubuntu 内核。 Canonical 于今年 2 月宣布,为购买 Ubuntu Pro 订阅,使用代号为 …

OPENCV C++(七)霍夫线检测+找出轮廓和外接矩形+改进旋转

霍夫线检测 vector<Vec2f> lines1;HoughLines(canny_mat, lines1, 1, CV_PI / 180.0,90 );//45可以检测里面两条线 80检测出外边两条线 定义存放输出线的向量 此向量输出有<距离&#xff0c;角度> 因为检测的原理就是在变换霍夫空间里面去检测的&#xff0c;这里可…

ESP8266(RTOS SDK)内嵌网页以实现WEB配网以及数据交互

【本文发布于https://blog.csdn.net/Stack_/article/details/131997098&#xff0c;未经允许不得转载&#xff0c;转载须注明出处】 1、执行make menuconfig&#xff0c;将http头由512改为更大的值&#xff0c;否则用电脑浏览器访问正常&#xff0c;但用手机浏览器访问会因为ht…

基于weka手工实现K-means

一、K-means聚类算法 K均值聚类&#xff08;K-means clustering&#xff09;是一种常见的无监督学习算法&#xff0c;用于将数据集中的样本划分为K个不同的类别或簇。它通过最小化样本点与所属簇中心点之间的距离来确定最佳的簇划分。 K均值聚类的基本思想如下&#xff1a; …

【快应用】list组件如何区分滑动的方向?

【关键词】 list组件、滑动方向、scroll 【问题背景】 有cp反馈list这个组件在使用的时候&#xff0c;不知道如何区分它是上滑还是下滑。 【问题分析】 list组件除了通用事件之外&#xff0c;还提供了scroll、scrollbottom、scrolltop、scrollend、scrolltouchup事件&#x…

UIE在实体识别和关系抽取上的实践

近期有做信息抽取的需求&#xff0c;UIE在信息抽取方面效果不错。 模型准备 huggingface上下载UIE模型&#xff1a;PaddlePaddle/uie-base Hugging Face 点击“Clone Repository”&#xff0c;确定git clone的链接 其中包含大文件&#xff0c;需要在windows安装git-lfs&am…

九、多态(1)

本章概要 向上转型回顾 忘掉对象类型 转机 方法调用绑定产生正确的行为可扩展性陷阱&#xff1a;“重写”私有方法陷阱&#xff1a;属性与静态方法 多态是面向对象编程语言中&#xff0c;继数据抽象和继承之外的第三个重要特性。 多态提供了另一个维度的接口与实现分离&…

C++_模板初阶

在面向对象中&#xff0c;我们可以使用重载来实现多态。 但是问题在于&#xff0c;重载的函数仅仅是类型不同&#xff0c;代码复用率比较低&#xff0c;只要有新的类型出现时&#xff0c;就要增加对应的函数&#xff1b;另一方面它的代码可维护性比较低&#xff0c;一个出错可…

java实现文件的下载

系统日志的获取不可能每次都登录服务器&#xff0c;所以在页面上能够下载系统运行的日志是必须的 如何来实现日志的下载&#xff0c;这样的一个功能 前端我们用到的是window.open(...)这样可以发送一个get请求到后台 后台接收到get请求之后&#xff0c;如何实现对文件的下载 R…

ubuntu中redis+mysql安装使用

pip -V 回车&#xff08;大写V&#xff09;&#xff1a;python包库安装路径 python -m site: python查找路径 1、redis ubuntu安装redis System has not been booted with systemd as init system (PID 1). Cant operate&#xff1b;该问题是systemctl start redis报错&#…

ZLMediaKit(webrtc)在linux上(CentOS7)部署与启动

一.ZLMediaKit(webrtc)在CentOS7部署与启动 # 1. 卸载旧版本 yum remove git # 2. 安装 yum 源的 Git 版本 yum install -y git # 3. 查看版本 git version # 输出 git version 1.8.3.1配置全局环境变量 # 1. 编辑配置文件 vim /etc/profile # 2. 在 /etc/profile 文件中末尾…

用 Rufus 制作 Ubuntu 系统启动盘时,选择分区类型为MBR还是GPT?

当使用 Rufus 制作 Ubuntu 系统启动盘时&#xff0c;您可以根据您的需求选择分区类型&#xff0c;MBR&#xff08;Master Boot Record&#xff09;还是 GPT&#xff08;GUID Partition Table&#xff09;。 MBR 是传统的分区表格式&#xff0c;适用于大多数旧版本的操作系统和旧…

2023/08/13_____JMM JAVA Memory Model JAVA内存模型

JMM JAVA Memory Model java内存模型 作用&#xff1a;缓存一致性协议&#xff0c;用于定义数据读写的规则&#xff08;遵守&#xff0c;找到这个规则&#xff09; JMM定义了线程2工作内存和主内存之间的抽象关系&#xff1a;线程之间的共享变量存储在主内存&#xff08;main …

TLS协议

目录 什么是TLS协议&#xff1f; TLS的基本流程&#xff1f; 两种密钥交换算法&#xff1f; 基于ECDHE密钥交换算法的TLS握手过程&#xff1f; 基于RSA密钥交换算法的TLS握手过程&#xff1f; 基于RSA的握手和基于ECDHE的握手有什么区别&#xff1f; 什么是前向保密&…