AWD-LSTM为什么这么棒?_regularizing and optimizing lstm language models-程序员宅基地

技术标签: 算法  语言模型  神经网络  

AWD-LSTM是目前最优秀的语言模型之一。在众多的顶会论文中,对字级模型的研究都采用了AWD-LSTMs,并且它在字符级模型中的表现也同样出色。

本文回顾了论文——Regularizing and Optimizing LSTM Language Models ,在介绍AWD-LSTM模型的同时并解释其中所涉及的各项策略。该论文提出了一系列基于词的语言模型的正则化和优化策略。这些策略不仅行之有效,而且能够在不改变现有LSTM模型的基础上使用。

AWD-LSTM即ASGD Weight-Dropped LSTM。它使用了DropConnect及平均随机梯度下降的方法,除此之外还有包含一些其它的正则化策略。我们将在后文详细讲解这些策略。本文将着重于介绍它们在语言模型中的成功应用。

实验代码获取:awd-lstm-lm GitHub repository

LSTM中的数学公式:

  • it = σ(Wixt + Uiht-1)
  • ft = σ(Wfxt + Ufht-1)
  • ot = σ(Woxt + Uoht-1)
  • c’t = tanh(Wcxt + Ucht-1)
  • ct = it ⊙ c’t + ft ⊙ c’t-1
  • ht = ot ⊙ tanh(ct)


其中, Wi, Wf, Wo, Wc, Ui, Uf, Uo, Uc都是权重矩阵,xt表示输入向量,ht表示隐藏单元向量,ct表示单元状态向量, 表示element-wise乘法。
接下来我们将逐一介绍作者提出的策略:

权重下降的LSTM

RNN的循环连接容易导致过拟合问题,如何解决这一问题也成了一个较为热门的研究领域。Dropouts的引入在前馈神经网络和卷积网络中取得了巨大的成功。但将Dropouts引入到RNN中却反响甚微,这是由于Dropouts的加入破坏了RNN长期依赖的能力。

研究学者们就此提出了许多解决方案,但是这些方法要么作用于隐藏状态向量ht-1,要么是对单元状态向量ct进行更新。上述操作能够解决高度优化的“黑盒”RNN,例如NVIDIA’s cuDNN LSTM中的过拟合问题。

但仅如此是不够的,为了更好的解决这个问题,研究学者们引入了DropConnect。DropConnect是在神经网络中对全连接层进行规范化处理。Dropout是指在模型训练时随机的将隐层节点的权重变成0,暂时认为这些节点不是网络结构的一部分,但是会把它们的权重保留下来。与Dropout不同的是DropConnect在训练神经网络模型过程中,并不随机的将隐层节点的输出变成0,而是将节点中的每个与其相连的输入权值以1-p的概率变成0。


Regularization of Neural Networks using DropConnect

DropConnect作用在hidden-to-hidden权重矩阵(Ui、Uf、Uo、Uc)上。在前向和后向遍历之前,只执行一次dropout操作,这对训练速度的影响较小,可以用于任何标准优化的“黑盒”RNN中。通过对hidden-to-hidden权重矩阵进行dropout操作,可以避免LSTM循环连接中的过度拟合问题。

你可以在 awd-lstm-lm 中找到weight_drop.py 模块用于实现。

作者表示,尽管DropConnect是通过作用在hidden-to-hidden权重矩阵以防止过拟合问题,但它也可以作用于LSTM的非循环权重。

使用非单调条件来确定平均触发器

研究发现,对于特定的语言建模任务,传统的不带动量的SGD算法优于带动量的SGD、Adam、Adagrad及RMSProp等算法。因此,作者基于传统的SGD算法提出了ASGD(Average SGD)算法。

Average SGD

ASGD算法采用了与SGD算法相同的梯度更新步骤,不同的是,ASGD没有返回当前迭代中计算出的权值,而是考虑的这一步和前一次迭代的平均值。

传统的SGD梯度更新:

w_t = w_prev - lr_t * grad(w_prev)

AGSD梯度更新:

avg_fact = 1 / max(t - K, 1)
if avg_fact != 1:
  w_t = avg_fact * (sum(w_prevs) + (w_prev - lr_t * grad(w_prev)))
else:
  w_t = w_prev - lr_t * grad(w_prev)

其中,k是在加权平均开始之前运行的最小迭代次数。在k次迭代开始之前,ASGD与传统的SGD类似。t是当前完成的迭代次数,sum(w_prevs)是迭代k到t的权重之和,lr_t是迭代次数t的学习效率,由学习率调度器决定。

你可以在这里找到AGSD的PyTorch实现。

但作者也强调,该方法有如下两个缺点:

  • 学习率调度器的调优方案不明确
  • 如何选取合适的迭代次数k。值太小会对方法的有效性产生负面影响,值太大可能需要额外的迭代才能收敛。

基于此,作者在论文中提出了使用非单调条件来确定平均触发器,即NT-ASGD,其中:

  • 当验证度量不能改善多个循环时,就会触发平均值。这是由非单调区间的超参数n保证的。因此,每当验证度量没有在n个周期内得到改进时,就会使用到ASGD算法。通过实验发现,当n=5的时候效果最好。
  • 整个实验中使用一个恒定的学习速率,不需要进一步的调整。

正则化方法

除了上述提及的两种方法外,作者还使用了一些其它的正则化方法防止过拟合问题及提高数据效率。

长度可变的反向传播序列

作者指出,使用固定长度的基于时间的反向传播算法(BPTT)效率较低。试想,在一个时间窗口大小固定为10的BPTT算法中,有100个元素要进行反向传播操作。在这种情况下,任何可以被10整除的元素都不会有可以反向支撑的元素。这导致了1/10的数据无法以循环的方式进行自我改进,8/10的数据只能使用到部分的BPTT窗口。

为了解决这个问题,作者提出了使用可变长度的反向传播序列。首先选取长度为bptt的序列,概率为p以及长度为bptt/2的序列,概率为1-p。在PyTorch中,作者将p设为0.95。

base_bptt = bptt if np.random.random() < 0.95 else bptt / 2

其中,base_bptt用于获取seq_len,即序列长度,在N(base_bptt, s)中,s表示标准差,N表示服从正态分布。代码如下:

seq_len = max(5, int(np.random.normal(base_bptt, 5)))

学习率会根据seq_length进行调整。由于当学习速率固定时,会更倾向于对段序列而非长序列进行采样,所以需要进行缩放。

lr2 = lr * seq_len / bptt

Variational Dropout

在标准的Dropout中,每次调用dropout连接时都会采样到一个新的dropout mask。而在Variational Dropout中,dropout mask在第一次调用时只采样一次,然后locked dropout mask将重复用于前向和后向传播中的所有连接。

虽然使用了DropConnect而非Variational Dropout以规范RNN中hidden-to-hidden的转换,但是对于其它的dropout操作均使用的Variational Dropout,特别是在特定的前向和后向传播中,对LSTM的所有输入和输出使用相同的dropout mask。

点击查看官方awd-lstm-lm GitHub存储库的Variational dropout实现。详情请参阅原文

Embedding Dropout

论文中所提到的Embedding Dropout首次出现在——《A Theoretically Grounded Application of Dropout in Recurrent Neural Networks》一文中。该方法是指将dropout作用于嵌入矩阵中,且贯穿整个前向和反向传播过程。在该过程中出现的所有特定单词均会消失。

Weight Tying(权重绑定)

权重绑定共享嵌入层和softmax层之间的权重,能够减少模型中大量的参数。

Reduction in Embedding Size

对于语言模型来说,想要减少总参数的数量,最简单的方法是降低词向量的维数。即使这样无法帮助缓解过拟合问题,但它能够减少嵌入层的维度。对LSTM的第一层和最后一层进行修改,可以使得输入和输出的尺寸等于减小后的嵌入尺寸。

Activation Regularization(激活正则化)

L2正则化是对权重施加范数约束以减少过拟合问题,它同样可以用于单个单元的激活,即激活正则化。激活正则化可作为一种调解网络的方法。

loss = loss + alpha * dropped_rnn_h.pow(2).mean()

Temporal Activation Regularization(时域激活正则化)

同时,L2正则化能对RNN在不同时间步骤上的输出差值进行范数约束。它通过在隐藏层产生较大变化对模型进行惩罚。

loss = loss + beta * (rnn_h[1:] - rnn_h[:-1]).pow(2).mean()

其中,alpha和beta是缩放系数,AR和TAR损失函数仅对RNN最后一层的输出起作用。

模型分析

作者就上述模型在不同的数据集中进行了实验,为了对分分析,每次去掉一种策略。

图中的每一行表示去掉特定策略的困惑度(perplexity)分值,从该图中我们能够直观的看出各策略对结果的影响。

实验细节

数据——来自Penn Tree-bank(PTB)数据集和WikiText-2(WT2)数据集。

网络体系结构——所有的实验均使用的是3层LSTM模型。

批尺寸——WT2数据集的批尺寸为80,PTB数据集的批尺寸为40。根据以往经验来看,较大批尺寸(40-80)的性能优于较小批尺寸(10-20)。

总结

该论文很好的总结了现有的正则化及优化策略在语言模型中的应用,对于NLP初学者甚至研究者都大有裨益。论文中强调,虽然这些策略在语言建模中获得了成功,但它们同样适用于其他序列学习任务。


原文链接
本文为云栖社区原创内容,未经允许不得转载。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/yunqiinsight/article/details/82797449

智能推荐

java jmstemplate_java – Spring JmsTemplate – 添加自定义属性-程序员宅基地

文章浏览阅读175次。我使用Spring API的JmsTemplate和MappingJackson2MessageConverter(版本:spring-jms-4.3.4.RELEASE.jar)来发布消息到ActiveMQ主题,如下面的代码所示.TopicPublisher类:@Componentpublic class TopicPublisher {@Autowiredprivate JmsTemplate..._spring 定义jmstopictemplate

初学者都能看懂的蒙特卡洛方法以及python实现_python编程蒙特卡罗-程序员宅基地

文章浏览阅读10w+次,点赞299次,收藏1.5k次。1.什么是蒙特卡洛方法(Monte Carlo method)蒙特卡罗方法也称统计模拟方法,是1940年代中期由于科学技术的发展和电子计算机的发明,而提出的一种以概率统计理论为指导的数值计算方法。是指使用随机数(或更常见的伪随机数)来解决很多计算问题的方法。 20世纪40年代,在冯·诺伊曼,斯塔尼斯拉夫·乌拉姆和尼古拉斯·梅特罗波利斯在洛斯阿拉莫斯国家实验室为核武器计划工作时,发明了蒙特卡罗..._python编程蒙特卡罗

将项目部署在linux系统上,将项目部署到linux下的docker容器中-程序员宅基地

文章浏览阅读402次。此时docker是已经安装好的状态序言:介绍一下需要运行的Python项目的结构: 平时在PyCharm里面运行该工程,只要直接运行server.py文件即可 现在希望将该工程,部署到docker里面,使用容器启动:步骤如下:1:创建一个上传到Linux系统文件夹(文件名任意)docker_EF_NFCS是要上传到Linux系统,生成Docker镜像的文件夹 docker_EF_NFCS文件夹下面..._cmd ["python", "/code/package/server.py"]

用sonar扫描maven的多模块项目_多个maven工程可以一起扫描sonar规则?-程序员宅基地

文章浏览阅读1.4w次。本来想借助mvn sonar:sonar执行代码分析,但是因为父工程没有class文件,总是缺少相应的依赖;顾只能改用sonar-scanner进行。具体实施如下:1.maven多模块工程如图所示:我们可以看到此时multi-boluome工程下有dao、domain、service、web四个模块项目,且每一个都有其独立的pom.xml文件;2.因为借助sonar-scanner..._多个maven工程可以一起扫描sonar规则?

Linux:如何安装RPM呢?_ruhe xiezai rpm-程序员宅基地

文章浏览阅读1.1k次。RPM 安装( install )安装就是 install 嘛!所以啰,使用 rpm 来安装就很简单啦!假设我要安装一个档名为 rp-pppoe-3.1-5.i386.rpm 的档案,那么我可以这样( 记得某些套件可能需要以系统管理员的身份来安装 ): [root@test root]# rpm -i rp-pppoe-3.1-5.i386.rpm不过,这样的参数其实无法显示安装的进度,所以,通常我们会这样下达安装指令:  另外,如果我们在安装的过程当中发现问题,或者已经知道会发生的_ruhe xiezai rpm

php gif动态验证码,PHP实现GIF图片验证码_php技巧-程序员宅基地

文章浏览阅读256次。这是一个用PHP生成GIF动画来实现动态图片验证码的程序,非常实用,是php用户注册登录界面经常需要用到的验证码程序,有需要GIF动态图片验证码功能的朋友可以收藏一下。第一步:创建ImageCode.php文件,验证码生成函数代码如下:0) // 屏蔽第一帧{for ($k = 0; $k < strlen($authstr); $k++){$colorRandom = mt_ra..._php动画验证码

随便推点

虚拟内存_matlab2010 虚拟内存-程序员宅基地

文章浏览阅读134次。程序代码和数据。对所有的进程来说,代码是从同一固定地址开始,紧接着的是和C 全局变量相对应的数据位置。堆。代码和数据区在进程一开始运行时就被指定了大小,与此不同,当调用像 malloc 和 free 这样的 C 标准库函数时,堆可以在运行时动态地扩展和收缩。共享库。大约在地址空间的中间部分是一块用来存放像 C 标准库和数学库这样的共享库的代码和数据的区域。栈。位于用户虚拟地址空间顶部的是用户栈,编译器用它来实现函数调用。和堆一样,用户栈在程序执行期间可以动态地扩展和收缩。特别地,每次我们调用..._matlab2010 虚拟内存

AI当自强:独家揭秘旷视自研人工智能算法平台Brain++-程序员宅基地

文章浏览阅读1.3k次,点赞2次,收藏5次。随着深度学习逐渐从实验室走向工业应用,各大企业都在探索构建算法架构、实现模型的工具和平台。和使用 TensorFlow 或 PyTorch 等开源框架的公司不同,旷视走向..._旷视刷掌算法

关于IDEA使用时一选中代码段光标就变粗的解决方案_idea光标变粗了怎么办-程序员宅基地

文章浏览阅读1.2k次。一、选中菜单栏中的Tool工具项二、将Vim钩子去掉三、回到IDEA操作界面,insert按键可以使光标变细,就回归正常操作了_idea光标变粗了怎么办

Java网络编程基础学习-程序员宅基地

文章浏览阅读565次。1、网络编程概述:_java网络编程基础学习

【转载】利用Java XStream序列化为XML及将XML反序化为对象示例代码_xstream 反序化-程序员宅基地

文章浏览阅读104次。XStream是一个很容易上手的工具,也在日常开发中极为常用.其特点如下: 一、可以将对象序列化为XML,也可以将XML反序列化对象; 二、不需要任何配制,速度快,占用内存小,生成的XML可以写到文件,做持久化; 用到的JAR包括:xstream-1.3.jar、xpp3_min-1.1.4c.jar/** * */package test;import com.thoughtworks...._xstream 反序化

IPC-(进程间通信)-实现方式_ipc通信实现-程序员宅基地

文章浏览阅读1.7k次。ipc实现方式_ipc通信实现

推荐文章

热门文章

相关标签