十五、循环神经网络

目前你见过的所有神经网络(比如密集连接网络和卷积神经网络)都有一个主要特点,那就是它们都没有记忆。它们单独处理每个输入,在输入与输入之间没有保存任何状态。

你在 IMDB 示例中就是这么做的:将全部电影评论转换为一个大向量,然后一次性处理。这种网络叫作前馈网络(feedforward network)。
与此相反,当你在阅读这个句子时,你是一个词一个词地阅读(或者说,眼睛一次扫视一次扫视地阅读),同时会记住之前的内容。这让你能够动态理解这个句子所传达的含义。生物智能以渐进的方式处理信息,同时保存一个关于所处理内容的内部模型,这个模型是根据过去的信息构建的,并随着新信息的进入而不断更新。
循环神经网络(RNN,recurrent neural network)采用同样的原理,它处理序列的方式是,遍历所有序列元素,并保存一个状态(state),其中包含与已查看内容相关的信息。
在这里插入图片描述

简单 RNN 的 Numpy 实现

import numpy as np
timesteps = 100 输入序列的时间步数
input_features = 32 输入序列的时间步数
output_features = 64 输入序列的时间步数
inputs = np.random.random((timesteps, input_features)) 输入数据:随机噪声
state_t = np.zeros((output_features,)) 初始状态:全零向量
创建随机的权重矩阵
W = np.random.random((output_features, input_features)) 
U = np.random.random((output_features, output_features))
b = np.random.random((output_features,))
successive_outputs = []
for input_t in inputs: input_t 是形状为 (input_features,) 的向量
 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.stack(successive_outputs, axis=0)最终输出是一个形状为 (timesteps, output_features) 的二维张量

总之,RNN 是一个 for 循环,它重复使用循环前一次迭代的计算结果,仅此而已。
在这里插入图片描述

Keras 中的循环层

from keras.layers import SimpleRNN

SimpleRNN 层能够像其他 Keras 层一样处理序列批量,而不是像 Numpy 示例那样只能处理单个序列。因此,它接收形状为 (batch_size, timesteps, input_features) 的输入,而不是 (timesteps, input_features)。

Keras 中的所有循环层一样,SimpleRNN 可以在两种不同的模式下运行:一种是返回每个时间步连续输出的完整序列,即形状为 (batch_size, timesteps, output_features)的三维张量;另一种是只返回每个输入序列的最终输出,即形状为 (batch_size, output_features) 的二维张量。这两种模式由 return_sequences 这个构造函数参数来控制。

使用 SimpleRNN 的例子,它只返回最后一个时间步的输出

>>> from keras.models import Sequential
>>> from keras.layers import Embedding, SimpleRNN
>>> model = Sequential()
>>>> model.add(Embedding(10000, 32))
>>> model.add(SimpleRNN(32))
>>> model.summary()
_________________________________________________________________
Layer (type) Output Shape Param # 
=================================================================
embedding_22 (Embedding) (None, None, 32) 320000 
_________________________________________________________________
simple_rnn_10 (SimpleRNN) (None, 32) 2080 
=================================================================
Total params: 322,080
Trainable params: 322,080
Non-trainable params: 0

返回完整的状态序列

>>> model = Sequential()
>>> model.add(Embedding(10000, 32))
>>> model.add(SimpleRNN(32, return_sequences=True))
>>> model.summary() 
_________________________________________________________________
Layer (type) Output Shape Param # 
=================================================================
embedding_23 (Embedding) (None, None, 32) 320000 
_________________________________________________________________
simple_rnn_11 (SimpleRNN) (None, None, 32) 2080 
=================================================================
Total params: 322,080
Trainable params: 322,080
Non-trainable params: 0

为了提高网络的表示能力,将多个循环层逐个堆叠有时也是很有用的。在这种情况下,你
需要让所有中间层都返回完整的输出序列。

>>> model = Sequential()
>>> model.add(Embedding(10000, 32))
>>> model.add(SimpleRNN(32, return_sequences=True))
>>> model.add(SimpleRNN(32, return_sequences=True))
>>> model.add(SimpleRNN(32, return_sequences=True))
>>> model.add(SimpleRNN(32)) 
>>> model.summary() 
_________________________________________________________________
Layer (type) Output Shape Param # 
=================================================================
embedding_24 (Embedding) (None, None, 32) 320000 
_________________________________________________________________
simple_rnn_12 (SimpleRNN) (None, None, 32) 2080 
_________________________________________________________________
simple_rnn_13 (SimpleRNN) (None, None, 32) 2080 
_________________________________________________________________
simple_rnn_14 (SimpleRNN) (None, None, 32) 2080 
_________________________________________________________________
simple_rnn_15 (SimpleRNN) (None, 32) 2080 
=================================================================
Total params: 328,320
Trainable params: 328,320
Non-trainable params: 0

IMDB 电影评论分类

from keras.datasets import imdb
from keras.preprocessing import sequence
max_features = 10000 
maxlen = 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 sequences')
print(len(input_test), 'test sequences')
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)

用一个 Embedding 层和一个 SimpleRNN 层来训练一个简单的循环网络

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)

显示训练和验证的损失和精度
在这里插入图片描述

理解 LSTM 层和 GRU 层

SimpleRNN 并不是 Keras 中唯一可用的循环层,还有另外两个:LSTM 和 GRU。
LSTM 层是 SimpleRNN 层的一种变体,它增加了一种携带信息跨越多个时间步的方法。

使用 Keras 中的 LSTM 层

from keras.layers import LSTM
model = Sequential()
model.add(Embedding(max_features, 32))
model.add(LSTM(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)

循环神经网络的高级用法

  • 循环 dropout(recurrent dropout)。这是一种特殊的内置方法,在循环层中使用 dropout
    来降低过拟合。
  • 堆叠循环层(stacking recurrent layers)。这会提高网络的表示能力(代价是更高的计算负
    荷)。
  • 双向循环层(bidirectional recurrent layer)。将相同的信息以不同的方式呈现给循环网络,
    可以提高精度并缓解遗忘问题。

用卷积神经网络处理序列

理解序列数据的一维卷积

前面介绍的卷积层都是二维卷积,从图像张量中提取二维图块并对每个图块应用相同的变换。按照同样的方法,你也可以使用一维卷积,从序列中提取局部一维序列段(即子序列)。
在这里插入图片描述

序列数据的一维池化

你已经学过二维池化运算,比如二维平均池化和二维最大池化,在卷积神经网络中用于对图像张量进行空间下采样。一维也可以做相同的池化运算:从输入中提取一维序列段(即子序列),然后输出其最大值(最大池化)或平均值(平均池化)。与二维卷积神经网络一样,该运算也是用于降低一维输入的长度(子采样)。

实现一维卷积神经网络

Keras 中的一维卷积神经网络是 Conv1D 层,其接口类似于 Conv2D。它接收的输入是形状为 (samples, time, features) 的三维张量,并返回类似形状的三维张量。卷积窗口是时间轴上的一维窗口(时间轴是输入张量的第二个轴)。
IMDB 情感分类任务

from keras.datasets import imdb
from keras.preprocessing import sequence
max_features = 10000
max_len = 500
print('Loading data...')
(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=max_features)
print(len(x_train), 'train sequences')
print(len(x_test), 'test sequences')
print('Pad sequences (samples x time)')
x_train = sequence.pad_sequences(x_train, maxlen=max_len)
x_test = sequence.pad_sequences(x_test, maxlen=max_len)
print('x_train shape:', x_train.shape)
print('x_test shape:', x_test.shape)
from keras.models import Sequential
from keras import layers
from keras.optimizers import RMSprop
model = Sequential()
model.add(layers.Embedding(max_features, 128, input_length=max_len))
model.add(layers.Conv1D(32, 7, activation='relu'))
model.add(layers.MaxPooling1D(5))
model.add(layers.Conv1D(32, 7, activation='relu'))
model.add(layers.GlobalMaxPooling1D())
model.add(layers.Dense(1))
model.summary()
model.compile(optimizer=RMSprop(lr=1e-4),
 loss='binary_crossentropy',
 metrics=['acc'])
history = model.fit(x_train, y_train,
 epochs=10,
 batch_size=128,
 validation_split=0.2)
  • 16
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值