前言
最近由ChatGPT带起来的人工智能风潮非常的很火,并且AI的发展日新月异,不同的产品也层出不穷,如AutoGPT、BabyAGI等。论文和研究概念在各个领域也得到了广泛关注,比如SAM。
对于人工智能小白,应该如何抓重点,补充自己的人工智能理论短板,不局限于AI产品上浅尝辄止的试玩呢,我的想法是先看NLP最重要的几篇核心论文和模型,包括Transformer模型,Bert模型,GPT模型,GPT2,GPT3,GPT4的模型演进发展,这样通过研究这些主流的模型和其中最重要的设计,就能够大致抓住AI发展的主线和脉络,做到心中有货,遇事不慌。
所以第一个需要了解的就是经典seq2seq模型:Transformer模型,一个基于编码器和解码器的模型,后续的Bert,GPT都是参考和借鉴传承了这个模型。
而Transformer变形金刚中,最重要的火种是什么呢?
就是今天要介绍的Self-Attention(自注意力)机制。
图:Self-Attention广泛运用于NLP自然语言处理
模型要解决的问题是什么
首先在进入Self-Attention模型介绍之前,得先搞清楚这些深度学习模型包括循环神经网络RNN和卷积神经网络CNN,到底是要解决什么问题,并且如何抽象解决这些问题。
比如上图,对于一段句子,我们需要识别每个单子的词性,是名词,动词还是形容词。
对于一段语音,我们需要识别每段音频中的识别音标。
对于一个社交网络,我们需要识别每个有连接的社交关系中哪些客户是有购买意愿的。
又比如,对于一段句子,我们需要知道这个句子的语义是正面的评价还是负面评价。比如发布了一个新产品,用户在网上的评价是赞美居多还是批评居多
对于一段语音,我们需要识别说话的人是谁,乔布斯?马斯克?马云?
对于一个分子结构,我们需要判断这个分子是否有毒性,或者亲水性如何
结合上述的两类例子,我们再看看每个输入,分别是一段句子,一段音频,一个图网络。
对于一段句子「this is a cat」,包含了四个词汇,每个词汇可以你可以用一个向量来表示。那么如何来表示呢,第一个比较好想的就是罗列所有的词汇(假如总共有10000个词),那么每个向量的长度就是10000,用1在不同位置的占位来区分,如上图左边的One-hot Encoding方式,但这有个问题就是每个词之间的关系没法表达,即如何表达cat和dog都是动物的含义呢,即cat和dog词义上是有相似性的,这个相似性怎么表示呢。
那么就引入了另外一种方式叫Word Embedding,每个词都是表示一个向量,如果把每个向量按照坐标系画出来,相近词就会聚集在一起。Word Embedding怎么得到的呢?我下次再专门搞个专题来分享。
总之,你可以把一个句子抽象为一排向量。不同的句子长短不一,那么对应的向量的个数也是不一样。但是每个向量自身的长度都是一样的。
接着对于一段音频序列,你也是可以把他抽象成一排向量,上图就是把每25ms的声音讯号变成一个向量即frame,下一个向量就由向后滑动10ms后的25ms时长的声音讯号转换而来。所以1s的声音讯号就会形成100个向量的集合。1分钟就是6000个向量的集合,可想而知一段短短的声音讯号包含的信息还是很多的。
接下来就是一个Graph图的案例。在一个社交网络中,每个人即为一个节点,也就是一个向量,可以拿每个人的简介信息包括姓名,年龄,性别,工作等信息计算出来一个向量来表示。那么一个社交网络也就是一个向量的集合。
甚至是图像,你都可以把每个像素当做一个向量,每个向量存在RGB三维的数据信息。一张图像也就是5*10个向量的序列集合。
总之想说的一点就是万物皆可向量化,即多模态输入可以统一抽象成一个数学表达。
所以结合上面的所有场景问题,抽象出来要解决的问题无非就是以上三大类:
-
输入是N个向量,经过模型处理后,输出是N个值。比如上面举例的句子中词语的词性问题。
-
输入是N个向量,经过模型处理后,输出是1个值。比如上面举例的一段音频是谁说的问题。
-
输入是N个向量,经过模型处理后,输出是N’个值,也就是俗称的sequence to sequence,比如Chatgpt就是一个典型的seq2seq,输入一个问题,输出一个答案。
自注意力(Self-Attention)的背景和概念
在过去的几年里,深度学习模型已经在各种任务中取得了显著的成果。然而,处理序列数据时,传统的深度学习模型(如循环神经网络RNN和卷积神经网络CNN)仍然面临一些挑战,例如长距离依赖问题和计算复杂性等。为了解决这些问题,研究人员提出了自注意力(Self-Attention)机制。
自注意力(Self-Attention)是一种用于捕获输入序列中不同位置间的依赖关系的方法,而无需考虑它们在序列中的固定距离。通过计算序列中每个元素与其他元素之间的相关性,自注意力机制使得模型能够对输入序列的全局信息进行建模,从而捕获长距离依赖。
说人话其实就举例刚才的例子「I saw a saw」如上图,在计算第二个词saw是个动词还是名词的时候,可以通过self-Attention模型层将I, saw, a, saw都一起看一遍,找出相似度大的信息,输出一个考虑了所有输入的向量信息,在经过FC层,进而得到结果第二个单词saw是个动词,而第四个单词saw是名词。
FC层,即全连接网络(Fully Connected Network, FCN)是一种常见的神经网络结构,其中每个神经元都与其前一层和后一层的所有神经元相连。全连接网络的主要作用是将前面的特征层提取到的信息进行组合和整合,以进行最终的分类或回归任务。
以手写数字识别(MNIST)为例,让我们简单解释一下全连接网络的作用。假设我们有一个输入层,其中每个神经元表示图像的一个像素值。我们的任务是识别图像中的数字(0-9)。为了完成这个任务,我们可以使用全连接网络。
在这个全连接网络中,输入层与下一层(隐藏层)中的每个神经元都相互连接。隐藏层的神经元将通过学习输入层的加权组合来捕捉输入图像的某些局部特征。而这些局部特征随着网络层数的增加,将逐渐变得更加抽象和高级。
最后一层是输出层,它也是一个全连接层。在这个例子中,输出层有10个神经元,每个神经元对应一个数字(0-9)。输出层的神经元将根据前面各层提取到的特征信息,为每个数字分配一个概率值。最终,具有最高概率值的神经元对应的数字就是网络识别的结果。
总之,全连接网络在深度学习中的主要作用是将前面各层提取到的特征信息进行整合和组合,最终完成分类或回归任务。
可以通过Self-attention和FC层不断叠加的方式,来处理信息。Self-attention处理整个seq的信息,FC专注处理某个位置的信息。 他就是Transformer的最核心的部分,也就是变形金刚的火种源。
自注意力模型的数学原理
数学原理比较枯燥,我觉得直接记录结论就好了,Self-acctention在计算每个输出矩阵O时候,是可以转化成输入矩阵I进行了大量的矩阵运算来完成的。而这个大量矩形乘法的计算恰好是GPU的长项,遥想当年研究生阶段就是研究的NVIDIA基于CUDA编程框架的并行计算研究,当然知识早就还给我的导师了。所以这也就解释了为什么研究AI人工智能会这么严重依赖GPU的资源,本质上就是将研究的问题转化为大量的线形代数的矩阵乘法的问题,当矩阵的边宽越来越大,就需要足够的存储和算力才能解决的问题。
在自注意力(Self-Attention)模型中,Q、K、V分别代表查询(Query)、键(Key)和值(Value)。这些概念源于信息检索领域,并在自注意力模型中被用于捕捉输入序列中不同位置间的相关性。
- 查询(Query,Q):查询用于表示当前位置的元素,即我们试图获取关于该元素的上下文信息。在自注意力计算中,每个输入元素都会有一个对应的查询。
- 键(Key,K):键用于表示其他位置的元素,用于和查询进行匹配。在自注意力计算中,每个输入元素都会有一个对应的键。
- 值(Value,V):值用于表示其他位置的元素的实际信息。在自注意力计算中,每个输入元素都会有一个对应的值。
自注意力机制通过计算查询(Query)与所有键(Key)之间的相关性(通常是通过点积或其他相似度度量计算),然后根据这些相关性对应的值(Value)进行加权求和,从而生成当前位置元素的上下文表示。这个过程会对输入序列中的所有元素进行计算,最终生成一个新的序列,其中每个元素都包含了来自输入序列的全局上下文信息。
那么下面我们来看看具体公式是如何推导的:
如上图,a1..a4是输入的向量集合,b1…b4是输出,那么b1其实是考虑了a1,a2,a3,a4从中拿了一些信息才得出来的值。同理b2到b4。
怎么计算b1呢,首先我们需要先找出这个序列中a1和其他向量a2-a4的向量相关性有多大,需要用个数值来表示,我们用α来表示。
而如何计算这个相关性数值α呢?学术界有很多种方式,上图介绍了两种一种是左边的Dot-product算法,一种是右边的Additive算法。其中Dot-product算法(也是Transformer模型作者使用的方式)如下,将两个输入向量分别乘以Wq和Wk两个矩阵,得到q,k两个向量,然后两个向量相乘,最终得到α值。
最重点的公式来了。我们用α12来表示a1和a2两个向量的关联性值,取名Attention score(注意力分数)。
q1就是Wq矩阵乘以a1,k2就是Wk矩阵乘以a2,那么α12 = q1 * k2 ,同理α13 = q1 * k3 , α14 = q1 * k4 , 并且 a1也要和a1自己计算相关性 α11
计算出来对应的α11,α12, α13, α14之后通过Soft-max层获得对应的α’ 11,α’ 12, α’ 13, α’ 14,即这些值加起来等于1,本质上就是计算相关性权重,权重越大就会从该向量中抽取越多的信息。
计算出来α’ 11,α’ 12, α’ 13, α’ 14,我们就可以通过加权的方式抽取对应v的信息了。v是通过Wv乘以α获得,分别使用v1…v4表示。b1就是按照加权的方式抽取出了所有相关v的信息,这就是注意力机制,抽取和自己相关或者感兴趣的信息,如果不相关则就不会抽取信息。
上图就是使用矩阵运算的方式来计算self-attention。每个向量a都会产出q,k,v三个向量,你可以把a1..a4拼接起来当做一个输入矩阵I。q1..q4拼接起来就是个矩阵Q,同理K,V。所以总结下来就是输出是一个矩阵I,通过乘以三个不同的矩阵Wq,Wk,Wv获得了对应的矩阵Q,K,V
接着a1和其他a2…a4的相关性attention score的计算就是K矩阵和q1向量的相乘。
a2和a1,a3,a4的相关性计算就是K矩阵和q2向量的相乘
a3和a1,a2,a3的相关性计算就是K矩阵和q3向量的相乘
a4和a1,a2,a3的相关性计算就是K矩阵和q4向量的相乘
然后再把q1…q4排列成矩阵Q
既可以归结为K转置矩阵和Q矩阵的相乘操作获得A矩阵,然后再通过Softmax获得A’矩阵
接下来就是计算b,即将V矩阵乘以A’矩阵,获得O,就完成了整个self-attention的操作了。
上图就是简化抽象为一连串的矩阵乘法的公式。其中Wq,Wk,Wv就是需要机器学习找出的参数。
多头自注意力(Multi-Head Attention)
Self-Attention有个进阶的版本,Multi-head Self-attention 多头注意力机制。 其实就是将原有的Wq,分裂成多个Wq1,Wq2…计算的方式还是和独立的Self-attention一致。
Self-Attention少了位置的信息,需要通过上面的Position Encoding的方式来补充。即为每一个位置设定一个不同的向量,叫做ei来表示。然后将ei加到输入的ai上就结束了。图上右边,每一个列就代表一个ei。
上图罗列了几种Position Encoding的算法,有待深入学习
引用
Attention Is All You Need
跟李沐学AI – Transformer论文逐段精读【论文精读】
【機器學習2021】自注意力機制 (Self-attention) (上)
speech.ee.ntu.edu.tw/~hylee/ml/m…
【機器學習2021】自注意力機制 (Self-attention) (下)