自然语言炼丹之路(三之七)筑基丹seq2seq&deep_nmt

Sequence to Sequence Learning with Nerual Networks 使用神经网络学习序列到序列的任务

例如机器翻译、摘要生成、机器对话、阅读理解等都是输入一个序列(句子、短语等),输出一个序列(句子、短语等)的任务,也可以说是序列生成任务或者Encoder——Decoder任务。本篇主要是在机器翻译上的工作。其实现在的谷歌翻译就是seq2seq加attention。
这篇文章是谷歌的ilya Sutskever在2014年发在NIPS上的,其实他并非第一个提出seq2seq的人。本文对英语到法语的WMT14数据集进行了翻译,得到34.81的BLEU分数;对统计机器翻译的用这个模型得到的重打分做平均,BLEU也提高3.2个点。本文的seq2seq集成了8个lstm(每个384M参数、8000维)和test时使用从左到右的Beam Search解码。

背景知识

(一)BLEU评价指标

BLEU(bilingual evaluation understudy,双语互译质量评估辅助工具)是自动为机器翻译结果进行评价的指标。主要是通过算法翻译结果和人工的翻译语料去对比,从而判断模型好坏。论文可见《BLEU》
那么我们就会有一到多个机器翻译结果(我们称为候选翻译集,candidate)和一到多个参考翻译集(reference),以及被翻译语言(源语言,source)和目标语言(target)。我们会统计n-gram的正确比例,然后加权平均(加权平均使用公式视情况)。下面是具体过程:
首先统计候选翻译和参考翻译n-gram下词的频次数,然后每个候选翻译和每个参考翻译分别比较出最小的词频,然后结果里再比出最大的。
C o u n t w i , j c l i p = m i n ( C o u n t w i , R e f j _ C o u n t w i ) Count_{w_i,j}^{clip} = min(Count_{w_i},Ref_{j}\_Count_{w_i}) Countwi,jclip=min(Countwi,Refj_Countwi)

C o u n t c l i p = m a x ( C o u n t w i , j c l i p ) , i = 1 , 2 , 3...... Count^{clip} = max(Count_{w_i,j}^{clip}), i=1,2,3...... Countclip=max(Countwi,jclip),i=1,2,3......
最后对n-gram结果加权平均,打出分值。
p n = ∑ c ∈ c a n d i d a t e s ∑ n − g r a m ∈ c C o u n t c l i p ( n − g r a m ) ∑ c ∈ c a n d i d a t e s ′ ∑ n − g r a m ∈ c ′ ′ C o u n t c l i p ( n − g r a m ′ ) p_{n}=\frac{\sum_{c_{\in candidates}}\sum_{n-gram_{\in c}}Count_{clip}(n-gram)}{\sum_{c^{'}_{\in candidates}}\sum_{n-gram^{'}_{\in c^{'}}}Count_{clip}(n-gram^{'})} pn=ccandidatesngramcCountclip(ngram)ccandidatesngramcCountclip(ngram)

p a v e = e x p ( 1 4 ∗ ( l o g p 1 + l o g p 2 + l o g p 3 + l o g p 4 ) ) p_{ave}=exp(\frac{1}{4}*(log^{p_{1}}+log^{p_{2}}+log^{p_{3}}+log^{p_{4}})) pave=exp(41(logp1+logp2+logp3+logp4))
当然,如果参考翻译是the boy is best,而候选翻译是the,那么这个时候打分也会是1,所以我们希望译句长度也是合适的,于是引入了惩罚项,让候选翻译和至少一个参考翻译长度相同,即达到最佳匹配长度。
对未达到的进行长度惩罚,达到的不惩罚,此时惩罚因子设为1。
B P = { e 1 − r c … … i f … c ≤ r 1 … … … … i f … c > r BP=\lbrace^{1…………if…c>r}_{e^{1-\frac{r}{c}}……if…c \leq r} BP={e1crifcr1ifc>r
就有了最终打分函数,为了展示好看,一般乘100展示:
B L E U = B P ∗ e x p ( ∑ n = 1 N w n ∗ l o g p n ) BLEU=BP*exp(\sum_{n=1}^{N}w_{n}*log^{p_{n}}) BLEU=BPexp(n=1Nwnlogpn)
下面放注释好的使用1-gram、2-gram混合的代码辅助理解,使用nltk封装好的函数:

# -*- coding: utf-8 -*-
# @Software: PyCharm
# @Author: Beilop Jiao
# @Contact: 781933206@qq.com
# @Time: 2021/1/9 19:09

from nltk.translate.bleu_score import sentence_bleu

#参考文献1和参考文献2

reference = [['the','boy','is','the', 'best'],
             ['he', 'is','the','only']]
#翻译结果1

candidate = ['the','the','the','the']

#使用uni-gram即1-gram和bi-gram即2-gram,然后加权平均。
#首先1-gram比较翻译结果the出现的频次,翻译结果是4次the,第一个参考出现2次,第二个1次;
#然后求翻译结果和参考翻译的最小频次,分别是2,1;
#然后比较上一步里最大的,除以翻译结果的频次,是2/4=0.5;

#使用2-gram,重复上面的过程;翻译结果是3次“the the”,显然参考集的2-gram没有重合,打分都为0。
#再加权平均一下,这里默认是对数加权平均,值很小:1.1125369292536926e-308。
#加上3-gram,4-gram后值会近乎0,这就是说翻译结果很差的意思。
#大家可以试试只用1-gram,计算出来是0.5。然后自己写个句子试试。weights改为(1,0,0,0)即可。

score = sentence_bleu(reference, candidate, weights=(1, 1, 0, 0))
print(score)

优点很明显:方便、快速、结果有参考价值
缺点也不少,主要有:

  1. 不考虑语言表达(语法)上的准确性。
  2. 测评精度会受常用词的干扰。
  3. 短译句的测评精度有时会较高。
  4. 没有考虑同义词或相似表达的情况,可能会导致合理翻译被否定。
(二)HMM隐马尔可夫模型

大家可以自己去看一下。

(三)Viterbi维特比算法

同上。

(四)BeamSearch

如果我们在一个10000维的序列里去找最优的路径,仍旧使用viterbi算法显然不大明智,每次搜索就是10000步的softmax,即使最好的TPU也撑不住。贪婪搜索每次只要一步softmax,但显然不一定搜索到的就是最好的。beam search相当于做了个折中,每次维持一个大小为 K 的翻译语句集合,每次只需要k步softmax即可。下面是保持每步大小为2的beam search。
在这里插入图片描述
论文使用的beam search大小是12,用大小为1和2的做了对比,其实大小为2的就已经提高很多。
实际上,viterbi就是保留大小为全部大小的beam search,而贪婪搜索就是保留大小为1的beam search。

Seq2Seq模型

即输入一个序列(句子/图像等),输出一个序列的模型。
基本思想就是使用一个Encoder把输入序列编码成定长向量C,Decoder解码这个向量产生输出。
下面是机器翻译常用的seq2seq模型,这里encoder和decoder一般都是RNN结构,可以是lstm或者gru等。C其实就是encoder模型最后一层的输出,而源语言和目标语言采用不同的embedding。
在这里插入图片描述
举个栗子说明和语言模型不同的地方:beijing的概率在这里是P(Beijing|欢迎,来,北京,welcome,to)。
通过把输入反序可以降低对近距离的词高度依赖的问题,让优化变得更容易。再举个栗子,把“欢迎,你,来,北京,玩”变为“玩,北京,来,你,欢迎”,降低了近距离的依赖,提高长期依赖。在这里就是降低了welcome对玩的依赖,to对北京的依赖,提高welcome对欢迎依赖等等。这样也可以学到更多关系。不需要担心倒置后“玩”和最后对应的“play”会因为依赖太长而翻译不好,因为对序列任务首要的是翻译好前面的词,前面的翻译好了,后面的词会自然而然地得到好的信息提高准确率。
可以看到对语义、语法、语态学习效果都相当不错,相近的句子在向量空间离得很近,即使还进行了调换语序等干扰:
在这里插入图片描述
以前的rnn模型有两个问题:

  1. 只能预测等长序列。
  2. 只能用前面信息预测后面信息的问题,翻译问题可能各语言语序不同,而需要用到全局信息。

seq2seq模型很好地解决了这两点。

deep nmt

在seq2seq模型基础上,本文集成了4个lstm作为encoder层,4个lstm作为decoder层,测试时使用beam search,我们称之为deep nmt模型,也就是深层神经机器翻译模型。这一点开头已经说过。
在这里插入图片描述
可以看到多层lstm里,每层lstm的每一时间步输出H不止作为本层下一时间步输入,还作为下一层lstm这个时间步的输入。
在这里插入图片描述

decoder也是一样。decoder在训练时依旧会输入参考翻译w,x,y,z去产生loss,训练参数,得到预测输出。而测试的时候decoder不再输入参考翻译,这也和beam search是有关的。
一般decoder层我们还会把最后一层lstm的当前时间步信息给到最前面一层的下一时间步。
当句子过长时我们为了避免遗忘c的信息,还会把c的信息输入到decoder的每一个时间步而不是第一个时间步,当然有attention后就不需要这个结构了,且效果更好。
在这里插入图片描述

Some Tricks

总结一下小技巧:

  1. Encoder 和Decoder使用不同LSTM,实际上每个LSTM都不共享参数。
  2. 深层LSTM效果更好,但如果太深会难以训练,也可能会梯度消失。
  3. 源语言倒序输入会大幅提高效果。

以下是本文的其他一部分炼丹术:

  1. 参数初始化为-0.8到0.8之间的均匀分布。
  2. 使用不带动量的SGD,学习率0.7,5个epoch后每0.5轮学习率减半,一共训练7.5轮。
  3. 批次128大小,梯度除以批次大小即可。
  4. 可能会有梯度爆炸问题,对梯度g求二范数s,如果s>5,令g=5g/s,这里的g是除以128之后的。
  5. 为了加快速度,对句子长度进行排序,让每个batch的句子长度都差不多,这样就不需要对句子补<PAD>让句子等长,大概会加速2倍。

应用

  1. GNMT谷歌翻译的基石。
  2. 多层LSTM配合attention是transformer出来之前的最强模型。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值