对于一堆vector,我们称其为一个Sequence,由多个vector组成。
事实上,我们有这样的任务,输入是一个不知长度的Sequence,这个任务就是文本、语音、图相关的任务。
文本任务:
对于文本任务,因为对于每一个单词我们会采用 One-hot Encoding 或者 Word Embedding 的方式对文本进行编码,这个时候一段文本就是一个 vectors 的 Sequence,而这个Sequence的长度是取决于文本的长度。
语音任务:
对于一个语音任务,对于每个小的时间段的语音信息,我们会将其编码为一个frame,这个frame也是一个vector,因此,整段语音也会作为一个vector的Sequence作为输入,这个sequence的长度取决于语音的长度。
图任务:
对于图任务,这里以人类的社交图为例子,每个点都是具体的人,而通过编码这个人的个人信息(profile),可以获得一个vector,而整幅图就是一个vector的集合,也就是一个Sequence,这个Sequence的长度则取决于这个图中人的数量。
因此,综上所述,我们直到在机器学习领域中,是存在非常多对于输入是一个不确定长度的、由多个vector组成的 Sequence的任务的,比如文本任务、语音任务、与图有关的任务。
接下来,我们需要讨论的是:关于这些Sequence作为输入的情况,输出有哪些情况呢?
假设对于文本任务中的词性分析任务,输入是一个文本句子,我们需要将组成句子的单词划分词性:
- I — N词性
- saw — V词性
- a — DET词性
- saw — N词性
此时,每一个vector,也就是每一个单词,都有一个对应的类别(词性),我们按照输入vector的个数,输出对应个数的类别即可。
假设对于文本任务中情感分析任务,需要对整个句子的情感做出分析,比如是负面情感还是正面情感:
- positive — 整个句子是正面情感
- negative — 整个句子是负面情感
此时,有多个vector组成的sequence,也就是整个句子只有一个标签,因此不管多少个vector,只会产生一个标签。
举一个简单例子就是,在文本任务中的翻译任务,假设需要将英文翻译成中文,输出的中文句子的长度其实并不是确定的,而是根据输入的英文句子所决定的。
此时,对于一个长度的不确定的 Sequence 的输入来说,将有模型自己决定输出的Sequence的长度。
综上,对于未知长度的Sequence作为输入的机器学习任务,存在3种不同的输出情况:
接下来我们将会详细探讨:第一种情况——每个vector对应于一个标签,因此输出的Sequence的长度等于输入Sequence的长度。
从直觉上出发,词性标注任务会非常容易解决,我们只需要将每个词做分类,通过FC(Fully Connected)使用分类算法,就可以得到句子中每个词的词性,如下图所示:
但是,我们会发现存在问题,就是对于 第一个saw和第二个saw来说,它们完全是独立的分类过程,对于模型来说,它们是一模一样的,因此,模型会将它们分类为同一种词性。
这是一个非常大的错误,我们显然直到 第一个saw 是动词,第二个saw 是名词,而当我们使用最简单基于直觉的方法来完成这个句子的词性分析的时候,模型完全不能完成任务。
我们非常容易想到上图的方式,在之前模型分类无法考虑到上下文的信息,是因为我们传入FC层的信息只有当前词汇的vector,那我们只需定义一个window,FC接收的vector信息是这个window中所有词汇的vector,这样的话,模型就拥有上下文的信息以便更好的对当前词汇做出词性分析。
通过上述方法,模型确实能够考虑一定范围的上下文信息,但是如果需要获取整个Sequence的上下文信息,我们需要将window开辟到整个Sequence的长度,而整个Sequence的长度的window我们是无法提前定义,它完全取决于输入的Sequence,这又是一个值得思考的问题。
综上,我们总结一下:
对于词性标注任务,一种最简单的方式就是对每个词汇做简单的分类,将当前词汇输入FC,得到具体的分类,但是这种方式存在问题,模型无法得知上下文的信息,也就是无法得出当前词汇的准确词性分类。
我们对最简单的方式进行改善,我们定义一个window,当对某个词汇进行分类的时候,FC不仅接收关于当前词汇的vector,还会接收位于window窗口中词汇的vector,这样模型就获取到相关的上下文信息,但是这种方式页存在问题,当我们需要获取足够多的上下文信息以至于需要将window开到整个sequence的长度大小,我们事先无法定义window的大小,因为这取决于输入Sequence的大小。
接下来,我们介绍 Self-Attention 机制,它将有助于解决这些问题。
对于Selt-Attention 可以多次重复叠加使用,如下图所示:
以上就是从整体上了解了Self-Attention,接下来我们将具体了解Self-Attention的细节内容。
对于每个输入Vector,它需要获取其他Vector的信息来组成它的上下文信息,但是,对于不同的vector,可能有些vector的信息更重要,有些vector的信息不那么重要,所以,我们首先需要获得一个相关性的分数,分数越高,代表越重要,在当前Vector中上下文的权重占比也就越高,如下图所示:
那么,关于这个相关性分数如何计算呢?
一般采用的是 Dot-product 方式,当然也有其他的方式,比如下图右侧的方式,这里主要介绍 Dot-product 的方式,它也是transformer使用的方式:
直到了相关性分数的计算方法,下面来看整体的流程。
可以这样理解,每个输入的vector,可以通过与Wq,Wk的计算,获得两个vector,分别是 q 和 k。
之后,对于每个向量vector,我们不仅仅需要获得其 q 、k 向量,这两个向量仅仅是用来获取Attention Score的,我们还需要获取一个v向量:v = Wv * a,它是用于真正融合上下文信息的向量,我们需要将每个 Attention Score 和 每个向量的v 相乘,以获取最终的输出向量b,如上图所示。
综上所述,我们已经直到了Attention Layer 中的处理方式,我们这里再总结一下:
对于每个输入向量a,我们需要获得其三个向量,分别是q、k、v
- q 向量,q = Wq * a,用于计算当前vector和其他vector的Attention Score。
- k 向量,k = Wk * a,用于被其他vector计算Attention Score。
- v 向量,v = Wv * a,真正包含上下文融合所需信息的vector,它会和Attention Score相乘,输出到最后的输出向量b中。
经过以上的操作,以当前b1输出向量为例,它拥有b2、b3、b4 的上下文信息。
我们之前提到过,每个输入向量a,都需要经过乘 Wq Wk Wv 三个矩阵来获取相关的 q、k、v 向量,这里可以将它们进行矩阵运算以便简化,如上图所示。
包括 Attention Score 也可以使用类似的矩阵运算来获得,如下图所示。
经过整理,我们最终发现,需要通过机器学习自动调整的参数是 Wq 、Wk 、Wv 这三个矩阵中的参数。
Multi-head Self-Attention 主要用于处理 相关性的不同种类。
举个例子,当我们去计算某些vector之间的Attention Score的时候,可能会有 时间意义 上的相关性,可能会有 空间意义 上的相关性,这个时候,说明存在两种不同种类的相关性,我们应该得出两种Attention Score。
实现其实很简单,之前我们计算相关性,每个输入向量a 需要获得一个 q 向量 和一个 k 向量用于计算Attention Score。
这里我们需要计算两个Attention Score,每个输入向量a 需要获得两个 q 向量 和 两个 k 向量用于计算Attention Score,它们代表不同种类的相关性,并且这两个q向量是以原始的q向量所获得。
而k向量的处理过程也和q向量一样。
如下图所示:
最终,我们需要将 不同种类的Attention Score,乘上不同种类的 v 向量,最终获得多个b向量,我们需要将多个b向量汇聚成一个最终的b向量,通过乘以 Wo 矩阵的方式。
我们现在基本上已经了解 Self-Attention 的概念以及工作方式:它可以融合上下文的信息,以便模型可以参考这些上下文信息计算更精确的输出。
但是我们发现,在融合上下文信息的过程中,我们并没有提供位置信息,比如 b1 是 a1 经过 Attention Layer 的输出,它融合 b2、b3 、b4的信息,但是它并不知道b2、b3、b4的位置信息,它并不知道 b2 是离它最近的,b4 是离它最远的。
所以,我们要引出一个解决方法 Positional Encoding。
我们在输入a向量的同时附加上这个表示位置信息的positinal vector,即可以提供每个vector的位置信息,如上图所示。
总结一下:
Self-Attention 机制中可以帮助融合上下文信息,但是它忽略了位置信息,我们可以通过 Positional Encoding 的技术来传递位置信息,Positional Encoding 有非常多的实现方法,可以是人工设置,也可以是 机器自己学 出来的。
在语音领域,Self-Attention 机制也发挥了重要作用。
但是在语音领域,Truncated Self-Attention 更为常用。
因为对于语音来说,可能不需要全局的上下文信息,可能只需要周围几个的上下文信息,即 Attention 是有一个范围的。
我们可以将每个像素的位置三个通道数视为一个vector,进而使用Self-Attention机制来处理图片。
以下是将 Self-Attention 用于图像处理的一些方法
综上所述:CNN 其实是 Self-Attention 的一种特例,如下图所示
以下是不同data量来训练不同架构(Transformer or CNN)的比较图:
RNN 也可以融合上下文的相关信息,但是对于Self-Attention 来说,它的机制更为繁琐和不那么高效。
首先,单向的RNN只能考虑之前上下文信息,不能考虑全局的上下文或者之后的上下文信息。
如果采用双向的RNN,那么它确实能够达到和Self-Attention 一样的效果,可以考虑 之前、之后的上下文信息,但是它是串行的,Self-Attention是并行的,如下图
对于Graph来说,其中的每个node,我们都可以表示为一个vector,那么,当我们需要计算Attention Score即相关性分数的时候,我们可以根据Connected nodes 来简化 Attention Score 的计算,如果两个node之间存在边,说明它们是有相关性的,如果没有边,说明相关性几乎为0.
Self-Attention 主要是用来解决什么问题?
Self-Attention 的输入可以是输入层,也可以是某些 Hidden Layer 层的输出,多个 Self-Attention Layer 层次之间可以堆叠。
Self-Attention 的主要工作机制:
Self-Attention 很早之前就在一些任务中存在,但是在Transformer架构中发扬光大。
Self-Attention 在多个领域中都有应用,比如 NLP CV 等等。