以下模型由CQU 高旻老师挑选,内容由本人总结,部分内容来源网络,侵删
模型实现项目github地址:https://github.com/CQU-MinGao-NLP/NLP-learning
1 N-gram模型
- 基本思想
N-gram模型引入了马尔可夫假设,这是一种独立性假设,在这里说的是某一个词语出现的的概率只由其前面的n-1个词语所决定,这被称为n元语言模型 ,即n-gram,当n=2时,相应的语言模型就被称为是二元模型。
- 概率模型
传统语言模型(无法计算):
N-gram通用模型:
Bi-gram:
Tri-gram:
2 NNLM
2.1 FFNNLM
- 全称:Feedforward neural network model language model,前馈神经网络模语言模型
以下内容来自博客:从经典结构到改进方法,神经网络语言模型综述
- 基本思想
Bengio 等人于 2003 年提出了原始 FFNNLM 的架构。这个 FFNNLM 可以写作:
其中,H、U 和 W 是层与层之间连接的权重矩阵;d 和 b 是隐藏层和输出层的偏置。
受到 N 元语言模型的启发,FFNNLM 将前 n-1 个单词作为了预测下一个单词的上下文。
- 优点
FFNNLM 通过为每个单词学习一个分布式表征来实现在连续空间上的建模。单词表征是语言模型的副产品,它往往被用于改进其它的 NLP 任务。基于 FFNNLM,Mikolov 等人于 2013 提出了两种词表征模型:「CBOW」和「Skip-gram」。FFNNLM 通过将单词转换为低维向量克服了维数诅咒。FFNNLM 引领了 NNLM 研究的潮流。
- 缺点
(1)在训练前指定的上下文大小是有限的,这与人类可以使用大量的上下文信息进行预测的事实是严重不符的。
(2)序列中的单词是时序相关的。而 FFNNLM 没有使用时序信息进行建模。
(3)此外,全连接 NN 需要学习许多可训练的参数,即使这些参数的数量比 N 元 少,但是仍然具有很大的计算开销,十分低效。
3 Word Embedding
3.0 one-hot
以下内容来自博客:词嵌入基础及其使用
- 基本思想
one-hot,简单来说就是单词编号是多少,哪个位置就为1,其余为0。这种词表示方法的特点就是,没有保留句子中的上下文关系(任何词之间的内积为0)。
3.1 TF-IDF 与 BOW
3.1.1 TF-IDF
以下内容来自博客:TF-IDF算法原理及其使用详解
- 基本思想
TF-IDF(Term Frequency-inverse Document Frequency)是一种针对关键词的统计分析方法,用于评估一个词对一个文件集或者一个语料库的重要程度。一个词的重要程度跟它在文章中出现的次数成正比,跟它在语料库出现的次数成反比。这种计算方式能有效避免常用词对关键词的影响,提高了关键词与文章之间的相关性。
其中TF指的是某词在文章中出现的总次数,该指标通常会被归一化定义为TF=(某词在文档中出现的次数/文档的总词量),这样可以防止结果偏向过长的文档(同一个词语在长文档里通常会具有比短文档更高的词频)。IDF逆向文档频率,包含某词语的文档越少,IDF值越大,说明该词语具有很强的区分能力,IDF=log(语料库中文档总数/包含该词的文档数+1),+1的原因是避免分母为0。TF-IDF=TFxIDF,TF-IDF值越大表示该特征词对这个文本的重要性越大。
- 具体实现
可以在Sklearn中调用TF-IDFVectorizer库实现TF-IDF算法,并且可以通过stopwords参数来设置文档中的停用词(没有具体意义的词,如助词,语气词等),使得停用词不纳入计算范围,提高算法的精确性。
3.1.2 BOW
以下内容来自博客:词向量之词袋模型(BOW)详解
- 基本思想
词袋模型(Bag-of-Words model,BOW)BoW(Bag of Words)词袋模型最初被用在文本分类中,将文档表示成特征矢量。它的基本思想是假定对于一个文本,忽略其词序和语法、句法,仅仅将其看做是一些词汇的集合,而文本中的每个词汇都是独立的。简单说就是讲每篇文档都看成一个袋子(因为里面装的都是词汇,所以称为词袋,Bag of words即因此而来),然后看这个袋子里装的都是些什么词汇,将其分类。如果文档中猪、马、牛、羊、山谷、土地、拖拉机这样的词汇多些,而银行、大厦、汽车、公园这样的词汇少些,我们就倾向于判断它是一篇描绘乡村的文档,而不是描述城镇的。
- 具体实现
- 首先根据语料中出现的句子分词,然后构建词袋(每一个出现的词都加进来)。计算机不认识字,只认识数字,那在计算机中怎么表示词袋模型呢?其实很简单,给每个词一个位置索引就可以了。小孩放在第一个位置,喜欢放在第二个位置,以此类推。
- 其中key为词,value为词的索引,语料中共有9个单词, 那么每个句子我们就可以使用一个9维的向量来表示。如果句子中含有的一个词出现了一次,就让那个词的位置置为1,词出现几次就置为几,(本质是one-hot模型)
- 将两篇文本通过词袋模型变为向量模型,通过计算向量的余弦距离来计算两个文本间的相似度。
- 缺点:基本同one-hot编码的缺点,没有上下文信息和向量稀疏。
3.2 Word Embedding
- 基本思想
embedding是数学领域的有名词,是指某个对象 X 被嵌入到另外一个对象 Y 中,映射 f : X → Y ,例如有理数嵌入实数。word embedding,就是找到一个映射或者函数,生成在一个新的空间上的表达,该表达就是word representation。
Word Embedding 是NLP中一组语言模型和特征学习技术的总称,**把词汇表中的单词或者短语映射成由实数构成的向量上(映射)**。
- 具体实现
以下内容来自博客:词嵌入基础及其使用
一种表示如下图所示,在左侧一栏是维度,表格中的值是每个词在这个维度(特征)上的取值(-1,+1),越相关,绝对值越大。
3.2 Word2Vec
(1)如果是用一个词语作为输入,来预测它周围的上下文,那这个模型叫做『Skip-gram 模型』
(2)而如果是拿一个词语的上下文作为输入,来预测这个词语本身,则是 『CBOW 模型』
以下内容来自博客:Word2Vec详解
- 基本思想
word2vec是用一个一层的神经网络把one-hot形式的稀疏词向量映射称为一个n维(n一般为几百)的稠密向量的过程。为了加快模型训练速度,其中的tricks包括Hierarchical softmax,negative sampling, Huffman Tree等。
模型框架:
3.2.1 CBOW
全称:Continuous Bag of Words(连续词袋模型)
1、输入层:上下文单词的One-Hot编码词向量,V为词汇表单词个数,C为上下文单词个数。以上文那句话为例,这里C=4,所以模型的输入是(is,an,on,the)4个单词的One-Hot编码词向量。
2、初始化一个权重矩阵 ,然后用所有输入的One-Hot编码词向量左乘该矩阵,得到维数为N的向量 ,这里的N由自己根据任务需要设置。
3、将所得的向量 相加求平均作为隐藏层向量h。
4、初始化另一个权重矩阵 ,用隐藏层向量h左乘 ,再经激活函数处理得到V维的向量y,y的每一个元素代表相对应的每个单词的概率分布。
5、y中概率最大的元素所指示的单词为预测出的中间词(target word)与true label的One-Hot编码词向量做比较,误差越小越好(根据误差更新两个权重矩阵)
在训练前需要定义好损失函数(一般为交叉熵代价函数),采用梯度下降算法更新W和W’。训练完毕后,输入层的每个单词与矩阵W(左侧的权重矩阵)相乘得到的向量的就是我们想要的Distributed Representation表示的词向量,也叫做word embedding。因为One-Hot编码词向量中只有一个元素为1,其他都为0,所以第i个词向量乘以矩阵W得到的就是矩阵的第i行,所以这个矩阵也叫做look up table,有了look up table就可以免去训练过程,直接查表得到单词的词向量了。
3.2.2 Skip-gram
通过在一个大的语料库训练,得到一个从输入层到隐含层的权重模型。“apple”的上下文词是(’there’,’is’,’an’,’on’,’the’,’table’)。那么以apple的One-Hot词向量作为输入,输出则是(’there’,’is’,’an’,’on’,’the’,’table’)的One-Hot词向量。训练完成后,就得到了每个词到隐含层的每个维度的权重,就是每个词的向量(和CBOW中一样)。
- 如何训练神经网络模型
假如我们有一个句子“There is an apple on the table”。
1、首先我们选句子中间的一个词作为我们的输入词,例如我们选取“apple”作为input word;
2、有了input word以后,我们再定义一个叫做skip_window的参数,它代表着我们从当前input word的一侧(左边或右边)选取词的数量。如果我们设置skip_window=2,那么我们最终获得窗口中的词(包括input word在内)就是[‘is’,’an’,’apple’,’on’,’the’ ]。skip_window=2代表着选取左input word左侧2个词和右侧2个词进入我们的窗口,所以整个窗口大小span=2x2=4。另一个参数叫num_skips,它代表着我们从整个窗口中随机选取多少个不同的词作为我们的output word,当skip_window=2,num_skips=2时,我们将会得到两组 (input word, output word) 形式的训练数据,即 (‘apple’, ‘an’),(‘apple’, ‘on’)。
3、神经网络基于这些训练数据中每对单词出现的次数习得统计结果,并输出一个概率分布,这个概率分布代表着到我们词典中每个词有多大可能性跟input word同时出现。举个例子,如果我们向神经网络模型中输入一个单词“中国“,那么最终模型的输出概率中,像“英国”, ”俄罗斯“这种相关词的概率将远高于像”苹果“,”蝈蝈“非相关词的概率。因为”英国“,”俄罗斯“在文本中更大可能在”中国“的窗口(Skip_window)中出现。我们将通过给神经网络输入文本中成对的单词来训练它完成上面所说的概率计算。
4、通过梯度下降和反向传播更新矩阵W
5、W中的行向量即为每个单词的Word embedding表示
- skip_window和num_skips
简单来说,skip_window和num_skips用来生成标注(label)的训练数据集,可以理解为是监督学习中的标注数据。每个(input_word, output_word)表示在模型中每个input_word 所对应的 output_word应该是什么。
skip_window代表窗口大小,num_skips = 2 表示input用于产生label的次数限制,就是对于一个中心词 在window范围 随机选取num_skips个词,产生一系列(input_id, output_id) 。
在生成单词对时,会在语料库中先取出一个长度为skip_window*2+1连续单词列表,这个连续的单词列表是上面程序中的变量buffer。buffer中最中间的那个单词是Skip-Gram方法中“出现的单词”,其余skip_window*2个单词是它的“上下文”。会在skip_window*2个单词中随机选取num_skips个单词,放入的标签labels。
如skip_window=1 , num_skips=2的情况。会首先选取一个长度为3的buffer,假设它是[‘anarchism’, ‘originated’,’as’],此时originated为中心单词,剩下的两个单词为它的上下文。再在这两个单词中选择num_skips形成标签。由于num_skips=2,所以实际只能将这两个单词都选上(标签不能重复),最后生成的训练数据为originated ->anarchism和originated -> as。
3.2.3 Tricks
- Hierarchical Softmax
Hierarchical Softmax对原模型的改进主要有两点,第一点是从输入层到隐藏层的映射,没有采用原先的与矩阵W相乘然后相加求平均的方法,而是直接对所有输入的词向量求和。假设输入的词向量为(0,1,0,0)和(0,0,0,1),那么隐藏层的向量为(0,1,0,1)。
Hierarchical Softmax的第二点改进是采用哈夫曼树来替换了原先的从隐藏层到输出层的矩阵W’。哈夫曼树的叶节点个数为词汇表的单词个数V,一个叶节点代表一个单词,而从根节点到该叶节点的路径确定了这个单词最终输出的词向量。
哈夫曼树的所有内部节点就类似之前神经网络隐藏层的神经,其中,根节点的词向量对应投影后的词向量,而所有叶子节点就类似于之前神经网络softmax输出层的神经元,叶子节点的个数就是词汇表的大小。在哈夫曼树中,隐藏层到输出层的softmax映射不是一下子完成的,而是沿着哈夫曼树一步步完成的,因此这种softmax取名为”Hierarchical Softmax”。
- Negative Sampling(负采样)
比如我们有一个训练样本,中心词是w,它周围上下文共有2c个词,记为context(w)。由于这个中心词w,的确和context(w)相关,因此它是一个真实的正例。通过Negative Sampling采样,我们得到n个和w不同的中心词wi, i=1,2,..n,这样context(w)和wi就组成了n个并不真实存在的负例。利用这一个正例和n个负例,我们进行二元逻辑回归,得到负采样对应每个词wi对应的模型参数θi,和每个词的词向量。
3.3 GloVe
以下内容来自博客:GloVe详解
- 基本思想
GloVe的全称叫Global Vectors for Word Representation,它是一个基于全局词频统计(count-based & overall statistics)的词表征(word representation)工具,它可以把一个单词表达成一个由实数组成的向量,这些向量捕捉到了单词之间一些语义特性,比如相似性(similarity)、类比性(analogy)等。我们通过对向量的运算,比如欧几里得距离或者cosine相似度,可以计算出两个单词之间的语义相似性。
- 主要模型
构建词向量(Word Vector)和共现矩阵(Co-ocurrence Matrix)之间的近似关系,论文的作者提出以下的公式可以近似地表达两者之间的关系:
其中,wi^T和wj是我们最终要求解的词向量;bi和bj分别是两个词向量的bias term。
- 损失函数
这个loss function的基本形式就是最简单的mean square loss,只不过在此基础上加了一个权重函数f(Xij)。
4 Fasttext
全称:Facebook开发的一款快速文本分类器
论文链接:
以下内容来自博客:fastText原理及实践
基本思想
fastText模型也只有三层:输入层、隐含层、输出层(Hierarchical Softmax),输入都是多个经向量表示的单词,输出都是一个特定的target,隐含层都是对多个词向量的叠加平均。不同的是,CBOW的输入是目标单词的上下文,fastText的输入是多个单词及其n-gram特征,这些特征用来表示单个文档;CBOW的输入单词被onehot编码过,fastText的输入特征是被embedding过;CBOW的输出是目标词汇,fastText的输出是文档对应的类标。
值得注意的是,fastText在输入时,将单词的字符级别的n-gram向量作为额外的特征;在输出时,fastText采用了分层Softmax,大大降低了模型训练时间。
- 主要优点:fastText是一个快速文本分类算法
- fastText在保持高精度的情况下加快了训练速度和测试速度
- fastText不需要预训练好的词向量,fastText会自己训练词向量
- fastText两个重要的优化:Hierarchical Softmax、N-gram
5 textCNN
5.1 CNN
- 基本思想:
卷积神经网络主要由这几类层构成:输入层、卷积层,ReLU层、池化(Pooling)层和全连接层(全连接层和常规神经网络中的一样)。通过将这些层叠加起来,就可以构建一个完整的卷积神经网络。在实际应用中往往将卷积层与ReLU层共同称之为卷积层,所以卷积层经过卷积操作也是要经过激活函数的。具体说来,卷积层和全连接层(CONV/FC)对输入执行变换操作的时候,不仅会用到激活函数,还会用到很多参数,即神经元的权值w和偏差b;而ReLU层和池化层则是进行一个固定不变的函数操作。卷积层和全连接层中的参数会随着梯度下降被训练,这样卷积神经网络计算出的分类评分就能和训练集中的每个图像的标签吻合了。
详细解读见博客:卷积神经网络(CNN)详解
- 卷积层
- 池化层
- 全连接层(Fully Connected Layer)
连接所有的特征,将输出值送给分类器(如softmax分类器)。
- 感受野(receptive filed)
每个神经元只与输入数据的一个局部区域连接,该连接的空间大小叫做神经元的感受野(receptive field),它的尺寸是一个超参数(其实就是滤波器的空间尺寸,注意仅仅是大小相同,但是概念不一样)
- 滤波器(filter)
如果在一个深度切片中的所有权重都使用同一个权重向量,那么卷积层的前向传播在每个深度切片中可以看做是在计算神经元权重和输入数据体的卷积(这就是“卷积层”名字由来)。这也是为什么总是将这些权重集合称为滤波器(filter)(或卷积核(kernel)),因为它们和输入进行了卷积。
卷积核:二维的矩阵
滤波器:多个卷积核组成的三维矩阵,多出的一维是通道数目。
- 权值共享
卷积核内每一个元素值不同,但是同一深度切片使用相同卷积核,这就是权值共享。也就是说每一层(深度切片)使用同一个卷积核(一个滤波器有也多个卷积核,且一定与输入数据深度相同)。
- 深度depth(与通道类似)
分为输入数据的深度和输出数据的深度,输入数据深度由输入数据决定。
输出数据的深度,取决于滤波器的个数,就是有滤波器有几个,深度就是多少。
- 通道channel
可以把channels 分为三种:
- 最初输入的图片样本的 channels ,取决于图片类型,比如RGB;
- 卷积操作完成后输出的 out_channels ,取决于卷积核的数量。此时的out_channels 也会作为下一次卷积时的卷积核的 in_channels;
- 卷积核中的 in_channels ,刚刚2中已经说了,就是上一次卷积的 out_channels ,如果是第一次做卷积,就是1中样本图片的 channels
(详见博客:【CNN】理解卷积神经网络中的通道 channel)
- 特征图
卷积层之后的输出结果就是特征图。
5.2 textCNN
- 基本思想
卷积神经网络的核心思想是捕捉局部特征,对于文本来说,局部特征就是由若干单词组成的滑动窗口,类似于N-gram。卷积神经网络的优势在于能够自动地对N-gram特征进行组合和筛选,获得不同抽象层次的语义信息。
详细解读见博客:深入TextCNN(一)详述CNN及TextCNN原理
6 textRNN
6.1 RNN
- 基本思想
- RNN 的输入和输出可以是不定长且不等长的
- RNN 有多种结构,如下图:
- RNN网络和其他网络最大的不同就在于RNN能够实现某种“记忆功能”,对所处理过的信息留存有一定的记忆,具体而言就是上一个时刻的网络状态会应影响下一个时刻的网络状态。
详细解读见博客:RNN 结构详解
- 隐状态
隐状态h(hidden state)可以对序列形的数据提取特征,接着再转换为输出。
- RNN经典n-to-n结构示例
先从h1的计算开始看:
h2的计算和h1类似。要注意的是,在计算时,每一步使用的参数U、W、b都是一样的,也就是说每个步骤的参数都是共享的,这是RNN的重要特点。
最终的输出如下:
剩下的输出类似进行(使用和y1同样的参数V和c):
这就是最经典的RNN结构,它的输入是x1, x2, …..xn,输出为y1, y2, …yn,也就是说,输入和输出序列必须要是等长的。
- 缺点:容易出现梯度消失
6.2 Encoder-Decoder
Encoder-Decoder是一种 n-to-m 结构,输入、输出为不等长的序列。
- 基本思想
(1)Encoder:将 input序列 →转成→ 固定长度的向量
(2)Decoder:将 固定长度的向量 →转成→ output序列
(3)Encoder 与 Decoder 可以彼此独立使用,实际上经常一起使用
Encoder-Decoder结构先将输入数据编码成一个上下文语义向量c,语义向量c可以有多种表达方式,最简单的方法就是把Encoder的最后一个隐状态赋值给c,还可以对最后的隐状态做一个变换得到c,也可以对所有的隐状态做变换。拿到c之后,就用另一个RNN网络对其进行解码,这部分RNN网络被称为Decoder。Decoder的RNN可以与Encoder的一样,也可以不一样。
详细解读见博客:RNN 结构详解
- 具体做法
具体做法就是将c当做之前的初始状态h0输入到Decoder中:
还有一种做法是将c当做每一步的输入:
- 缺点:
编码和解码之间的唯一联系是固定长度的语义向量c,编码要把整个序列的信息压缩进一个固定长度的语义向量c,语义向量c无法完全表达整个序列的信息,先输入的内容携带的信息,会被后输入的信息稀释掉,或者被覆盖掉。
输入序列越长,这样的现象越严重,这样使得在Decoder解码时一开始就没有获得足够的输入序列信息,解码效果会打折扣。
6.3 Attention机制
- 基本思想
注意力机制(attention mechanism)是对基础Encoder-Decoder的改良。Attention机制通过在每个时间输入不同的c来解决问题,每一个c会自动去选取与当前所要输出的y最合适的上下文信息,仅Decoder部分与简单RNN不同,下图是带有Attention机制的Decoder:
详细解读见博客:RNN 结构详解
- 具体做法
具体来说,我们用aij衡量Decoder中第i阶段与Encoder中第j阶段的hj的相关性,最终Decoder中第i阶段的输入的上下文信息 ci就来自于所有 hj 对 aij 的加权和。
以机器翻译为例(将中文翻译成英文):
- 计算权重aij
aij 同样是从模型中学出的,它实际和Decoder的第i-1阶段的隐状态、Encoder第j个阶段的隐状态有关。
同样还是拿上面的机器翻译举例, a1j 的计算(此时箭头就表示对h’和 hj 同时做变换):
- 优点
(1)让生词不只是关注全局的语义向量c,增加了“注意力范围”。表示接下来输出的词要重点关注输入序列的哪些部分。根据关注的区域来产生下一个输出。
(2)不要求编码器将所有信息全输入在一个固定长度的向量中。
(3)将输入编码成一个向量的序列,解码时,每一步选择性的从序列中挑一个子集进行处理。
(4)在每一个输出时,能够充分利用输入携带的信息,每个语义向量Ci不一样,注意力焦点不一样。
- 缺点
(1)需要为每个输入输出组合分别计算attention。50个单词的输出输出序列需要计算2500个attention。
(2)attention在决定专注于某个方面之前需要遍历一遍记忆再决定下一个输出是以什么。
- 强化学习
Attention的另一种替代方法是强化学习,来预测关注点的大概位置。但强化学习不能用反向传播算法端到端的训练。
强化学习是一种试错方法,其目标是让软件智能体在特定环境中能够采取回报最大化的行为。强化学习在马尔可夫决策过程环境中主要使用的技术是动态规划(Dynamic Programming)。流行的强化学习方法包括自适应动态规划(ADP)、时间差分(TD)学习、状态-动作-回报-状态-动作(SARSA)算法、Q 学习、深度强化学习(DQN);其应用包括下棋类游戏、机器人控制和工作调度等。
6.4 LSTM
以下内容来自博客:人人都能看懂的LSTM
- 基本思想
长短期记忆(Long short-term memory, LSTM)是一种特殊的RNN,主要是为了解决长序列训练过程中的梯度消失和梯度爆炸问题。简单来说,就是相比普通的RNN,LSTM能够在更长的序列中有更好的表现。
LSTM结构(图右)和普通RNN的主要输入输出区别如下所示。
相比RNN只有一个传递状态 ,LSTM有两个传输状态,一个 (cell state),和一个 (hidden state)。(Tips:RNN中的 对于LSTM中的 )
其中对于传递下去的 改变得很慢,通常输出的 是上一个状态传过来的 加上一些数值。
而 则在不同节点下往往会有很大的区别。
- 具体做法
是Hadamard Product,也就是操作矩阵中对应的元素相乘,因此要求两个相乘矩阵是同型的。 则代表进行矩阵加法。
LSTM内部主要有三个阶段:
1.忘记阶段。这个阶段主要是对上一个节点传进来的输入进行选择性忘记。简单来说就是会 “忘记不重要的,记住重要的”。
具体来说是通过计算得到的 (f表示forget)来作为忘记门控,来控制上一个状态的 哪些需要留哪些需要忘。
2.选择记忆阶段。这个阶段将这个阶段的输入有选择性地进行“记忆”。主要是会对输入 进行选择记忆。哪些重要则着重记录下来,哪些不重要,则少记一些。当前的输入内容由前面计算得到的 表示。而选择的门控信号则是由 (i代表input)来进行控制。
将上面两步得到的结果相加,即可得到传输给下一个状态的 。也就是上图中的第一个公式。
3.输出阶段。这个阶段将决定哪些将会被当成当前状态的输出。主要是通过 来进行控制的。并且还对上一阶段得到的 进行了放缩(通过一个tanh激活函数进行变化)。
- LSTM的四个状态
首先使用LSTM的当前输入 和上一个状态传递下来的 拼接训练得到四个状态。
其中, , , 是由拼接向量乘以权重矩阵之后,再通过一个 激活函数转换成0到1之间的数值,来作为一种门控状态。而 则是将结果通过一个 激活函数将转换成-1到1之间的值(这里使用 是因为这里是将其做为输入数据,而不是门控信号)。
6.5 textRNN
以下内容来自博客:TextRNN
- 基本思想
自然语言处理中更常用的是循环神经网络(RNN, Recurrent Neural Network),能够更好的表达上下文信息。具体在文本分类任务中,Bi-directional RNN(实际使用的是双向LSTM)从某种意义上可以理解为可以捕获变长且双向的的 “n-gram” 信息。
- Bi-LSTM
双向LSTM算是在自然语言处理领域非常一个标配网络了,在序列标注/命名体识别/seq2seq模型等很多场景都有应用,下图是Bi-LSTM用于分类问题的网络结构原理示意图,黄色的节点分别是前向和后向RNN的输出,示例中的是利用最后一个词的结果直接接全连接层softmax输出了。
6.6 TextRNN + Attention
- 基本思想:用Attention Layer代替全连接层
Att-BiLSTM包含5部分:
输入层:输入句子到模型。
嵌入层:将每个词映射到低维向量。
LSTM层:使用BLSTM得到高层特征。
注意力层:通过与权重向量加权求和,将词级别的特征合并到句子级别的特征。
输出层:将句子层级的特征用于关系分类。
整个网络结构如下图:
- Bi-LSTM
使用BiLSTM,句子中第 个词的输出为,即对前向和后向的Hidden State进行拼接:
- Attention层
为LSTM层的输出向量,T是句子长度。 , 是LSTM层的输出维度。 的维度是 , 的维度是T, 的维度是 .
然后用于最后分类的特征为
- 输出层
最后将句子的特征 接入softmax进行分类。
然后损失函数是使用交叉熵损失,并且加入了L2正则化。
- 正则化
7 seq2seq
seq2seq 是一个Encoder–Decoder 结构的网络。
8 Transformer
8.1 Transformer
以下内容来自博客:详解Transformer (Attention Is All You Need)
- 基本思想
Transformer中抛弃了传统的CNN和RNN,整个网络结构完全是由Attention机制组成。更准确地讲,Transformer由且仅由self-Attenion和Feed Forward Neural Network组成。
- Attention计算方法
Attention的计算方法,整个过程可以分成7步:
- 将输入单词转化成嵌入向量;
- 根据嵌入向量得到 , , 三个向量;
- 为每个向量计算一个score: ;
- 为了梯度的稳定,Transformer使用了score归一化,即除以 ;
- 对score施以softmax激活函数;
- softmax点乘Value值 ,得到加权的每个输入向量的评分 ;
- 相加之后得到最终的输出结果 : 。
实际计算过程中是采用基于矩阵的计算方式,那么论文中的 , , 的计算方式如图:
总结为如图所示的矩阵形式:
在self-attention需要强调的最后一点是其采用了残差网络 中的short-cut结构,目的当然是解决深度学习中的退化问题,得到的最终结果如图13。
- Multi-head Attention
Multi-Head Attention相当于 个不同的self-attention的集成(ensemble),在这里我们以 举例说明。Multi-Head Attention的输出分成3步:
- 将数据 分别输入到图13所示的8个self-attention中,得到8个加权后的特征矩阵 。
- 将8个 按列拼成一个大的特征矩阵;
- 特征矩阵经过一层全连接后得到输出 。
整个过程如图14所示:
- Encoder-Decoder Attention
在解码器中,Transformer block比编码器中多了个encoder-cecoder attention。在encoder-decoder attention中, 来自于解码器的上一个输出, 和 则来自于与编码器的输出。其计算方式完全和Attention的计算过程相同。
在机器翻译中,解码过程是一个顺序操作的过程,也就是当解码第 个特征向量时,我们只能看到第 及其之前的解码结果,论文中把这种情况下的multi-head attention叫做masked multi-head attention。
- 位置编码
论文中在编码词向量时引入了位置编码(Position Embedding)的特征。具体地说,位置编码会在词向量中加入了单词的位置信息,这样Transformer就能区分不同位置的单词了。
编码位置常见的模式有:a. 根据数据学习;b. 自己设计编码规则。
论文给出的编码公式如下:
作者这么设计的原因是考虑到在NLP任务中,除了单词的绝对位置,单词的相对位置也非常重要。
- 优点
(1)虽然Transformer最终也没有逃脱传统学习的套路,Transformer也只是一个全连接(或者是一维卷积)加Attention的结合体。但是其设计已经足够有创新,因为其抛弃了在NLP中最根本的RNN或者CNN并且取得了非常不错的效果,算法的设计非常精彩。
(2)Transformer的设计最大的带来性能提升的关键是将任意两个单词的距离是1,这对解决NLP中棘手的长期依赖问题是非常有效的。
(3)Transformer不仅仅可以应用在NLP的机器翻译领域,甚至可以不局限于NLP领域,是非常有科研潜力的一个方向。
(4)算法的并行性非常好,符合目前的硬件(主要指GPU)环境。
- 缺点
(1)粗暴的抛弃RNN和CNN虽然非常炫技,但是它也使模型丧失了捕捉局部特征的能力,RNN + CNN + Transformer的结合可能会带来更好的效果。(2)Transformer失去的位置信息其实在NLP中非常重要,而论文中在特征向量中加入Position Embedding也只是一个权宜之计,并没有改变Transformer结构上的固有缺陷。
8.2 Informer
基本思想:基于Transformer模型的三处改进
(1)ProbSparse Self-Attention
在典型的Self-Attention机制中,少数点积对主要注意有贡献,其他点积对可以忽略,所以引入Query Sparsity评估。
并且使用最大值代替复杂的对数计算,既解决了计算精度问题,也降低了计算复杂度。
(2)Self-attention Distilling
作为ProbSparse Self-attention的自然结果,encoder的特征映射会带来V值的冗余组合,利用distilling对具有支配特征的优势特征进行特权化,使它们的输出维度对齐。
(3)Generating long sequential outputs
生成式长序列输出,从长序列中采样一个小部分token,作为预测序列之前的初始token,然后将初始token+初始化为0的预测序列拼接,作为Decoder的输入序列,然后通过前向过程预测所有输出,避免耗时的动态decoding。
9 ELMO
基本思想
以下内容来自博客:ELMo详解
之前2013年的word2vec及2014年的GloVe的工作中,每个词对应一个vector,对于多义词无能为力。ELMo的工作对于此,提出了一个较好的解决方案。不同于以往的一个词对应一个向量,是固定的。在ELMo世界里,预训练好的模型不再只是向量对应关系,而是一个训练好的模型。使用时,将一句话或一段话输入模型,模型会根据上下文来推断每个词对应的词向量。这样做之后明显的好处之一就是对于多义词,可以结合前后语境对多义词进行理解。比如appele,可以根据前后文语境理解为公司或水果。
ELMO 本身是个根据当前上下文对 Word Embedding 动态调整的思路。
- 算法模型
ELMo用到上文提到的双向的language model,给定N个tokens (t1, t2,…,tN), language model通过给定前面的k-1个位置的token序列计算第k个token的出现的概率:
后向的计算方法与前向相似:
biLM训练过程中的目标就是最大化:
ELMo对于每个token , 通过一个L层的biLM计算出2L+1个表示:
其中 是对token进行直接编码的结果(这里是字符通过CNN编码), 代表 是每个biLSTM层输出的结果。在实验中还发现不同层的biLM的输出的token表示对于不同的任务效果不同.最上面一层的输出 是用softmax来预测下面一个单词 。
应用中将ELMo中所有层的输出R压缩为单个向量, ,最简单的压缩方法是取最上层的结果做为token的表示: ,更通用的做法是通过一些参数来联合所有层的信息得到最终的ELMo向量:
其中 是一个softmax出来的结果, γ是一个任务相关的scale参数,我试了平均每个层的信息和学出来 发现学习出来的效果会好很多。 文中提到γ在不同任务中取不同的值效果会有较大的差异, 需要注意, 在SQuAD中设置为0.01取得的效果要好于设置为1时。
文章中提到的Pre-trained的language model是用了两层的biLM, 对token进行上下文无关的编码是通过CNN对字符级进行编码, 然后将三层的输出scale到1024维, 最后对每个token输出3个1024维的向量表示。 这里之所以将3层的输出都作为token的embedding表示是因为实验已经证实不同层的LM输出的信息对于不同的任务作用是不同的, 也就是所不同层的输出捕捉到的token的信息是不相同的。
- 具体实现
以下内容来自博客:NAACL2018:高级词向量(ELMo)详解(超详细) 经典
ELMO 采用了典型的两阶段过程,第一个阶段是利用语言模型进行预训练;第二个阶段是在做下游任务时,从预训练网络中提取对应单词的网络各层的 Word Embedding 作为新特征补充到下游任务中。
上图展示的是其预训练过程,它的网络结构采用了双层双向 LSTM,目前语言模型训练的任务目标是根据单词 的上下文去正确预测单词 , 之前的单词序列 Context-before 称为上文,之后的单词序列 Context-after 称为下文。图中左端的前向双层LSTM代表正方向编码器,输入的是从左到右顺序的除了预测单词外 的上文 Context-before;右端的逆向双层 LSTM 代表反方向编码器,输入的是从右到左的逆序的句子下文 Context-after;每个编码器的深度都是两层 LSTM 叠加。这个网络结构其实在 NLP 中是很常用的。
使用这个网络结构利用大量语料做语言模型任务就能预先训练好这个网络,如果训练好这个网络后,输入一个新句子Snew,句子中每个单词都能得到对应的三个Embedding:最底层是单词的 Word Embedding,往上走是第一层双向LSTM中对应单词位置的 Embedding,这层编码单词的句法信息更多一些;再往上走是第二层LSTM中对应单词位置的 Embedding,这层编码单词的语义信息更多一些。也就是说,ELMO 的预训练过程不仅仅学会单词的 Word Embedding,还学会了一个双层双向的LSTM网络结构,而这两者后面都有用。
上面介绍的是 ELMO 的第一阶段:预训练阶段。那么预训练好网络结构后,如何给下游任务使用呢?上图展示了下游任务的使用过程,比如我们的下游任务仍然是 QA 问题,此时对于问句 X,我们可以先将句子 X 作为预训练好的 ELMO 网络的输入,这样句子 X 中每个单词在 ELMO 网络中都能获得对应的三个 Embedding,之后给予这三个 Embedding 中的每一个 Embedding 一个权重a,这个权重可以学习得来,根据各自权重累加求和,将三个 Embedding 整合成一个。
然后将整合后的这个 Embedding 作为 X 句在自己任务的那个网络结构中对应单词的输入,以此作为补充的新特征给下游任务使用。对于上图所示下游任务 QA 中的回答句子 Y 来说也是如此处理。
因为 ELMO给下游提供的是每个单词的特征形式,所以这一类预训练的方法被称为“Feature-based Pre-Training”。
- 缺点(事后看)
- LSTM抽取特征能力远弱于Transformer
- 拼接方式双向融合特征,融合能力偏弱
- ELMo到XLnet模型
10 Bert
- 全称:Bidirectional Encoder Representations from Transformers
- 论文链接:BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding
- 相关文档:Bert
以下内容来自博客:【NLP】Google BERT模型原理详解、BERT模型详解
- 基本思想
模型的主要创新点都在pre-train方法上,即用了Masked LM和Next Sentence Prediction两种方法分别捕捉词语和句子级别的representation。
由于模型的构成元素Transformer已经解析过,就不多说了,BERT模型的结构如下图最左:
对比OpenAI GPT(Generative pre-trained transformer),BERT是双向的Transformer block连接;就像单向RNN和双向RNN的区别,直觉上来讲效果会好一些。
对比ELMo,虽然都是“双向”,但目标函数其实是不同的。ELMo是分别以 和 作为目标函数,独立训练处两个representation然后拼接,而BERT则是以 作为目标函数训练LM。
- Embedding
其中:
- Token Embeddings是词向量,第一个单词是CLS标志,可以用于之后的分类任务
- Segment Embeddings用来区别两种句子,因为预训练不光做LM还要做以两个句子为输入的分类任务
- Position Embeddings和之前文章中的Transformer不一样,不是三角函数而是学习出来的
- Pre-training Task 1: Masked LM
在将单词序列输入给 BERT 之前,每个序列中有 15% 的单词被 [MASK] token 替换。然后模型尝试基于序列中其他未被 mask 的单词的上下文来预测被mask的原单词。最终的损失函数只计算被mask掉那个token。
如果一直用标记[MASK]代替(在实际预测时是碰不到这个标记的)会影响模型,具体的MASK是有trick的:
- 随机mask的时候10%的单词会被替代成其他单词,10%的单词不替换,剩下80%才被替换为[MASK]。作者没有说明什么原因,应该是基于实验效果?
- 要注意的是Masked LM预训练阶段模型是不知道真正被mask的是哪个词,所以模型每个词都要关注。
- 训练技巧:序列长度太大(512)会影响训练速度,所以90%的steps都用seq_len=128训练,余下的10%步数训练512长度的输入。
- 具体实现注意:
- i) 在encoder的输出上添加一个分类层。
- ii) 用嵌入矩阵乘以输出向量,将其转换为词汇的维度。
- iii) 用softmax计算词汇表中每个单词的概率。
- BERT的损失函数只考虑了mask的预测值,忽略了没有掩蔽的字的预测。这样的话,模型要比单向模型收敛得慢,不过结果的情境意识增加了。
- Pre-training Task 2:Next Sentence Prediction
LM存在的问题是,缺少句子之间的关系,这对许多NLP任务很重要。为预训练句子关系模型,bert使用一个非常简单的二分类任务:将两个句子A和B链接起来,预测原始文本中句子B是否排在句子A之后。
具体训练的时候,50%的输入对在原始文档中是前后关系,另外50%中是从语料库中随机组成的,并且是与第一句断开的。
为了帮助模型区分开训练中的两个句子,输入在进入模型之前要按以下方式进行处理:在第一个句子的开头插入 [CLS] 标记,在每个句子的末尾插入 [SEP] 标记。
将表示句子 A 或句子 B 的一个句子 embedding 添加到每个 token 上,即前文说的Segment Embeddings。
给每个token添加一个位置embedding,来表示它在序列中的位置。
为了预测第二个句子是否是第一个句子的后续句子,用下面几个步骤来预测:
- 整个输入序列输入给 Transformer 模型用一个简单的分类层将[CLS]标记的输出变换为 2×1 形状的向量。
- 用 softmax 计算 IsNextSequence 的概率。
在训练BERT模型时,Masked LM和 Next Sentence Prediction 是一起训练的,目标就是要最小化两种策略的组合损失函数。
注意:作者特意说了语料的选取很关键,要选用document-level的而不是sentence-level的,这样可以具备抽象连续长序列特征的能力。
- 精调(Fine-tunning)
对于不同的下游任务,我们仅需要对BERT不同位置的输出进行处理即可,或者直接将BERT不同位置的输出直接输入到下游模型当中。具体的如下:
- 对于情感分析等单句分类任务,可以直接输入单个句子(不需要[SEP]分隔双句),将[CLS]的输出直接输入到分类器进行分类
- 对于句子对任务(句子关系判断任务),需要用[SEP]分隔两个句子输入到模型中,然后同样仅须将[CLS]的输出送到分类器进行分类
- 对于问答任务,将问题与答案拼接输入到BERT模型中,然后将答案位置的输出向量进行二分类并在句子方向上进行softmax(只需预测开始和结束位置即可)
- 对于命名实体识别任务,对每个位置的输出进行分类即可,如果将每个位置的输出作为特征输入到CRF将取得更好的效果。
- 对于常规分类任务中,需要在 Transformer 的输出之上加一个分类层。
- 优点:效果好,横扫了11项NLP任务。bert之后基本全面拥抱transformer。微调下游任务的时候,即使数据集非常小(比如小于5000个标注样本),模型性能也有不错的提升。
- 缺点:
作者在文中主要提到的就是MLM预训练时的mask问题:
- [MASK]标记在实际预测中不会出现,训练时用过多[MASK]影响模型表现
- 每个batch只有15%的token被预测,所以BERT收敛得比left-to-right模型(单向模型)要慢(它们会预测每个token)
- 特殊标志
BERT 的输入可以包含一个句子对 (句子 A 和句子 B),也可以是单个句子。此外还增加了一些有特殊作用的标志位:
- [CLS] 标志放在第一个句子的首位,经过 BERT 得到的的表征向量 C 可以用于后续的分类任务。
- [SEP] 标志用于分开两个输入句子,例如输入句子 A 和 B,要在句子 A,B 后面增加 [SEP] 标志。
- [UNK]标志指的是未知字符
- [MASK] 标志用于遮盖句子中的一些单词,将单词用 [MASK] 遮盖之后,再利用 BERT 输出的 [MASK] 向量预测单词是什么。
11 XLNet
全称:XLNet: Generalized Autoregressive Pretraining for Language Understanding
相关文档:XLNet
12 GPT(1,2, 3)
全称:Generative Pre-training Transformer
论文链接:
相关文档: