您的位置:首页 > 理论基础 > 计算机网络

Neural Network Methods for Natural Language Processing 读书笔记1 —— 神经网络入门

2018-02-26 22:33 661 查看
前段时间一口气读完了 NN4NLP,很是畅快,非常喜欢作者行文讲解的口吻和逻辑。大概两周读完,每页都有收获,读完后反而担心有所疏漏,知识太多留不住,索性从头来一遍,把学习过程的知识点和思考记录下来,也算精简版供自己今后查阅。

感兴趣的,可以一起学习讨论,真的很推荐这本书。

大致介绍下该书。NN4NLP 由 Goldberg 撰写,是 CMU CS11-747 课程的教材,配合公开课食用更佳,公开课链接。本书并非系统介绍 NN 和 NLP,而是聚焦 NN 在 NLP 领域的具体应用,所以分成了四大部分:NN 中前馈神经网络的入门,前馈神经网络在 NLP 中的应用,RNN 等特殊结构在 NLP 中的应用,部分前沿方向介绍。

因此,本博客也打算分成多篇进行总结,其他篇章请自行搜索本博客。

NLP 与 NN 简介

由于人类语言的天然歧义性、不断变化演进、难以确切定义表示支配语言的规则、符号化离散化可组合性稀疏性对计算不友好等特性,使得 NLP 研究极具挑战性。

早期,NLP 的研究停留在符号层面,即基于逻辑、规则和本体。现在,NLP 研究的主流是基于统计的机器学习方法。很长一段时间,核心的 NLP 技术大多是监督学习中的线性模型方法,如感知机、线性 SVM、LR 等。大约从2014年起,NLP 的主流方法转移到非线性的神经网络方法,从而输入也从稀疏高维特征向量变为低位稠密特征向量。

NN 不仅像传统 ML 方法一样学习预测,也学习如何正确表达数据,即在处理输入输出对时,网络内部产生一系列转化以处理输入数据来预测输出数据。设计者需要做的事设计网络结构和训练机制,给网络提供适当的输入输出对,并适当地编码输入数据,繁重的学习正确表达数据的工作由网络完成。

NN 一大优点就是大幅简化了特征工程工作,即允许设计者仅制定一个较小的核心的基本的自然的特征集合,由 NN 结构来将它们组合为更高层级的特征(representation)。也可以说NN最大威力就在于学习到好的 representation 的能力。通常这些 representation很复杂,不单单是线性组合,因此不再具有可解释性。

虽然应用核方法的 ML 算法也可以实现从核心特征中自动结合更高层次的特征,但还是存在缺陷。应用核方法的分类器的计算复杂度和训练数据的规模呈线性关系,因而难以处理大规模数据,而 NN 分类器的计算复杂度只是网络规模的线性关系,和训练数据规模无关。

NN 在 NLP 中的应用,很大一部分涉及嵌入层(embedding layer),即将离散符号应设为连续的低维向量。两大类 NN 结构中,前馈神经网络接收固定尺寸的输入或者变长但不考虑元素顺序的输入,其中 MLP 可以用在任意之前线性模型可用的任务中; RNN 则主要用于处理序列数据,由于避免了之前序列模型中普遍需要的 Markov 假设,大大推广了在语言模型、自动机器翻译等多个 NLP 任务中的应用。当然,RNN 很少作为孤立模块使用,通常作为可训练模块,配合后续网络模块一起使用,主要用来产生向量,喂给后续的预测模块,但训练过程还是 RNN 部分和预测部分一起训练,即 end-to-end。

注意,本书中介绍的 NLP 任务大多是低层次相对定义明确的任务,像对话系统、文档摘要、问答系统等尚属于开放问题的,并未涉及。

神经网络入门

从监督机器学习中的线性模型到 MLP

本书所讨论的 NN 是一类监督 ML 算法,因此需要对监督 ML 算法有基本了解,但过于基础,不再细述。

线性模型的限制是处理不了非线性可分问题,典型如 XOR 问题。

一种方法是,手动设计非线性映射,将线性不可分数据转化为线性可分的,通常是变换到更高维空间,再利用线性模型解决。但这个手动设计过程需要靠直觉运气。

一种方法是,利用核技巧,过程同上。但利用核技巧的 SVM 方法将线性依赖训练集的尺寸,使得难以应用到大规模训练数据集。另一个缺点是高维空间增加了过拟合的风险。

另一种方法是,定义一个可训练的非线性映射函数,将其与后续的线性分类器一同训练,即找到合适的映射表示的工作成了训练算法的责任,从而解决非线性可分问题,此即 NN 的主要思想。显然,这个映射函数应可微,从而可以应用基于梯度的训练方法。如下图,



上图即描述了非常常见的 NN 结构——MLP。

前馈神经网络

MLP

典型的前馈神经网络如下图所示,



数学上,可表示为



神经元(Neuron)实现了上一节的φ作用,其中的非线性激活函数实现了 g 的作用。

如果该层所有神经元都与下一层所有神经元相连接,称之为全连接层或者仿射层。

定义了线性映射的项 W 和 b 属于网络的参数,由优化算法学习。不过不像线性模型,MLP 的损失函数并不是关于网络参数的凸问题,所以难以获得全局最优解,但仍是使用基于梯度的优化方法去搜寻。

表现能力

那么 MLP 的表现能力如何呢?Universality Theorem 表明,MLP1 是一个通用逼近器,简单来说可以实现任意的由 N 维实数空间到 M 维实数空间的连续函数。

虽然理论表明一层 MLP 即具有极强的表达能力,但并没告诉我们如何实现这一能力,实际上训练到想要的程度并不简单,包括超参设置。

理论表明,更深的 MLP 比更广的 MLP 性能表现更好。

非线性

非线性 g 有多种形式,目前并没有比较好的理论指导什么样的条件用什么非线性函数更好,通常根据确切任务靠经验选取。

常用的如下:

Sigmoid,σ(x)=1/(1+e^-x)以前较权威,目前在 NN 的内层中已弃用。

Tanh,tanh(x)=(e^2x-1)/(e^2x+1)。

Hard tanh,是 tanh 的近似,但计算和求导更快,hardtanh(x)={-1,x<-1;1,x>1;x,otherwise}。

ReLU,ReLU(x)=max(0,x),虽然形式很简单,但在很多任务中表现不错,尤其是和dropout正则化技术结合时。

正则化和 dropout

防止 NN 过拟合技术包括正则化和 dropout。

正则化包括 L1、L2和 elastic-net 等,

dropout 设计来避免网络学习着依赖特定权重,可以通过在随机梯度训练中,对每个训练样本随机舍弃网络中或某层的一半神经元(即神经元输出为0)来实现。

理论分析表明,dropout 和 L2 有很强的关联性,此外也可以把 dropout 看做模型平均和 ensemble 技术。

NN 的训练

NN 也是可微的参数化函数,可通过基于梯度的优化算法训练。虽然 NN 的非线性导致目标函数非凸,基于梯度的方法很难找到全局最优,但实践中仍然很有效。

线性模型中的梯度计算依赖微分的链式法则,这在复杂网络中变得艰难且易错。乐村98年提的反向传播算法有效地解决了这个问题。

反向传播算法通过缓存中间结果,来计算利用链式法则的复杂表达式的导数。反向传播算法也可以看做反转自动微分算法的特例。

计算图抽象

计算图抽象可以方便实现:构建任意网络、估计对应输入的预测(前向传导)、关于任意标量损失计算参数的梯度(反向传导)。

计算图将任意数学计算表述为一个图,是一个有向无环图(DAG)。NN 也是一个数学表达式,因此可以表示成计算图,如 MLP1 可以表示为



通常计算图的构造通过已有的软件库或者 API 完成,之后只要直接执行前向计算获得计算结果,或者反向计算获得梯度即可。

(1) 前向计算



注意,这里的 N 个节点的序号 i 由拓扑排序确定,DAG 拓扑排序的经典算法由 khan、DFS 等。

(2) 反向计算



(3) 实现软件

实现计算图模型的软件包有不少,包括 Theano、TensorFlow、Chainer、DyNet 等。

DyNet 和 Chainer 使用的动态图构建方式,TensorFlow 和 Theano 采用了静态图构建方式。

在动态图构建方式中,每次对训练样本通过语言编码重新产生一个不同的计算图,然后前向和方向传播应用于该图。在静态图构建方式中,计算图的形状通过 API 在计算最初只定义一次,然后优化图编译器会产生一个最优的计算图,每个训练样本都将喂给这个最优计算图。

静态图构建方式是把双刃剑。一方面,一旦构建就可以在 CPU 或 GPU 上高效运行,特别适合固定结构的大型图。另一方面,编译过程本身非常耗时,使得接口更难应用。此外,对于 RNN 和在结构化预测环境中,动态图构建方式更方便。

实践考量

下面介绍 NN 训练过程中的一些重要影响因素,并非系统介绍。

(1)优化算法选择

SGD。

SGD+Momentum,Nesterov Momentum 等,属于SGD 的变种,将前面的梯度进行累积影响本次更新。

AdaGrad、AdaDelta、RMSProp、Adam 等,属于自适应学习速率算法。

通常,对于大规模网络,Adam 表现更高效也更强健。

(2)初始化

由于 NN 目标函数的非凸性,优化过程很可能卡在局部最小点或者鞍点,且从不同初始点开始优化可能得到不同结果。因此很有必要从不同的随机初始点进行多次训练选最优。

随机值的量级对训练影响也很大。

通常采用 bengio2010提出的 xavier 初始化方法。许多环境会默认选择此方法。He2015提出使用 ReLU时,从零均值sqrt(2/d_in)标准差高斯分布取样进行初始化性能也很好,尤其适用于深度网络。

(3)梯度消失和爆炸

在深度网络中,在计算图中反向传播时,经常发生错误梯度消失(逼近0)或者爆炸(逼近无穷)。该问题随着网络变深更加严重,尤其在 RNN 中。

处理梯度消失仍是个开放问题。方法包括浅化网络、步进式训练、批正则化、使用特殊结构(如针对 RNN 采用 LSTM 或者 GRU 结构)。

处理梯度爆炸,简单但有效的方式即当梯度的范数超过某阈值时修剪该梯度。

(4)饱和及死亡神经元

采用 tanh 和 sigmoid 激活函数的层可能出现饱和现象,即该层的输出值均接近1(激活函数的上限),导致该层的梯度非常小。

进入该层的值太大将导致饱和神经元出现。

改变初始化方式、缩放输入值的范围、改变学习率等方式可能起到控制作用。对于饱和层,还有一种选择是归一化饱和层经过激活函数后输出的值,该方法虽然对计数饱和有效,但计算复杂度高。CV 中还有一种相关的技术较批正则化,只是 NLP 中应用很少。

采用 ReLUctant 激活函数的层虽不会饱和,但可能死亡,即绝大多数输出值为负因此对所有输入都被修剪为0,导致该层的梯度为0。

进入该层的所有值均为负将导致死亡神经元出现。

降低学习率将会有所帮助。

(5)shuffling

训练样本供给给网络的顺序也很重要。一般建议提前 shuffle 数据。但当样本不是 IID 时,shuffle 反而不合适。

(6)学习速率

学习速率通常从0.001、0.01、0.1、1中进行试验。一般学习速率应随着训练进行递减。

注意,learning rate cannot be one-size-fits-all, and give different parameters different learning rate。

(7)minibatch

有时大点的 minibatch 计算效率更高,如 GPU 上。

(8)损失函数

当使用 softmax 输出层时,建议选择交叉熵

(9)激活函数
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐