前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >RNN,具有记忆功能神经网络的理解与实现

RNN,具有记忆功能神经网络的理解与实现

作者头像
望月从良
发布2018-09-29 15:56:55
1.1K0
发布2018-09-29 15:56:55
举报
文章被收录于专栏:Coding迪斯尼Coding迪斯尼

我们当前掌握的网络类型,统称为feed forward网络。这种网络的特点是,当我们把很多条数据输入网络进行训练时,网络没有“记忆性”,也就是网络认为前一条输入的数据与下一条输入的数据之间没有任何联系。然而在实际运用中,输入的数据间往往存在着强联系,特别是在自然语言处理中。

假设我们给网络输入“中华人民共和国”一词,我们第一次传给网络“中华”,第二次传给“人民”,第三次传入”共和国“,显然这三次输入数据存在着非常紧密的联系,但是我们现在的网络对数据处理方式并没有考虑到前后数据间可能存在着相关性,而这种相关性往往能极大的提高网络对数据的处理效率以及准确率,因此我们在本节将引入一种具备新特性的神经网络叫recurrent neural network,这种网络能够将前后输入数据关联起来,从而大大提升网络对数据模式的识别。

RNN的基本结构如下:

数据输入网络,网络对数据进行处理,然后网络使用一组叫做”state”的参数来记录下当前数据的特性,等到下一组数据输入网络时,网络对数据的处理,会结合上一次留下来的”state”参数组一同对数据进行处理,每次对数据进行处理后,“state”对应的参数组都会进行相应更新,然后参与下一次网络对新输入数据的处理。我们可以用一组伪码来表示RNN网络的运行逻辑:

代码语言:javascript
复制
state_t = 0  #状态参数在初始时为0
for input_t in input_sequences:  #不断的将数据输入网络
    #W对应网络链路参数,  U是一个参数矩阵,用于与状态变量state_t相互作用,b是一维向量
    output_t = activation(dot(W, input_t) + dot(U, state_t)+b)  
    state_t = output_t  #更新state_t参数,以便参与下一条数据处理

我们可以再将上面伪码展开,以便加深对RNN结构和处理流程的理解:

代码语言:javascript
复制
import numpy as np

timesteps = 100  #总共100条训练数据
input_features = 32 #每条数据有32个参数
output_features = 64 #网络读取数据后输出含有64个参数的向量

inputs = np.random.random((timestep, input_features))
state_t = np.zeros((output_features))  #先把状态参数初始化为0

W = np.random.random((input_features, output_features))
U = np.random.random((output_features, output_features))
b = np.random.random((output_features,))

successive_outputs = []
for input_t in inputs:
    #处理输入数据
    output_t = np.tanh(np.dot(W, input_t) + np.dot(U, state_t) + b)
    #记录当前数据处理结果
    successive_outputs.append(output_t)
    #更新状态变量以便参与下次数据处理
    state_t = output_t

final_output_sequence = np.concatenate(successive_outputs, axis = 0)

RNN本质上就是一个for循环,每次循环在处理输入数据时,利用当前数据去更新一个状态变量,这个状态变量相当于对当前数据的“记忆”,它将把当前数据携带的信息代入到下一次的数据处理过程中,我们可以从下面的结构图来理解RNN:

接下来我们看看keras是如何支持CNN的,keras框架提供一种简单的RNN网络层,如下代码所示:

代码语言:javascript
复制
from keras.layers import SimpleRNN

上面导入的SimpleRNN网络层有一个特点是,他必须同时接收一批输入,而不能像我们以为那样一条条的把数据传入网络,而是要一下子把一批数据传进去。也就是我们在使用SimpleRNN层时,需要把数据集合成一个3维向量(batch_size, timesteps, inputput_features),当数据处理完毕后,它可以一下子输出一批结果例如(batch_size, timesteps, output_features),要不然就输出最后一条结果(batch_size, output_features)。我们看一个具体例子,下面代码使得网络输出最后一条结果:

代码语言:javascript
复制
from keras.models import Sequential
from keras.layers import Embedding, SimpleRNN
model = Sequential()
model.add(Embedding(10000, 32))
model.add(SimpleRNN(32))
model.summary()

而下面代码使得网络一下子输出一批结果:

代码语言:javascript
复制
from keras.models import Sequential
from keras.layers import Embedding, SimpleRNN
model = Sequential()
model.add(Embedding(10000, 32))
model.add(SimpleRNN(32, return_sequences=True))
model.summary()

上一节我们使用预处理单词向量在影评的情绪分析中出现了严重的过度拟合,现在我们使用RNN到影评情绪分析上看看效果如何,首先我们先加载数据。

代码语言:javascript
复制
from keras.datasets import imdb
from keras.preprocessing import sequence

max_features = 10000 #只考虑最常使用的前一万个单词
maxlen = 500 #一篇文章只考虑最多500个单词
batch_size = 32
print("Loading data....")
(input_train, y_train), (input_test, y_test) = imdb.load_data(num_words=max_features)
print(len(input_train), 'train sequence')
print(len(input_test), 'test sequence')

print('Pad sequences (samples x time)')
input_train = sequence.pad_sequences(input_train, maxlen = maxlen)
input_test = sequence.pad_sequences(input_test, maxlen=maxlen)
print('input_train shape:', input_train.shape)
print('input_test shape: ', input_test.shape)

接着我们构造一个RNN网络,把数据输入网络进行训练:

代码语言:javascript
复制
from keras.layers import Dense
model = Sequential()
model.add(Embedding(max_features, 32))
model.add(SimpleRNN(32))
model.add(Dense(1, activation='sigmoid'))

model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['acc'])
history = model.fit(input_train, y_train, epochs = 10, batch_size = 128, validation_split=0.2)

上面代码运行后,我们把网络训练的结果绘制出来:

代码语言:javascript
复制
import matplotlib.pyplot as plt

acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']

epochs = range(1, len(acc) + 1)
plt.plot(epochs, acc, 'bo', label = 'Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.legend()
plt.figure()

plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and Validation loss')
plt.legend()

plt.show()

上面代码运行后,得到结果如下:

从第一幅图我们看到,网络对校验数据的准确率与对训练数据的准确率并没有分叉,因此相比于上一节,过度拟合得到了比较好的处理。对校验数据的检测中,最高准确率为85%,比我们以前采用的普通网络模型效果还要差一些。其中原因在于,我们只考虑影评前500个单词,这个量太小,但我们又不能简单的把这个限制增大,因为SimpleRNN无法记忆过长的单词串,下一节我们将引入新类型的记忆性网络以便处理我们现在遇到的问题。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-09-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Coding迪斯尼 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
NLP 服务
NLP 服务(Natural Language Process,NLP)深度整合了腾讯内部的 NLP 技术,提供多项智能文本处理和文本生成能力,包括词法分析、相似词召回、词相似度、句子相似度、文本润色、句子纠错、文本补全、句子生成等。满足各行业的文本智能需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档