本站内容均来自兴趣收集,如不慎侵害的您的相关权益,请留言告知,我们将尽快删除.谢谢.
携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第7天,点击查看活动详情
在上一篇文章中,我们介绍了数据padding,Embedding与变长输入的处理的问题,并且使用Embedding解决文本分类的问题
今天我们来解释为什幺需要循环神经网络和循环神经网络的结构,并且使用循环神经网络来进行文本分类。
2.1 序列问题
2.1.1 为什幺需要循环神经网络——合并+padding的缺点?
信息丢失
多个embedding合并
Pad噪音、无主次
无效计算太多、抵消
太多的padding
2.1.2 为什幺需要循环神经网络——序列式问题
普通神经网络
1对多:图片生成描述
多对1:文本分类(文本情感分析)
多对多:encoding-decoding机器翻译
实时多对多:视频解说
2.1.3 循环神经网络
维护一个状态作为下一步的额外输出
每一步使用同样的激活函数和参数
最简单的循环神经网络
循环神经网络的列子
2.2 循环神经网络文本分类
2.2.1 定义一个1层单层单向的rnn,2层全连接层的模型
embedding_dim = 16 batch_size = 512 single_rnn_model = keras.models.Sequential([ # 1. define matrix: [vocab_size, embedding_dim] # 2. [1,2,3,4..], max_length * embedding_dim # 3. batch_size * max_length * embedding_dim keras.layers.Embedding(vocab_size, embedding_dim, input_length = max_length), # return_sequences: 决定你返回的输出(False)是最后一步的输出,还是所有的输出 keras.layers.SimpleRNN(units = 64, return_sequences = False), 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'])
Model: "sequential" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= embedding (Embedding) (None, 500, 16) 160000 _________________________________________________________________ simple_rnn (SimpleRNN) (None, 64) 5184 _________________________________________________________________ dense (Dense) (None, 64) 4160 _________________________________________________________________ dense_1 (Dense) (None, 1) 65 ================================================================= Total params: 169,409 Trainable params: 169,409 Non-trainable params: 0
训练模型:
history_single_rnn = single_rnn_model.fit( train_data, train_labels, epochs = 30, batch_size = batch_size, validation_split = 0.2)
在训练30次之后,发现accuracy是0.4990,这对于一个二分类问题来说是没有进展的,因为做随机猜测的话,accuracy也有50%。
这说明普通的单层rnn并没有效果。
打印学习曲线
def plot_learning_curves(history, label, epochs, min_value, max_value): data = {} data[label] = history.history[label] data['val_'+label] = history.history['val_'+label] pd.DataFrame(data).plot(figsize=(8, 5)) plt.grid(True) plt.axis([0, epochs, min_value, max_value]) plt.show() plot_learning_curves(history_single_rnn, 'accuracy', 30, 0, 1) plot_learning_curves(history_single_rnn, 'loss', 30, 0, 1)
运行结果:
在测试集上的效果:
single_rnn_model.evaluate( test_data, test_labels, batch_size = batch_size, verbose = 0)
运行结果:
[0.7533659934997559, 0.5001599788665771]
2.2.2 实现一个双层双向的rnn,2层全连接层的模型
只需要使用Bidirectional对RNN进行一个封装,封装完之后就是一个双向的RNN
embedding_dim = 16 batch_size = 512 model = keras.models.Sequential([ # 1. define matrix: [vocab_size, embedding_dim] # 2. [1,2,3,4..], max_length * embedding_dim # 3. batch_size * max_length * embedding_dim keras.layers.Embedding(vocab_size, embedding_dim, input_length = max_length), keras.layers.Bidirectional( keras.layers.SimpleRNN( units = 64, return_sequences = True)), # return_sequences改为True的原因:下一个RNN的输入是序列,而不是单个的输入 keras.layers.Bidirectional( keras.layers.SimpleRNN( units = 64, return_sequences = False)), keras.layers.Dense(64, activation = 'relu'), keras.layers.Dense(1, activation='sigmoid'), ]) model.summary() model.compile(optimizer = 'adam', loss = 'binary_crossentropy', metrics = ['accuracy'])
运行结果:
Model: "sequential" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= embedding (Embedding) (None, 500, 16) 160000 _________________________________________________________________ bidirectional (Bidirectional (None, 500, 128) 10368 _________________________________________________________________ bidirectional_1 (Bidirection (None, 128) 24704 _________________________________________________________________ dense (Dense) (None, 64) 8256 _________________________________________________________________ dense_1 (Dense) (None, 1) 65 ================================================================= Total params: 203,393 Trainable params: 203,393 Non-trainable params: 0 _________________________________________________________________
训练模型:
history = model.fit( train_data, train_labels, epochs = 30, batch_size = batch_size, validation_split = 0.2)
可以发现,在训练集上的accuracy是1.0,但是在验证集上的accuracy只有0.5572,也只比单层RNN好了一点点
打印学习曲线:
plot_learning_curves(history, 'accuracy', 30, 0, 1) plot_learning_curves(history, 'loss', 30, 0, 3.8)
运行结果:
发现在训练集上accuracy非常好,但是在验证集上的accuracy不太好,这说明模型在训练集上过拟合了
这次的模型定义的是一个双层双向的RNN,模型太复杂了
2.2.3 实现一个单层双向的rnn,2层全连接层的模型
embedding_dim = 16 batch_size = 512 bi_rnn_model = keras.models.Sequential([ # 1. define matrix: [vocab_size, embedding_dim] # 2. [1,2,3,4..], max_length * embedding_dim # 3. batch_size * max_length * embedding_dim keras.layers.Embedding(vocab_size, embedding_dim, input_length = max_length), keras.layers.Bidirectional( keras.layers.SimpleRNN( units = 32, return_sequences = False)), keras.layers.Dense(32, activation = 'relu'), keras.layers.Dense(1, activation='sigmoid'), ]) bi_rnn_model.summary() bi_rnn_model.compile(optimizer = 'adam', loss = 'binary_crossentropy', metrics = ['accuracy'])
运行结果:
Model: "sequential" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= embedding (Embedding) (None, 500, 16) 160000 _________________________________________________________________ bidirectional (Bidirectional (None, 64) 3136 _________________________________________________________________ dense (Dense) (None, 32) 2080 _________________________________________________________________ dense_1 (Dense) (None, 1) 33 ================================================================= Total params: 165,249 Trainable params: 165,249 Non-trainable params: 0 _________________________________________________________________
训练模型:
history = bi_rnn_model.fit( train_data, train_labels, epochs = 30, batch_size = batch_size, validation_split = 0.2)
可以发现:在训练集上的accuracy达到了1.0,在测试集上的accur达到了0.7888,比双层双向的模型要好很多
打印学习曲线:
plot_learning_curves(history, 'accuracy', 30, 0, 1.1) plot_learning_curves(history, 'loss', 30, 0, 2.5)
运行结果:
虽然在验证集上的效果要好很多,但是依然由过拟合的现象存在。
在测试集上进行评估:
bi_rnn_model.evaluate(test_data, test_labels, batch_size = batch_size, verbose = 0)
运行结果:
[1.404372215270996, 0.7716000080108643]
可以发现:训练集上的accuracy是0.7716,相较于之前的简单模型的accur是0.85,那幺这是说明循环神经网络比普通的神经网络还要弱吗?
可以仔细看一下loss的曲线图,发现循环神经网络在训练第5次的时候,val_loss急剧上升,而在普通神经网络中在训练第10次的时候,val_loss急剧上升,这说明循环神经网络的过拟合更加明显,它的过拟合更加明显反而说明了这个模型更加强大。
在搭建模型的过程中,使用了一种方法来缓解过拟合,就是降低模型尺寸,把两层循环神经网络变成单层的;在搭建模型的时候,还有其他手段来缓解过拟合,比如dropout,正则化项等。
Be First to Comment