初识循环神经网络

1、循环神经网络-RNN的由来

之前写到的CNN,用的领域在计算机视觉-CV;接下来介绍的RNN的主要作用的领域是自然语言处理-NLP。

自然语言处理包括了现在最常见的领域:语音识别、语音模型、机器翻译、视频解说、文本分类和图片生成描述等等。为什么RNN能生效?

要从输入开始说起,之前说到的CNN都是固定大小的输入和模型的输出值;但在自然语言处理领域内的输入和输出都不在是定长了。比方:图片生成描述,输入一张图片,输出为一个句子;文本分类,输入是一段文本,输出是一个类别等。

现在要是还用之前CNN思想,要把变长的输入问题解决掉,怎么解决呢?

因为NLP处理的是自然语言,像机器翻译,输入的是一段字符串,而对于网络来说,能处理的只有数字,所以输入必须经过一定的处理,才能给网络来计算,这个处理的步骤称作为embedding。提到embedding,先来个相似的在CNN常用的概念 -- one-hot编码,假设我们的词表有5个,“公主很漂亮”。基本样子如下:

公 [0 0 0 0 1]
主 [0 0 0 1 0]
很 [0 0 1 0 0]
漂 [0 1 0 0 0] 
亮 [1 0 0 0 0]

可以看出,将所有的词做成了一个词表,每个词在词表中的相应位置标记为了1。那如果用一个向量来表示“公主很漂亮”的话,则为[4,3,2,1,0],这种编码方式被称作为稀疏编码。

针对稀疏编码来讲,如果要求输入的长度必须一致的话,当稀疏编码后的向量长度不够时,要引进padding的概念,也就是在稀疏编码后向量中添加某个值,补齐长度,这个值一般是自己定义的unknown word;而当稀疏编码后的长度过长时,则直接将过长的部分截断。

在稀疏编码的基础上,如果将每个词映射到一个向量上,而不是直接的取该词在词表中的索引,像:

公主 [ 1.0  0.25  1.0]
王妃 [ 0.6  0.75  1.0]

这种方式的编码,称作为dense_embedding,常在RNN中简称为embedding,密集编码。

针对密集编码来讲,如果要求输入的长度必须一致的话,采用的方法是合并。n个词语依次embedding,假设embedding向量的长度为10,那么结果组合就为 n * 10 矩阵,对于全连接的输入大小是固定的,所以用global_avg_pooling,将横向的维度消掉,变为长度为10 的向量。

而稀疏编码和密集编码这两种方式的缺点:
1、信息丢失:

  • 多个embedding合并后 有pad噪音 因为参与了avg_pooling计算 噪音过多 将原来的意思稀释
  • 即时没有pad 直接合并 没有句子中主次之分 像文本分类中更倾向的表达情感的词语 主语、连接词并不太重要 真实意思被稀释掉

2、无效计算太多,低效:
太多的padding 如果句子本身长度为20 而定长为500 480个padding 参与了计算 增加训练的速度 浪费资源 低效

能不能完美地解决输入变长这个问题,接下来要引出循环神经网络-RNN了。

2、RNN的基本结构

循环神经网络结构

如图所示,输入的Xt,经过A操作后会输出ht,在A框周围的线表示一种循环,将此次进过A的中间状态st,作为下一步Xt+1的额外输入。而下次输入的Xt+1和此次的Xt使用同样的激活函数和参数。

拆开来看:


循环神经网络结构
带参数的循环神经网络结构

整个计算过程为下图:


循环神经网络计算过程

这样,不管输入的长度有多长,每次输入的Xt都经过同一组参数的循环神经网络,中间维持的隐藏层h即为试图包含整个句子的所有信息的一个状态值。每个输入对应的输出值即为此次的预测值。

3、参数量

计算参数量得从两个大的步骤来看,第一步是通过隐藏层h,计算此次的中间状态ht时的参数量,有关联的是U、W,假设维护中间转态ht的W为32层的隐含层网络,则W的参数为 32 * 32,输入的xt的embedding的维度为16维,则U的参数为 16 * 32 ,偏置b 为 32;第二步输出o,中间维护的状态W大小为 32 * 32,如果输出10个类别,则V的参数为 32 * 10,偏置b 为 10。

使用TensorFlow2.0 ,调用rnn:

embedding_dim = 16 #词语embedding的维度
batch_size = 512 #批次取多少条数据
vocab_size = 10000 #词表大小
max_length = 500 # 句子最长的长度

# 单层rnn 
single_rnn_model = keras.models.Sequential([
    keras.layers.Embedding(vocab_size, embedding_dim,
                           input_length = max_length),
    keras.layers.SimpleRNN(units = 32, return_sequences = False), 
    # return_sequences 是否每次调用隐含层都需要输出  False-最后在输出一个值  TRUE-每次都输出一个值
    keras.layers.Dense(64, activation = 'relu'),
    keras.layers.Dense(1, activation='sigmoid'),
])

single_rnn_model.summary()
single_rnn_model.compile(optimizer = 'adam',
                         loss = 'binary_crossentropy',
                         metrics = ['accuracy'])

参数数目:

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding_2 (Embedding)      (None, 500, 16)           160000    
_________________________________________________________________
simple_rnn_3 (SimpleRNN)     (None, 32)                1568      
_________________________________________________________________
dense_4 (Dense)              (None, 64)                2112      
_________________________________________________________________
dense_5 (Dense)              (None, 1)                 65        
=================================================================
Total params: 163,745
Trainable params: 163,745
Non-trainable params: 0
_________________________________________________________________

4、参考资料

  • 深度学习-RNN-循环神经网络

  • 全面解析RNN,LSTM,Seq2Seq,Attention注意力机制

  • 深入理解 Embedding层的本质

你可能感兴趣的:(初识循环神经网络)