一文看懂Transformer(详解)

news2025/7/15 17:31:55

文章目录

    • Transformer
      • 前言
      • 网络结构图:
      • Encoder
        • Input Embedding
        • Positional Encoder
        • self-attention
        • Padding mask
        • Add & Norm
        • Feed Forward
      • Decoder
        • input
        • masked Multi-Head Attention
        • test时的Decoder
      • 预测

Transformer

前言

Transformer最初是用于nlp领域的翻译任务。

出自谷歌2017年发表的论文Attention Is All You Need

当然现在已经应用于各类任务了,在CV领域也表现非常出色。本文是自己的学习笔记,因为我主要是看图像方面的,所以中间有些关于nlp的一些特殊知识没有详细说,如有兴趣,请自行查阅。

参考链接:

台大李宏毅自注意力机制和Transformer详解

李沐老师讲解Transformer

自注意力机制讲解

Transformer详解

Transformer 详解

详解Transformer (Attention Is All You Need)

Transformer模型详解(图解最完整版)

网络结构图:

这个结构图很清晰,左边是编码器,右边是解码器。

编码器:由N=6个相同的层堆叠而成。每层有两个子层。第一层是一个multi-head self-attention机制,第二层是一个简单的、按位置排列的全连接前馈网络。两个子层都采用了一个residual(残差)连接,然后进行层的归一化。也就是说,每个子层的输出是LayerNorm(x + Sublayer(x)),其中Sublayer(x)是由子层本身的输出。
解码器:解码器也是由N=6个相同层的堆栈组成。注意,解码器也是有输入的,解码器的输入先经过一个masked multi-head self-attention,然后是残差和layerNorm,然后再与编码器的输出一起送入一个与编码器一样的结构。重复6次。最后经过线性层和softmax输出结果。

在这里插入图片描述

我们一步一步的看,先说左边的编码器。

Encoder

Input Embedding

首先说input输入,既然是做翻译任务那么输入自然是一个句子,比如I love you

那么这个肯定不能直接输入进去,计算机也不认识啊,一般我们都需要转化为方便计算机处理的形式。在图像领域,我们会把图像处理为[B,C,H,W]的矩阵交给计算机处理,那么nlp领域也是一样,我们可以采用一种方法讲单词转化为向量:One-hot 独热码

非常简单,就是假设词汇表一共只有五个单词,那我就用一个长度=5的向量,第一个单词就是{10000},第二个{01000},以此类推,如图所示。如果字典一共有五千个词汇,那么编码得到的向量长度就是5000。

img

但是这种方法很显然不好,它很稀疏(有效信息太少),而且很长(太长了计算量太大了)。

更重要的是这种编码方式完全无法体现出来词汇之间的关系,比如“香蕉”和“西瓜”,都是水果,他们是有联系的,但是这种编码方式忽略了关系,只与他们在词汇表的位置有关。

那么有另外一个方法叫做word Embedding,他会给每一个词汇对应一个向量,并且这个向量是包含语义的信息的。

在这里插入图片描述

至于word Embedding是怎么做的,这里不说了,感兴趣的自己搜索看下,我主要是做图像的。

我们只要知道,Transformer的第一步Input Embedding就是将输入的词汇,编码成了一个一个的向量(长度为512)。

Positional Encoder

转化为词向量后还需要给每个词向量添加位置编码positional encoding。因为位置是有用的,同样一个单词放在句首和放在句中,可能会有不同的词性,会有不同的意思,所以位置信息我们也需要。

如何获得位置编码?论文中使用正余弦位置编码来为每个词计算位置向量。位置编码通过使用不同频率的正弦、余弦函数生成,生成的向量长度与词向量长度一致(待会要相加)。

正余弦位置编码计算公式如下,至于为什么这样设计,可以看其他的讲解文章Transformer 中的 Positional Encoding

img

经过这个我们可以得到位置编码,再和前面得到的词向量做加法,就得到了我们处理好的输入。

在这里插入图片描述

假设输入的是I Love You,那么最后这个输入的尺寸就是[3,512]

接下来才开始进入真正的编码器部分。

在这里插入图片描述

self-attention

Transformer就是基于自注意力的

关于self-attention,可以看我在另一篇博客中的介绍:自注意力机制

这里就简单说下:

简单来说就是输入的向量x,分别与三个矩阵相乘得到 Q , K , V Q,K,V Q,K,V,也就是query,key,value

这里x的大小是[2,512], W Q W^Q WQ的大小是[512,64],所以得到的结果是[2,64],如果输入是三个单词,那就是[3,64]

img

然后Q和 K T K^T KT相乘得到注意力分数,再做一个softmax映射,然后再与V相乘,就得到了自注意力的输出。

img

这里为什么要除以一个根号下dk(dk就是K的维度,也就是64),是因为公式中计算矩阵Q和K每一行向量的内积,为了防止内积过大,因此除以向量维度的平方根。

这里注意,我们假设输入的尺寸是[3,512],计算得到的Q,K,V都是同样的尺寸[3,64],然后Q乘以 K T K^T KT就得到[3,3]大小,再乘以V:[3,64],最终得到的结果是[3,64]大小。

这个V其实就相当于,输入向量本身,注意力分数就是考虑了全部的相关性,V与注意力分数相乘,就是相当于输入序列考虑了所有的单词,然后进行有侧重的调整。

这就是自注意力机制,那么多头自注意力机制就是使用多组Q,K,V,来得到多个结果,最后拼接在一起。

假设我们用8个头,那么就会得到8个[3,64]的矩阵,cat在一起就是[3,64*8]=[3,512]大小。

img

但是我们还是需要[3,64]的大小,所以将这个结果再乘以一个权重矩阵[512,64]的,就能变回原来的大小了。

img

最终的Z就作为后面模块的输入。

Padding mask

这里强调一个东西Padding mask

我们的输入数据是一个单词序列。那么每个单词被编码后,得到的是不同长度的词向量。

有的长,有的短,这个时候我们就会做补齐操作,一般是填充0。0乘以其他数字也是0,所以我们经过自注意力得到的结果里面也有很多0,然后在我们进行softmax的时候就有问题了。softmax是指数运算, e 0 = 1 e^0=1 e0=1是有值的,所以这些填充的0会影响到计算结果。

这就相当于让无效的部分参与了运算。因此需要做一个 mask 操作,让这些无效的区域不参与运算,一般是给无效区域加一个很大的负数偏置,趋近于 − ∞ -∞ ,这样的话再做softmax,他就会趋近于0,就不会影响到结果。

在这里插入图片描述

这个就叫做padding mask。具体的做法就是我们有一个mask矩阵,不需要mask的位置是False,需要mask的位置是True,然后在我们计算出注意力分数之后,对已经计算好的scores,按照mask矩阵,填-1e9。下一步计算softmax的时候,被设置成-1e9的数对应的值~0,被忽视。

img

Add & Norm

经过自注意力机制之后呢,图上写着Add & Norm

Add的意思就是一个残差连接,

Norm 的意思是归一化,但是这里要注意,这里不是我们图像里面常用的Batch Normalization(BN)

Batch Normalization的目的是使我们的一批(Batch)feature map满足均值为0,方差为1的分布规律。

BN对整个Batch进行操作,就是对每一列进行操作。啥意思呢,假设batchsize=3,有三行数据,分别是身高,体重,年龄。

在这里插入图片描述

BN是对每一列做归一化,使其满足均值为0,方差为1的分布规律

而Layer Normalization(LN)则是对每一行进行归一化。
在这里插入图片描述

这里看起来不太合理,对每一行进行归一化就乱了。但是nlp领域很适合LN。

因为我们每一行是一句话,所以对每一行做归一化是合理的,相反对每一列做归一化是不合理的。

这里我解释的不一定对,大家可以搜一些别的资料看看。反正这个就是做归一化的。

公式表示如下:

img

Feed Forward

这里比较简单,就是一个两层的神经网络,先线性变换,过一个ReLU,然后再线性变换即可。

公式表示如下:

img

X是输入,Feed Forward 最终得到的输出矩阵的维度与X一致。

W1和W2的大小取反即可。假设输入X大小是[3,64],那么W1取[64,1024],W2取 [1024,64]。

(3,64)x(64,1024)x(1024,64)=(3,64)大小不变。

FeedForward的作用是:通过线性变换,先将数据映射到高纬度的空间再映射到低纬度的空间,提取了更深层次的特征。

FeedForward完了之后再经过一个Add&Norm,得到一个[3,64]的大小

至此Encoder部分就结束了

将输出再作为输入,将此部分重复N次。

Decoder

input

翻译是一个seq2seq的任务,输入三个单词我们并不知道要翻译出来几个单词,这些是不确定的。

所以我们需要让网络知道在哪里结束,所以我们翻译我爱你的时候

Encoder的输入是我爱你

Decoder的输入是<start>我爱你

Decoder的输出是I love you <end>

首先说Decoder的输入,有两种输入,一种是训练时候的输入,一种是预测时候的输入。

  • 训练的时候:输入为Ground Truth,也就是不管输出是什么,会将正确答案当做输入,这种模式叫做teacher-forcing
  • 预测的时候:预测的时候没有正确答案,那么我们的输入是已有的预测,具体来说就是先输入一个<start>然后过一遍decoder,让网络预测出I,然后将<start> I当作输入,再过一遍decoder,以此类推,最终翻译出整个句子。所以,这里我们可以看出来,预测的时候Decoder并不是并行的,而是串行的,需要一个单词一个单词去预测。

Decoder这边的输入,同样的经过位置编码,相加之后,输入进去。

同样的Decoder的输入也不是等长的,所以我们Decoder部分也需要一个Padding mask

接下来才是Decoder核心的部分。

masked Multi-Head Attention

首先是一个masked Multi-Head Attention

在这里插入图片描述

可以看到,这里和Encoder里面的自注意力不一样,加了个mask,为什么加了个mask呢。

我们首先来看下,Decoder部分输入句子我爱你,经过编码送入自注意力中,如下图所示

在这里插入图片描述

Q和K的转置相乘就是注意力分数,然后会做一个softmax。在做softmax之前,要注意,最后这个[4,4]的矩阵,第一行代表的就是第一个词语<start>与整个句子四个词语分别计算得到的相关性。第二行同理。

在这里插入图片描述

但是有一个问题,我们现在是在训练,我们自然掌握了Ground Truth,但是我们实际预测的时候,没有标准答案,实际的预测是我们把<start>输入进去,然后网络预测出I,然后将<start> I当作输入,再过一遍decoder,以此类推,最终翻译出整个句子。那我们训练的时候怎么做到这一点呢?

这就是用到sequence mask了,在softmask之前,用一个掩码矩阵,右上角全部是一个负的极大值,左下角为0,与注意力分数的矩阵相加,就可以保留下来左下角的数据了。经过softmax,右上角的数据都会被处理为0。

img

这个操作的意义就在于,经过这个操作,第一行<start>,只能看到它跟自己的注意力分数(相关度),而第二行字,可以看到他与<start>的注意力分数,同理,第三行能看到前三个的,每一个单词都只能考虑他以及他之前的单词。这是符合预测的,因为第一个单词进来的时候,是不应该看到之后的单词的,实际中我们做预测的时候也确实是这么做的。所以训练的时候使用masked多头自注意力。

1

将这个mask后的注意力分数,经过softmax,在与V相乘,就得到自注意力的输出Z,这个Z的第一行Z1只包含第一个单词的信息,第二行只包含前两个单词的信息,以此类推。多个头,就得到了多个Z

img

多头的结果cat起来,经过一个线性层,改变尺寸,使尺寸与出入同样大小。

然后经过Add&Norm,这就和Encoder那里一样。这样,解码器的第一部分就完成了。

解码器的第二部分,没有什么新的东西,主要就是,将编码器的输出,计算得到Q和K,然后将解码器第一部分的输出,计算得到V,拿这个Q,K,V去参与自注意力运算,最后再过一个Add&Norm,然后再过一个Feed Forward,再过一个Add&Norm。就结束,这就是整个Decoder的内容。将这部分也重复N次。

在这里插入图片描述

编码器和解码器都会重复N次,但是解码器中使用的编码器的结果,都是最后一次编码器给出的。他们的关系是这样的

img

test时的Decoder

上面说的是训练时候的decoder,实际测试的时候,比如我们输入我爱你,让网络翻译。

实际的流程是我爱你被输入到Encoder中,最顶层的Eecoder输出一个结果,然后Decoder中输入<start>,经过Decoder输出I,然后再将<start>I一同输入Decoder,用结果的最后一个维度来预测love

预测

Decoder完了之后,就是最后一部分,预测单词

在这里插入图片描述

Decoder的输出,会经过一个线性层,在经过一个softmax,输出概率来预测单词。

比如,最后得到的矩阵是[4,512],那么第一行中512个元素的概率,最大的那个假设是25,那么说明预测的第一个单词就是对应的词汇表25位置上的单词。

因为 Mask 的存在,使得单词 0 的输出 Z0 只包含单词 0 的信息

img

Softmax 根据输出矩阵的每一行预测下一个单词

img

这也使得我们训练的时候,Decoder可以并行,我们一次就可以预测所有的单词。

我们可以直接使用最后一行的预测结果,与真实值做loss计算。

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

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

相关文章

大屏图表,ECharts 从“熟练”到入门

&#x1f4d6;阅读本文&#xff0c;你将 了解 配置驱动 的思想理解 Echarts 基本概念了解 graphic 和 动画基本玩法。了解 Echarts 基底组件的封装的思路 一、不是标题党&#xff01;Echarts&#xff0c;简历上人均 “熟练”&#xff1f; 公司最近在招外包&#xff0c;而因为…

基于ASP学生资助管理系统的设计与实现

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做ASP程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问题…

用Python蹭别人家图片接口,做一个【免费图床】吧

打开本文&#xff0c;相信你确实需要一个免费且稳定的图床&#xff0c;这篇博客就让你实现。 文章目录⛳️ 谁家的图床⛳️ 实战编码⛳️ 第一轮编码⛳️ 第二轮编码⛳️ 第三轮编码⛳️ 第四轮编码⛳️ 谁家的图床 这次咱们用新浪微博来实现【免费图床应用】&#xff0c;通过…

栈浅谈(上)

目录 栈的定义 栈的实现 初始化 判断栈是否为空 入栈操作 获取栈顶元素 出栈操作 遍历栈 销毁栈 完整代码演示 栈—STL 基本操作 例题 参考代码 栈的定义 说到栈&#xff0c;一些不会计算机语言的“小白”&#xff08;我就是&#xff09;就会想到栈道之类的词语…

基于JavaWeb的婚恋交友网站设计与实现

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…

如何平衡新老策略的好与坏,一道常见风控送命题解答

作为一个风控策略从业者&#xff0c;在做风险管理的过程中一直在做的就是&#xff0c;不断的挖掘有效的变量特征来填充风控决策体系&#xff0c;使决策体系的功效变大变强&#xff0c;最终形成一套可变的稳定风险护盾。我们常见的一个场景比如如何筛选一些新策略来挑战老策略&a…

【C++中预处理语句 include、define、if】

1.预处理阶段 预处理阶段&#xff0c;在实际发生编译之前就根据对应的预处理语句进行操作&#xff0c;等到预处理阶段完成之后才进行编译阶段 。 2.预处理语句 预处理语句主要有include、define、if 和 program。利用 # 进行标记 2.1 include语句 include语句就是将所包含的…

if-else练习

if单分支 输入两个数&#xff0c;分别放入x和y中&#xff0c;若两数不相等&#xff0c;则输出其中的大数&#xff0c;若两数相等&#xff0c;则输出字符串“xy&#xff1a;”并输出其值 #define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> int main() {int a 0;int …

智慧油田解决方案-最新全套文件

智慧油田解决方案-最新全套文件一、建设背景1、智慧油田的概念及意义2、智慧油田的建设目标二、建设思路三、建设方案四、获取 - 智慧油田全套最新解决方案合集一、建设背景 1、智慧油田的概念及意义 石油产量、采收率、安全生产等都与石油工业未来息息相关&#xff0c;随着石…

十八、CANdelaStudio深入-Data Types

本专栏将由浅入深的展开诊断实际开发与测试的数据库编辑,包含大量实际开发过程中的步骤、使用技巧与少量对Autosar标准的解读。希望能对大家有所帮助,与大家共同成长,早日成为一名车载诊断、通信全栈工程师。 本文介绍CANdelaStudio的Data Types(数据类型),欢迎各位朋友订…

旧系统改造

背景 很多时候&#xff0c;我们在项目前期会优先确保项目业务的落地&#xff0c;在短时间内进行项目冲刺&#xff0c;最后完成项目上线。这样做让短时间内的目标达貌似达成了&#xff0c;却给系统留下了很大的隐患。 在项目的冲刺过程中&#xff0c;我们的精力大部分花在了业…

动态规划-不同路径

一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。 问总共有多少条不同的路径&#xff1f; 示例 …

单源广度优先搜索 (leetcode经典例题 C++实现)

文章目录01矩阵地图分析腐烂的橘子深度优先搜索与广度优先搜索前情回顾&#xff1a; 深度搜索dfs与广度搜索bfs算法总结&#xff08;c 例题&#xff09; 本节是广度优先搜索的进阶&#xff1a; 01矩阵 传送门&#xff1a; https://leetcode.cn/problems/01-matrix/?envType…

JavaWeb----Servlet技术

JavaEE简介 什么是JavaEE JavaEE&#xff08;Java Enterprise Edition&#xff09;&#xff0c;Java企业版&#xff0c;是一个用于企业 级web开发平台,它是一组Specification。最早由Sun公司定制并发 布&#xff0c;后由Oracle负责维护。在JavaEE平台规范了在开发企业级web 应…

【操作系统】死锁(详细)

文章目录一、死锁的概念二、死锁的产生因素三、死锁的必要条件1、互斥条件2、占有和等待条件&#xff08;部分分配条件&#xff09;3、不剥夺条件4、循环等待条件&#xff08;环路条件&#xff09;四、死锁防止1、破坏互斥条件2、破坏占有和等待条件3、破坏不剥夺条件4、破坏循…

Ceph文件系统

目录 一、环境准备 二、什么是文件系统 三、ceph块存储与文件系统区别 四、创建ceph文件系统 1、启动MDS服务 2、创建存储池 3、创建Ceph文件系统 4、客户端挂载 一、环境准备 Ceph集群搭建参照&#xff1a;Ceph集群部署_桂安俊kylinOS的博客-CSDN博客 以下Ceph存储实…

springcloud22:sentinal的使用

sentinal对比&#xff08;分布式系统的流量防卫&#xff09; 监控保护微服务 Hystrix 需要自己去手工搭建监控平台&#xff0c;没有一套web界面可以进行细粒度化的配置&#xff0c;流控&#xff0c;速率控制&#xff0c;服务熔断&#xff0c;服务降级… 整合机制&#xff1a;se…

外卖项目08---Linux

目录 一、 Linux简介 119 二、Linux安装 120 三、常用命令 122 3.1Linux命令初体验 3.1.1 command [-options] [parameter] 3.2Linux常用命令---文件目录操作命令-ls&-cd&-cat 124 3.2.1list 3.2.2 cd 3.2.3 cat 3.3 Linux常用命令---文件目录操作命令…

9.前端笔记-CSS-CSS三大特性

三大特性&#xff1a;层叠性、继承性、优先级 1、层叠性&#xff08;覆盖性&#xff09; 给相同的选择器设置相同的样式&#xff0c;此时一个样式会覆盖&#xff08;层叠&#xff09;其他冲突的样式。 层叠性原则&#xff1a; 同一选择器&#xff0c;样式冲突&#xff0c;遵…

OpenMV输出PWM,实现对舵机控制

OpenMV的定时器官方函数介绍&#xff1a;Timer类 – 控制内部定时器 目录 OpenMV的PWM资源介绍 为什么要用OpenMV输出PWM OpenMV的PWM资源分配 资源 注意 建议 PWM输出代码 代码讲解 Timer Timer.channel tim.channel与Timer.channel区别 Timer.channel解析 OpenM…