学习笔记

A sequence makes NN powerful(填坑中)

对Sequence的处理相对于单纯的图像分类来说,不仅包含频域信息,还额外包含了时域信息,对我来说Sequence是以前没有接触过的,因此最近对这块的知识进行了集中学习,写这篇博客的目的就是为了把最近自己学习的知识进行整理。

处理Sequence的方法我最近学习的主要有两种:循环神经网络,Transformer。本文主要依据这两种网络类型进行整理。

对Sequence数据的理解

首先谈一下自己对于Sequence数据的、理解,Sequence数据在时间或时间段上具有连续性,而且t时刻的数据对t+1时刻具有影响,举几个简单的例子:

例子错误回答正确回答
李华今天早上吃了___好几个太阳一些可以吃的东西
某公司股票开盘价格为100,经过3秒后价格为___-1000符合股票规则和常理的东西
一个视频中的人把手伸向了眼前的杯子,接下来他___了杯子起飞符合逻辑的词语
时序例子

从上面的例子可以看出Sequence数据的一个特点,已经出现在当前Sequence中的元素会对后续即将出现的元素具有一定的影响(约束)。
例子1中的“我今天早上吃了___”,这里的Sequence的本体为一个句子,已经出现的数据为“李华”、“今天”、“早上”、“吃了”、“???”,因此后面出现的必然要属于食物集合。
例子2中的“某公司股票开盘价格为100,经过3秒后价格为___”,这里的Sequence的本体为一个股票的时序序列,已经出现的数据为“{开盘价: 100}”,“{3秒后: ???}”,因此后面出现的必然是一个符合股票规则的股价。
例子3中的“一个视频中的人把手伸向了眼前的杯子,接下来他___了杯子”,这里的Sequence的本体为一个图像序列,已经出现的连续序列为:一个人把手伸向了杯子(由几十或几百帧图像组成),因此后面在不出现剪辑的情况下应该是这个人的手对杯子做了某件事情。

从上述例子也可以看出Sequence数据类型的多样,除此之外Sequence数据还可能是一段语音,一张图片(将Transformer运用到图像上)等。
在对Sequence数据进行处理时,都是区分了基本的单位,根据基本单位的顺序进行处理,例子1中的词汇,例子2中的level-1(三秒行情,指三秒钟刷新一次的股票行情)股价,例子3中的视频帧。因此不管是使用RNN还是Transformer都需要确定需要处理的Sequence的基本单位。

循环神经网络(Recurrent Neural Network)

概述

从上文中对Sequence数据的理解中可以得知,Sequence数据需要依赖当前时刻和过去t时刻的信息来对t+1时刻的可能性进行预测。因此如果想要对Sequence数据进行预测,那么只需要在t时刻的神经元接受来自1至t时刻的全部信息进行决策即可。因此网络结构如下:

循环神经网络整体结构图
循环神经网络局部结构图

上面整体结构图中的Hnm为RNN的隐层,可以看出RNN隐层的每一个神经元都接受上一时刻对应神经元的信息,并且在每接收到一个时刻的输入Xt就会输出基于当前时间序列的预测Ot,循环神经网络的局部结构图也可以说明这一点。每一个进入RNN的输入都对应一个输出。

Transformer

RNN的问题

根据前面一小节的介绍可以看出:RNN网络结构对当前时刻t之前的t-1,t-2的中间数据和结果都有要求,因此RNN网络在计算时必须先计算t-1时刻的结果,才能计算t时刻的结果,这就导致了模型的计算不能被拆分成更小的粒度并行。并且当一个序列很长时,序列开头所包含的信息很难传递到序列的尾部(反向传播时由于序列拉长导致梯度回传可能会消失或者爆炸),即使出现了LSTM这样的改进,这种问题依然存在。

Transformer引入了positional encoding取消了RNN网络中的循环部分,使得网络可以被拆分成更小的粒度并行计算。并且因为循环结构的消失和self-attention模块的引入,使得网络可以直接获取整个sequence的信息,同时采用残差结构,基本上解决了RNN网络在梯度回传时候可能产生的梯度消息和梯度爆炸的情况。

概述

Transformer是近年来新兴的网络结构,它的核心模块是self-attention。Transformer对于Sequence数据采用了和循环神经网络不一样的理解方式,通过positional encoding对sequence中元素出现的先后顺序进行编码。Transformer整体结构分为encoder和decoder两大部分,sequence数据经过encoder编码为中间表示层数据,后经decoder解码将中间表示层数据还原为另一个sequence,从而实现seq2seq。Transformer也可以只使用encoder部分,用来对sequence数据进行分类或其他目的。

Embedding

在开始介绍Transformer的核心模块self-attention之前,首先需要来看一下embedding。
首先思考一个问题:现在有一个中文句子,你想要将中文句子送入神经网络进行训练,应当如何把中文句子变成神经网络可以接受的输入方式?

说到底,神经网络说到底无非是一个函数,函数自然不可能接受中文作为输出,只要想办法把中文变成数字就可以了。基于这个思路很直接的会想到一种方式:做word-index mapping,给每个词分配一个编号制作成一个编号表,例如:我今天早上吃了一块炸鸡,可以被编码成下面的word-index map:

编号
0
今天1
早上2
3
4
一块5
炸鸡6
word-index map

那么这一句话就可以被表示成[0, 1, 2, 3, 4, 5, 6]的向量,就可以被送到神经网络进行计算。这算一种广义上的embedding,但不是本小节希望讲述的embedding。回头来看word-index map存在什么问题:
首先,每个词被用整形数字编码,一句话似乎看不出来问题,假设我们有一个100000句话组成的训练数据,每个句子中含有两个不和其他剩余句子重复的单词,那么word-index map中就会存在200000个word-index对,假设存在这样一个句子[0, 6, 4, 7, 11, 199991, 324],当这样的一个含有极端值的输入数据进入网络后会造成网络收敛困难(有可能存在梯度爆炸或者梯度消失的问题)。
其次,假设index 1876为柯基(一个狗的品种),index 99821为哈士奇(一个狗的品种),采用word-index编码方式根本无法发现index 1876和index 99821之间的关系,也很难通过网络学习建立起数字1876和99821之间的关系,会导致标签之间相对独立。

有经验的玩家可能会立马想到另一种给句子编码的方式:onehot
假设分类任务,需要预测的样本有5类,则属于1类的数据的标签为:[0, 1, 0, 0, 0]。如果使用onehot label来对句子进行标记,可以杜绝word-index中的第一个问题,句子的数字表示中不会再含有极端值。但是会引入一个新的问题,onehot label的表示过于稀疏,依旧以100000句话组成的训练数据为例,200000个词使用onehot编码后效果类似于[0, 1, 0, 0, 0, …, 0],一个长度为200000的向量中只有一个元素是0,而一个句子中假设有8个词,那么最后输入到神经网络的矩阵维度为:[8, 200000],而如此庞大的矩阵中只有8个位置含有有效信息,会给神经网络带来过多的无用信息,从而影响训练。
onehot label也并没有解决word-index中不同编号之间关系的问题,因此这种embedding也不是本小节希望讲述的embedding。

在Transformer中使用的embedding是一种类似于Self-Supervised Learning一样的存在。通过上面介绍的两种方法

Self-attention

作为Transformer的核心模块,self-attention这个名字看起来就让人一头雾水,但终究名字只是纸老虎。先来看一个例子:

飞机离马路越来越近,马路上的车吓得纷纷避让,尽管驾驶员做出了很多努力,但最后还是重重的砸在了地面

例子1

针对上述例子,假设我们要机器对该句进行理解,然后对机器提问它指的是谁?这对人来说是一个简单的问题,但对机器却是个比较难的问题。而self-attention则允许网络在处理单个元素(词或字)的时候结合整个sequence(句子)的其他元素(词或字)对当前元素(词或字)进行学习,因为self-attention认为单同一个sequence之间的数据存在某种关联,借以学习这种关联来对sequence进行encoding或学习。例子中的它的潜在指代对象为:飞机、马路、马路上的车,而self-attention结合整个句子进行学习,最后会确定它与飞机关联。

那来看一下self-attention具体的原理和计算是什么,self-attention的核心部分为三个矩阵(Q K V),Q K V三个矩阵的思想来源于Memory Networks(一个问答网络-QA),Q:Queries,K:Keys,V:Values。在self-attention中

—填坑位—

发表评论

您的电子邮箱地址不会被公开。