一文搞懂循环神经网络(RNN)
RNN与传统神经网络
循环神经网络(RNN)是专门处理序列数据的神经网络。
传统的神经网络模型(左图),输入层(input layer)到隐藏层(hidden layer),隐藏层再到输出层(output layer),层与层之间是全连接的,但是隐藏层节点之间是无连接的。
循环神经网络(右图),隐藏层节点之间是有连接的。

RNN的基本结构

其中,右图圆形的箭头表示隐藏层的自连接。
在RNN中,每一层都共享参数U、V、W,降低了网络中需要学习的参数,提高学习效率。
输入单元(input units)记为:

隐藏单元(hidden units)记为:

输出单元(output units)记为:

RNN的计算过程

输入层: Xt{X}_{t}Xt表示时刻t的输入。
隐藏层: st=f(Uxt + Wst−1){s}_{t}=f(U{x}_{t}\, +\, W{s}_{t-1})st=f(Uxt+Wst−1) ,f是非线性激活函数,比如tanh。
输出层:ot=softmax( Vst){o}_{t}=softmax(\, V{s}_{t})ot=softmax(Vst)
其中tanh为双曲正切,公式为:

其曲线图如下所示:

softmax函数是归一化的指数函数,使每个元素的范围都在0到1之间 ,并且所有元素的和为1。其公式为:

zi{z}_{i}zi —— 第i个节点的输出值
C —— 输出节点的个数,即分类的类别个数。
Python案例
本案例参考《Python深度学习》温度预测问题:数据使用德国耶拿的马克思• 普朗克生物地球化学研究所的气象站记录,天气时间序列数据集 jena_climate_2009_2016。
在命令行输入如下命令下载数据:
wget https://s3.amazonaws.com/keras-datasets/jena_climate_2009_2016.csv.zip
若wget命令无法使用,可以去wget官网下载一个。
https://eternallybored.org/misc/wget/
选择32位/64位,下载ZIP/EXE,将下载下来的EXE文件放到C:\Windows\System32即可。
先来查看数据信息,这个数据集中,每10分钟记录14个不同的量(气温、气压、湿度、风向等),其中气温T(degC)数据服从正态分布——

我们基于这个数据集来构建模型,输入最近几天的数据点,预测24小时之后的气温。
python代码:
import os
data_dir = 'E:\Tensorflow\code\data\jena_climate_2009_2016\jena_climate_2009_2016.csv'
file = open(data_dir) #打开文件,创建file对象,相关方法才可调用它进行读写
next(file) #返回文件的第二行,由于第一行是表头,从第二行开始是数据
data = file.read() #逐字节(字符)读取文件中的内容
file.close() #关闭已打开文件的
import numpy as np
lines = data.split('\n') #指定"\n"分隔符对字符串进行切片
#lines = lines[1:]
print(len(lines)) #420451
for i, line in enumerate(lines): #enumerate是枚举, i:0~len(lines)-1 line:每行元素
values = [float(x) for x in line.split(',')[1:]] #每个元素值从String转为float
float_data[i, :] = values #每行数据存入float_data
from matplotlib import pyplot as plt
temp = float_data[:,1] #温度(摄氏度)
plt.plot(range(len(temp)),temp) #两个参数分别是x轴数据和y轴数据
输出:

x轴为0~420450 ,y轴为对应时刻的温度。
查看一天、一周、一个月(30天)、一年温度数据分布:
def show(daynum,index):
plt.figure(figsize=(10,10))
plt.subplot(410 + index + 1)
plt.plot(range(daynum*144), temp[:daynum*144])
title = str(daynum)+"day"
plt.title(title)
plt.show
for index,daynum in enumerate([1,7,30,365]): #一天、一周、一个月(30天)、一年
show(daynum,index)
输出:

从结果可以看出,温度数据一天、一周数据较为分散,一个月以上的温度数据开始出现周期性。若推测未来几天的温度,可能会出现较大误差。
接下来对数据进行标准化处理,这里使用z-score标准化(标准差标准化法),该方法通常在最大值和最小值未知,或者有超出取值范围的离群数值的情况使用。
它基于原始数据的均值和标准差进行标准化,计算公式为新数据 = (原始数据 - 均值)/ 标准差。
其中,axis=0 表示纵轴平均,输出的是格式(1,x)的格式,axis=1表示横轴的平均,输出的是(x,1)的格式。
mean = float_data[:200000].mean(axis=0) #使用前200000个时间步作为训练数据
float_data -= mean
std = float_data[:200000].std(axis=0)
float_data /= std
构造generator函数,它是生成时间序列样本及其目标的生成器。它生成了一个元组(samples,targets),其中samples是输入数据的一个批量,targets是对应目标温度数组。
#data;标准化后的浮点数数据组成的原始数组
#lookback:时间步数量 =720 每一个时间步是10分钟 给定过去5天内的观测数据
#delay:目标是未来24小时之后的数据 =144
#min_index和max_index:data数组中的索引,用于界定需要抽取的时间步
#shuffle:False 按顺序抽取样本 True打乱样本
#batch_size:每个批量的样本数
#step:数据采样的周期(时间步) =6,每小时抽取一个数据点
def generator(data, lookback, delay, min_index, max_index,shuffle=False, batch_size=128, step=6):
if max_index is None:
max_index = len(data) - delay - 1
i = min_index + lookback
while 1:
if shuffle:
rows = np.random.randint(
min_index + lookback, max_index, size=batch_size)
else:
if i + batch_size >= max_index:
i = min_index + lookback
rows = np.arange(i, min(i + batch_size, max_index))
i += len(rows)
samples = np.zeros((len(rows),
lookback // step,
data.shape[-1]))
targets = np.zeros((len(rows),))
for j, row in enumerate(rows):
indices = range(rows[j] - lookback, rows[j], step)
samples[j] = data[indices]
targets[j] = data[rows[j] + delay][1]
yield samples, targets #yield类似return,带yield的函数是一个生成器而不是一个函数
使用generator函数来实例化三个生成器,分别用于训练、验证和测试,每个生成器分别读取原始数据不同的时间段。
lookback = 1440
step = 6
delay = 144
batch_size = 128
train_gen = generator(float_data, #训练集
lookback=lookback,
delay=delay,
min_index=0,
max_index=200000,
shuffle=True,
step=step,
batch_size=batch_size)
val_gen = generator(float_data, #验证集
lookback=lookback,
delay=delay,
min_index=200001,
max_index=300000,
step=step,
batch_size=batch_size)
test_gen = generator(float_data, #测试集
lookback=lookback,
delay=delay,
min_index=300001,
max_index=None,
step=step,
batch_size=batch_size)
val_steps = (300000 - 200001 - lookback) // batch_size
test_steps = (len(float_data) - 300001 - lookback)
预测24小时后的温度等于现在的温度,使用平均绝对误差(MAE)指标来评估这种方法。
def evaluate_naive_method():
batch_maes = []
for step in range(val_steps):
samples, targets = next(val_gen)
preds = samples[:, -1, 1]
mae = np.mean(np.abs(preds - targets))
batch_maes.append(mae)
print(np.mean(batch_maes))
evaluate_naive_method()
得到的MAE为0.2897,将平均绝对误差转化为摄氏度。0.2897×8.4804=2.45677188摄氏度,这个误差比较大。
应用
1.自动生成莎士比亚风格的句子
Tensorflow的官方教程里就有提到:
https://tensorflow.google.cn/tutorials/text/text_generation?hl=zh-cn
2.自动生成中文古诗
3.预测股票价格
4.语音识别
5.图像生成
…
更多推荐
所有评论(0)