RNN与传统神经网络

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

在这里插入图片描述

RNN的基本结构

在这里插入图片描述

其中,右图圆形的箭头表示隐藏层的自连接。

在RNN中,每一层都共享参数U、V、W,降低了网络中需要学习的参数,提高学习效率。

输入单元(input units)记为:
(https://img-blog.csdnimg.cn/600b06c209294d66ac6cc902fb957981.png)
隐藏单元(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+Wst1) ,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.图像生成

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐