基于TensorFlow 的神经网络语言模型
Dr.Pachira 普强信息 2018-01-03
当前无论是学术界还是工业界,深度学习都受到极大的追捧。Google在2015年11月推出开源深度学习平台TensorFlow,由于其灵活性和高效性,不仅促进学术界的研究进程,同时提供了解决大量实际问题优秀的工具。普强一直致力于为客户提供高效精准的语音识别服务,在语音识别技术框架中,语言模型是一个最基本的组成模块,能够对语音识别的准确率产生重要影响。本文主要介绍深度学习在语言模型中的相关应用,以及如何利用TensorFlow平台产品化上述技术,提高普强语音识别技术创新性及竞争力。
人工神经网络
人工神经网络(Artificial Neural Network, ANN)是一组大致模仿人类大脑构造设计的计算机算法或数学模型,属于机器学习(Machine Learning, ML)方法中的一类,适合于处理语音,图像,文本等数据,赋予计算机处理有关人类认知方面问题的能力,如语音识别,图像识别,自然语言理解等。
人工神经网络的基本组成单元称为一个神经元,其结构如下图所示:
一般而言,一个神经元可以接受多个输入经过一些线性或非线性变换后转化成一个输出值。神经元内部的这个变换函数称为激活函数(activation function),常用的激活函数包括:sigmoid, tanh, RELU等。
人工神经网络的神经元可以看成一种简化版的生物神经元。我们知道,生物神经元通过细胞体上的树突接收其他神经元的信号,而通过轴突向其他神经元传递信号;并且通常一个神经元有一个至多个树突,但轴突只有一条。
显然,单个神经元能够进行的处理和计算能力有限,因此类似生物的大脑,我们可以将许多个的神经元连接起来,组成一个更大规模的网络,这个网络就是人工神经网络,例如下图中这样:
出于计算的考虑,人工神经网络中的神经元不会像生物大脑中那样随意的连接,而是形成相对简单的分层结构。一般的基本组成包括:
· 输入层(input layer):每个网络中只有一个,处于这一层神经元用于接收输入数据;
· 隐藏层(hiddeng layer):每个网络可以由零个或多个,这部分神经元对输入进行变换,分析和计算;
· 输出层(output layer):每个网络中只有一个,这一层中的神经元对来自隐藏层或输入层的数据进行最后的处理,并输出最终结果。
深度学习
深度学习(Deep Learning, DL),顾名思义,指的使用是隐藏层的数目较大的深层神经网络(Deep Neural Network, DNN)为模型的机器学习方法。
传统神经网络主要使用由一个输入层和一个输出层组成的浅层网络,至多在两层之间添加一个隐藏层。三层以上(包括输入和输出层在内)的系统就可以称为“深度”学习。
在深度学习网络中,每一个节点层在前一层输出的基础上学习识别一组特定的特征。随着神经网络深度增加,节点所能识别的特征也就越来越复杂,因为每一层会整合并重组前一层的特征。随着特征越来越复杂,它们的抽象度也越来越高,可能会与人类大脑中的某些高层语义概念相对应,因而,使用这些特征能够更有利于和认知有关任务的处理。
深度的重要性可以在一些图像识别任务中直观的看到,如下图所展示的人脸识别深度模型:
(图源:Key Concepts of Deep Neural Networks)
观察图片左边部分,我们可以看到,随着层数的增加,神经网络学习到的特征越来越抽象。网络的第一层的特征只是一些简单纹理,方向等线条,第二层通过第一层得到的线条组成了一些脸部的局部细节,最终在第三层通过组合上一层的各个局部,形成一幅幅人脸的图像。
递归神经网络
前面我们举的例子中,神经元之间的连接只在相邻的层之间,并且是单方向的,这种类型的神经网络统称为前馈神经网络(Feed Forward Neural Network)。前馈神经网络的这种结构特性使得它在处理每个输入时,是不考虑之前的输入的,这仅对输入数据点之间是独立的应用有效。而许多实际的应用场景,每个输入点的值会对其他输入点的值有所依赖。这时,我们需要使用另一种结构的神经网络,即递归神经网络(Recurrent Neural Network, RNN),这种网络更适合处理时间序列的输入数据,如语音,手写识别,文本等。
递归神经网络与前馈神经网络的主要区别在于,递归神经网络的神经元在前馈神经网络神经元的基础,增加了一条到自身的连接,也就是说,神经元上一个时刻的输出会作为下一时刻的输入反馈给自身。如图所示,
通过这条自反馈连接,RNN把处理过的历史数据都存储在它的状态向量中,并且把它与输入数据一并送给神经元处理。由于这部分额外信息的获取,使得RNN具有更强的记忆和学习能力。
LSTM
历史信息使得RNN具备较强的记忆能力,但是同时也使RNN的学习过程变得更加困难。
RNN的学习通常使用的是沿时间反向传播(BackPropagation Through Time, BPTT)算法,这个算法需要多次连乘权重矩阵,这样就很容易出现极小或极大的数值,使得训练不稳定,这个问题被称为梯度消失(vanishing gradients)或梯度爆炸(exploding gradients)问题。
为解决上述问题,学者设计出一种称为长短期记忆(Long-Short Term Memory, LSTM)的模型。LSTM在RNN神经元的基础上,加入了三个门(gate),对模型的记忆内容进行精细的控制。一般使用的LSTM包含三个门:
· 输入门(input gate),控制输入数据权重;
· 忘记门(forget gate),控制历史信息权重;
· 输出门(output gate),控制输出结果权重。
LSTM神经元的结构,如下图所示,
使用LSTM能够使RNN模型的训练过程更稳定,学习更有效。
TensorFlow
为了加速深度学习领域的发展,2015年11月9日,Google发布深度学习框架TensorFlow并宣布开源。在不到一年时间内,在GitHub上,TensorFlow就成为了最流行的深度学习项目。TensorFlow在图形分类、音频处理、推荐系统和自然语言处理等场景下都有丰富的应用。
TensorFlow是一个深度学习框架,支持Linux平台,Windows平台,Mac平台,甚至手机移动设备等各种平台。其次,TensorFlow提供了非常丰富的深度学习相关的API,可以说目前所有深度学习框架里,提供的API最全的,包括基本的向量矩阵计算、各种优化算法、各种卷积神经网络和循环神经网络基本单元的实现、以及可视化的辅助工具等等。
TensorFlow的特点包括:
● 高度的灵活性
TensorFlow并不仅仅是一个深度学习库,只要可以把你的计算过程表示称一个数据流图的过程,我们就可以使用TensorFlow来进行计算。TensorFlow允许我们用计算图的方式还建立计算网络,同时又可以很方便的对网络进行操作。用户可以基于TensorFlow的基础上用Python编写自己的上层结构和库,如果TensorFlow没有提供我们需要的API的,我们也可以自己编写底层的C++代码,通过自定义操作将新编写的功能添加到TensorFlow中。
● 真正的可移植性
TensorFlow可以在CPU和GPU上运行,可以在台式机,服务器,甚至移动设备上运行。
● 多语言支持
TensorFlow采用非常易用的python来构建和执行我们的计算图,同时也支持C++ 的语言。我们可以直接写python和C++的程序来执行TensorFlow,也可以采用交互式的ipython来方便的尝试我们的想法。
● 丰富的算法库
TensorFlow提供了所有开源的深度学习框架里,最全的算法库,并且在不断的添加新的算法库。这些算法库基本上已经满足了大部分的需求,对于普通的应用,基本上不用自己再去自定义实现基本的算法库了。
● 完善的文档
TensorFlow的官方网站,提供了非常详细的文档介绍,内容包括各种API的使用介绍和各种基础应用的使用例子,也包括一部分深度学习的基础理论。
语言模型
语言模型是一种概率模型,它是基于一个语料库创建,得到每个句子出现的概率。语言模型在语音识别中起到重要的作用,如果没有语言模型,语音识别的结果只能是一些发音正确的词语或单字,却不一定能组成有意义的句子。关于语音识别原理的详细介绍,请参见我们的上一篇文章。
传统的N-gram语言模型数学上表示为:
上述公式的意义是:一个句子出现的概率等于给定前面的词情况下,紧接着后面的词出现的概率。它是通过条件概率公式展开得到。其中条件概率P(w2|w1),P(w3|w1w2),⋯,P(wt|w1w2⋯wt−1)就是创建语言模型所需要的参数,每个条件概率的意义解释为:根据前面的词预测下一个词的概率。有了这些条件概率参数,给定一个句子,就可以通过以上公式得到一个句子出现的概率。句子的概率越大,说明它越接近自然语言的表达。
神经网络的语言模型则是使用神经网络来建模句子的概率。将句子中的词按顺序逐个输入给一个神经网络,在每次得到的输出中找到下一个词的概率,最后将句子中所有词的概率连乘,就得到了这个句子的概率。
语言模型中下一个词的概率显然和之前历史的词有非常大的依赖关系,因此,LSTM比较适合于应用在语言模型建模中。
基于TensorFlow的LSTM语言模型
根据以上原理,我们就可以利用TensorFlow来实现LSTM语言模型了。根据以上原理,我们就可以利用TensorFlow来实现LSTM语言模型了。
● 模型训练
首先,扫描语料库建立字典,并为每个词编号。
第二步,需要建立TensorFlow的计算流图,在其中定义要使用的LSTM模型。这里的使用模型是一个N+2层的LSTM,其中第一层是输入层,又叫做词向量矩阵,然后是N层的LSTM隐藏层,最后连接的是输出层。输出层的神经元个数与词典中词数相同,每个神经元输出的值就是它所对应的词的概率大小。
第三步,使用BPTT算法训练模型。 这时我们需要优化目标函数,采用梯度下降逐步更新参数。
梯度下降算法最重要的参数就是学习率,需要人工设置一个合适的值,学习率太大容易造成训练过程不稳定,太小则会使得学习过程太慢。一般而言,我们会在一次训练的过程中,逐步减小学习率,最终使得训练收敛。
将上面所述转化为代码后,使用TensorFlow运行,我们就可以得到最终的模型。
● 模型评价
对于任何一种机器学习模型,我们都需要使用某种方法评价它的好坏。在语言模型领域,使用最多的是一种称为困惑度(Perplexity, PPL)的指标。其基本思想是给测试集的句子赋予较高概率值的语言模型较好,公式如下:
可以看出,困惑度和概率成反比,概率越高,困惑度越低,语言模型越好。
使用TensorFlow进行模型评估时,代码和训练时基本一样,只需要把最后运行的梯度下降的去掉。得到每一个词的概率后,就可以通过上面的公式计算PPL了。在Penn Tree Bank (PTB)数据集(训练集包含929k个词)上,不同模型的PPL如下:
模型 | PPL |
N-gram | 141 |
RNN | 123 |
LSTM | 82 |
显然,基于神经网络的模型效果优于传统的Ngram模型,而LSTM模型比RNN更优。