RNN模型与NLP应用(4)LSTM模型

前言

这篇主要讲述LSTM的基本过程以及实现代码,LSTM是一种RNN模型,是对Simple RNN的改进
如下图,LSTM有四个参数矩阵
LSTM避免梯度消失问题,可以有更长的记忆请添加图片描述

LSTM基础知识

传输带记为向量c,解决梯度消失问题,过去的信息通过传输带直接送到下一个时刻,不会发生太多的变化请添加图片描述
LSTM中有很多Gate,可以有选择的让信息通过
sigmoid函数
sigmoid作用到向量a的每一个元素上,将每一个元素都压到0-1之间
算出f向量之后,计算传输带向量c和遗忘门向量f的Elementwise multiplication

请添加图片描述
遗忘门f
有选择的让传输带c的值通过,假如f的一个元素是0,那么c对应的元素就不能通过对应的输出是0,如果是1,那么c对应的元素全部通过,对应输出是c的本身
在这里插入图片描述
遗忘门
f t f_t ft是上一个状态 h t − 1 h_{t-1} ht1与当前输入x的函数,状态 h t − 1 h_{t-1} ht1与输入 x t x_t xt做串联操作得到更高维的向量,然后算矩阵Wf与这个向量的乘积,得到一个向量,再用sigmoid的函数得到向量 f t f_t ft。` f t f_t ft的每一个元素都介于0和1之间。
遗忘门有一个参数矩阵$w_f$,需要通过反向传播从训练数据学习

请添加图片描述
输入门
把旧的状态 h t − 1 h_{t-1} ht1与新的输入 x t x_t xt做串联,得到更高维的向量 然后算矩阵 W i W_i Wi与这个向量的乘积得到一个向量,最后再用sigmoid函数得到向量 i t i_t it i t i_t it的每一个元素都介于0和1之间。
在这里插入图片描述
这里的激活函数是双曲正切函数
把旧状态 h t − 1 h_{t-1} ht1,与新输入xt做串联操作,再乘以参数矩阵。区别在于激活函数不是Sigmoid,而是双曲正切函数 t a n h tan_h tanh,所以算出的向量的元素都介于[-1,1]之间,同时如图可知计算该向量 c t ’ c_t’ ct也需要单独的一个参数矩阵,记作 w c w_c wc

请添加图片描述
更新 c t c_t ct的值
用遗忘门 f t f_t ft和传送带旧的值 c t − 1 c_{t-1} ct1算Elementwise multiplication
计算输入门 i t i_t it和新的值 c t ’ c_t’ ct的Elementwise multiplication
请添加图片描述
计算输出门向量 O t O_t Ot
旧的状态 h t − 1 h_{t-1} ht1与新的输入 x t x_t xt做串联,得到更高维的向量,然后算矩阵 w o w_o wo与这个向量的乘积得到一个向量,最后再用sigmoid函数得到向量 O t O_t Ot
输出门也有自己的参数矩阵 w 0 w_0 w0

请添加图片描述
计算状态向量 h t h_t ht
对传输带 c t c_t ct的每一个元素求双曲正切函数,把元素全都压到[-1,1]的区间,然后求这两个向量的Elementwise multiplication
请添加图片描述
Lstm参数
LSTM有遗忘门,输入门,new value以及输出门,这四个模块都有各自的参数矩阵w,所以一共有四个参数矩阵
请添加图片描述
using keras
请添加图片描述
总结

请添加图片描述
代码实现
只需将上篇的simple RNN改成LSTM即可
from keras.layers import LSTM, Dense, Embedding

'数据集读取与预处理'
# 此处使用Keras库自带函数进行简洁实现(从零开始实现请看上一节)
# 使用keras的embedding层处理文字数据(同样使用imdb数据集)

from keras.datasets import imdb
from keras import preprocessing

max_feature = 10000  # 词汇量(作为特征的单词个数)
maxlen = 500  # 在500个单词以后截断文本

(input_train, y_train), (input_test, y_test) = imdb.load_data(num_words=max_feature)
# y_train、y_test分别表示训练集和测试集的标签
# max_words=10000:只考虑数据集中前10000个最常见的单词
print(len(input_train), 'train sequences')
print(len(input_test), 'test sequences')

print('sequence 格式:(samples*time)')
input_train = preprocessing.sequence.pad_sequences(input_train, maxlen=maxlen)
input_test = preprocessing.sequence.pad_sequences(input_test, maxlen=maxlen)
# 此处相当于对齐序列(补0或者阶段评论)
print('input_train shape:', input_train.shape)
print('input_test shape:', input_test.shape)

'定于模型:Simple RNN'
from keras.models import Sequential     # 调入Sequential模型,按顺序搭建神经网络层
from keras.layers import LSTM, Dense, Embedding   # 各种层

'词嵌入操作:降低输入向量维度'
embedding_dim = 32
model = Sequential()
model.add(Embedding(max_feature, embedding_dim, input_length=maxlen))
# 第一层是Embedding层,设定字典里10000个单词,Embedding层的输出是个500×32的矩阵,
# 只考虑每条电影评论中最后的500个单词,每个单词用32维的向量来表示
# 参数矩阵在此的维度是320000,矩阵的参数根据设定的每个单词表示的向量(32)*字典词个数10000得到
'Simple RNN Layer'
state_dim = 32
model.add(LSTM(state_dim, return_state=False))
# return_state=False,不需要存储ht之前的状态

model.add(Dense(1, activation='sigmoid'))
# units :代表该层的输出维度或神经元个数,此处设定输出的维度为1
# activation=None:激活函数.但是默认 liner

'设定优化算法以及模型评价标准'
model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['accuracy'])
# optimizer: 优化器,loss:损失函数,metrics: 评价函数.
# 评价函数的结果不会用于训练过程中,可以传递已有的评价函数名称

'设置训练模型'
history = model.fit(
    input_train, y_train,
    epochs=10,
    batch_size=128,
    validation_split=0.2
)
# input_train:输入数据,y_train:标签,
# batch_size:整数,指定进行梯度下降时每个batch包含的样本数
# epochs:整数,训练终止时的epoch值
# validation_split:0~1之间的浮点数,用来指定训练集的一定比例数据作为验证集
model.summary()
'查看模型最终性能'
loss_and_acc = model.evaluate(input_test, y_test)
print('loss=' + str(loss_and_acc[0]))
print('acc=' + str(loss_and_acc[1]))
#loss=0.3974949774980545
#acc=0.86744



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值