深度学习|一文搞懂循环神经网络(RNN)

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

RNN的基本结构 深度学习|一文搞懂循环神经网络(RNN)
文章图片

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

隐藏单元(hidden units)记为:
深度学习|一文搞懂循环神经网络(RNN)
文章图片

输出单元(output units)记为:
深度学习|一文搞懂循环神经网络(RNN)
文章图片

RNN的计算过程 深度学习|一文搞懂循环神经网络(RNN)
文章图片

输入层:X t {X}_{t} Xt?表示时刻t的输入。
隐藏层:s t = f ( U x t ? + ? W s t ? 1 ) {s}_{t}=f(U{x}_{t}\, +\, W{s}_{t-1}) st?=f(Uxt?+Wst?1?) ,f是非线性激活函数,比如tanh。
输出层: o t = s o f t m a x ( ? V s t ) {o}_{t}=softmax(\, V{s}_{t}) ot?=softmax(Vst?)
其中tanh为双曲正切,公式为:
【深度学习|一文搞懂循环神经网络(RNN)】深度学习|一文搞懂循环神经网络(RNN)
文章图片

其曲线图如下所示:
深度学习|一文搞懂循环神经网络(RNN)
文章图片

softmax函数是归一化的指数函数,使每个元素的范围都在0到1之间 ,并且所有元素的和为1。其公式为:
深度学习|一文搞懂循环神经网络(RNN)
文章图片

z i {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)数据服从正态分布——
深度学习|一文搞懂循环神经网络(RNN)
文章图片

我们基于这个数据集来构建模型,输入最近几天的数据点,预测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 = https://www.it610.com/article/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)-1line:每行元素 values = [float(x) for x in line.split(',')[1:]]#每个元素值从String转为float float_data[i, :] = values#每行数据存入float_datafrom matplotlib import pyplot as plt temp = float_data[:,1]#温度(摄氏度) plt.plot(range(len(temp)),temp)#两个参数分别是x轴数据和y轴数据

输出:
深度学习|一文搞懂循环神经网络(RNN)
文章图片

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.showfor index,daynum in enumerate([1,7,30,365]): #一天、一周、一个月(30天)、一年 show(daynum,index)

输出:
深度学习|一文搞懂循环神经网络(RNN)
文章图片

从结果可以看出,温度数据一天、一周数据较为分散,一个月以上的温度数据开始出现周期性。若推测未来几天的温度,可能会出现较大误差。
接下来对数据进行标准化处理,这里使用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.图像生成

    推荐阅读