我们当前掌握的网络类型,统称为feed forward网络。这种网络的特点是,当我们把很多条数据输入网络进行训练时,网络没有“记忆性”,也就是网络认为前一条输入的数据与下一条输入的数据之间没有任何联系。然而在实际运用中,输入的数据间往往存在着强联系,特别是在自然语言处理中。
假设我们给网络输入“中华人民共和国”一词,我们第一次传给网络“中华”,第二次传给“人民”,第三次传入”共和国“,显然这三次输入数据存在着非常紧密的联系,但是我们现在的网络对数据处理方式并没有考虑到前后数据间可能存在着相关性,而这种相关性往往能极大的提高网络对数据的处理效率以及准确率,因此我们在本节将引入一种具备新特性的神经网络叫recurrent neural network,这种网络能够将前后输入数据关联起来,从而大大提升网络对数据模式的识别。
RNN的基本结构如下:
屏幕快照 2018-09-04 下午4.34.28.png数据输入网络,网络对数据进行处理,然后网络使用一组叫做”state"的参数来记录下当前数据的特性,等到下一组数据输入网络时,网络对数据的处理,会结合上一次留下来的"state"参数组一同对数据进行处理,每次对数据进行处理后,“state"对应的参数组都会进行相应更新,然后参与下一次网络对新输入数据的处理。我们可以用一组伪码来表示RNN网络的运行逻辑:
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结构和处理流程的理解:
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:
屏幕快照 2018-09-04 下午4.58.23.png接下来我们看看keras是如何支持CNN的,keras框架提供一种简单的RNN网络层,如下代码所示:
from keras.layers import SimpleRNN
上面导入的SimpleRNN网络层有一个特点是,他必须同时接收一批输入,而不能像我们以为那样一条条的把数据传入网络,而是要一下子把一批数据传进去。也就是我们在使用SimpleRNN层时,需要把数据集合成一个3维向量(batch_size, timesteps, inputput_features),当数据处理完毕后,它可以一下子输出一批结果例如(batch_size, timesteps, output_features),要不然就输出最后一条结果(batch_size, output_features)。我们看一个具体例子,下面代码使得网络输出最后一条结果:
from keras.models import Sequential
from keras.layers import Embedding, SimpleRNN
model = Sequential()
model.add(Embedding(10000, 32))
model.add(SimpleRNN(32))
model.summary()
而下面代码使得网络一下子输出一批结果:
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到影评情绪分析上看看效果如何,首先我们先加载数据。
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网络,把数据输入网络进行训练:
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)
上面代码运行后,我们把网络训练的结果绘制出来:
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()
上面代码运行后,得到结果如下:
屏幕快照 2018-09-05 下午5.19.21.png
从第一幅图我们看到,网络对校验数据的准确率与对训练数据的准确率并没有分叉,因此相比于上一节,过度拟合得到了比较好的处理。对校验数据的检测中,最高准确率为85%,比我们以前采用的普通网络模型效果还要差一些。其中原因在于,我们只考虑影评前500个单词,这个量太小,但我们又不能简单的把这个限制增大,因为SimpleRNN无法记忆过长的单词串,下一节我们将引入新类型的记忆性网络以便处理我们现在遇到的问题。
更多技术信息,包括操作系统,编译器,面试算法,机器学习,人工智能,请关照我的公众号:
这里写图片描述
网友评论