理解循环神经网络

理解循环神经网络

之前有一篇文章已经初步介绍过RNN的原理,里面其实已经介绍的比较清晰易懂了,这篇文章再来回顾和拓展一下:https://forchenxi.github.io/2021/04/23/nlp-rnn/

首先要知道RNN是一个带有内部环的神经网络,上面的这篇文章中的图描述的更形象,这里再来简单回顾下,使用tensorflow来实现(实际也是用keras来实现的)。

SimpleRNN

RNN基本计算过程

这张图中为了让大家看到RNN网络的计算过程,没有展现出RNN网络的内部循环,但是各个参数的含义表示的非常清楚。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import tensorflow as tf

# 这里随机生成一个3*2的矩阵,前面的1表示样本数量(表示本批次只有一个样本)
# 输出数据的第一维与这里样本数量一致
# 3*2可以理解为一个文本句子的向量表示,有三个单词,每个单词的的向量长度为2
x = tf.random.normal((1, 3, 2))

# 这里的4可以理解为权重向量的长度(上面的图上有标注出来),最后输出张量的尺寸也与此参数有关
layer = tf.keras.layers.SimpleRNN(4, input_shape=(3, 2))
output = layer(x)

print(output.shape)

print(output)

(1, 4)
tf.Tensor([[0.8968392 0.53277504 0.07782626 0.42022803]], shape=(1, 4), dtype=float32)

这里最后输出只有一个长度为4的向量,而RNN在实际计算时是每个单词都计算了一遍,所以实际计算过程得到了3个长度为4的向量,上篇文章中也有提到是通过return_sequences这个参数来控制的。

RNN的输出

RNN的输出分为多对一(N vs 1)、多对多(N vs N)和一对多(1 vs N)三种

上面的代码是单输出形式,多输出的代码如下:

1
2
3
4
5
6
7
8
x = tf.random.normal((1, 3, 2))

layer = tf.keras.layers.SimpleRNN(4, input_shape=(3, 2), return_sequences=True)
output = layer(x)

print(output.shape)

(1, 3, 4)

代码理解图

上面仅是得到了每个时间步的张量,还可以通过添加输层出来获取输出

1
2
3
4
model = tf.keras.Sequential()
model.add(tf.keras.layers.SimpleRNN(4, input_shape=(3, 2),
return_sequences=True))
model.add(tf.keras.layers.TimeDistributed(tf.keras.layers.Dense(4, activation='softmax')))

另外也可以将多个RNN层叠加在一起

1
2
3
model = tf.keras.Sequential()
model.add(tf.keras.layers.SimpleRNN(4, input_shape=(3, 2), return_sequences=True))
model.add(tf.keras.layers.SimpleRNN(4))

添加embedding层

这里的词向量是随机矩阵,直接输入到RNN中,其实还可以再此之前插入一个embedding层

1
2
3
4
model = tf.keras.Sequential()
# embedding层的shape与RNN的输入shape保持一致
model.add(tf.keras.layers.Embedding(3, 2))
model.add(tf.keras.layers.SimpleRNN(4, input_shape=(3, 2)))

关于embedding层的原理和使用方法,在这篇博客中也有介绍

https://forchenxi.github.io/2021/03/15/nlp-vectorize/

双向RNN

双向的RNN实际上就是将一个前向的RNN和一个后向的RNN在每个时间步得到的状态值拼接在一起作为总的状态。

1
2
3
4
5
6
model = tf.keras.Sequential()
model.add(tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(10, return_sequences=True), input_shape=(5, 10)))
model.add(tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(10)))
model.add(tf.keras.layers.Dense(5))
model.add(tf.keras.layers.Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')

这里实际是用的LSTM网络