【程序喵笔记】递归神经网络实现预测

递归神经网络实现预测

有一天,一个女孩子向电脑小黑说“我好喜欢你好久了,你能不能。。。”,女孩子羞涩的低下下了头。小黑一愣“她啥意思啊?”,女孩子一看无望,转身离开。小黑绞尽脑汁,终于研究了一种“递归神经网络(RNN)”有了这个神器,就可以根据有逻辑关系的一段话进行判断,预测啦~简直就是直男的救星。

专业点来讲,递归神经网络就是处理序列数据的神经网络,也就是处理前后有关系的数据,比如语言、天气预测。比起其他神经网络,它引入了“记忆”功能,不仅能根据当前输入找到输出,也会结合前面的信息。

RNN (Recurrent Neural Network)

RNN基本结构

RNN的结构图很简单,添加中间隐层s,传递上一个输入的信息,输出o(t)不仅由当前输入x(t)决定,也和上一个隐层h(t-1)有关。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-65YLdh72-1587817246609)(E:\Tensorflow\0.我的笔记\5.从RNN到LSTM实现气温数据预测\image\1.RNN示意图.png)]

在时刻t,隐层h(t)表达如下,其中f为激活函数,b为偏置
h t = f ( W h t − 1 + U x t + b ) h_t=f(Wh_{t-1}+Ux_t+b) ht=f(Wht1+Uxt+b)
在时刻t,输出o(t)表达式如下,c为偏置
o t = V h t + c o_t=Vh_t+c ot=Vht+c

输入和输出

我们会发现,此时输出有些多,到底取哪一个输出呢?这就由我们的任务决定了。

1.多输入单输出

如果我们需要一个输出,比如根据一句话判断是夸你的还是骂你的.那么很明显就取最后一个结果,原因很简单,最后一个输出是最全面。

2.单输入多输出

如果从一张图像描述出来一段话,可以把输入x作为一个信息输入,也可以把输入x作为每个输入

3.多输入多输出

如果是一一对应,那么直接把输出都拿到就可以,比如后面还要连接下一层的RNN,。大多数情况是并不是一一对应。比如,输入是:“我喜欢你很久了,能不能”,输出是"做我男朋友"这样就是seq2seq,也可以称为Encoder-Decoder模型.

Encoder是一个RNN, 它的输出为上下文向量c,c可以取Encoder最后一个隐状态,也可以是Encoder多个隐状态组合. Decoder是另一个RNN, 将c用作RNN隐层初始状态.

在这里插入图片描述

还有一种Decoder是将c用作每一步的输入

RNN反向传播

BPTT(back-propagation through time)算法是常用的训练RNN的方法,其实本质还是BP算法,也就是梯度下降,损失对各个参数求梯度(偏导)就是关键问题.三个参数W,U和V.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PCObyeAb-1587817246613)(E:\Tensorflow\0.我的笔记\5.从RNN到LSTM实现气温数据预测\image\1.RNN示意图.png)]

对参数V, 和时间没有关系,但是损失L会随着t的增加而增加的,也就是累加
∂ L ∂ V = ∑ t = 1 n ( ∂ L t ∂ o t ∂ o t ∂ V ) \frac{\partial L}{\partial V} =\sum_{t=1}^n\left(\frac{\partial L_t}{\partial o_t}\frac{\partial o_t}{\partial V} \right) VL=t=1n(otLtVot)
对于参数WU求偏导,都需要涉及历史数据
∂ L t ∂ W = ∂ L t ∂ o t ∂ o t ∂ h t ∑ k = 1 t [ ( ∏ i = k + 1 t ∂ h i ∂ h i − 1 ) ∂ h k ∂ W ] \frac{\partial L_t}{\partial W}= \frac{\partial L_t}{\partial o_t}\frac{\partial o_t}{\partial h_t}\sum_{k=1}^t\left[\left(\prod_{i=k+1}^t\frac{\partial h_i}{\partial h_{i-1}}\right)\frac{\partial h_k}{\partial W}\right] WLt=otLthtotk=1t[(i=k+1thi1hi)Whk]

∂ L t ∂ U = ∂ L t ∂ o t ∂ o t ∂ h t ∑ k = 1 t [ ( ∏ i = k + 1 t ∂ h i ∂ h s i − 1 ) ∂ h k ∂ U ] \frac{\partial L_t}{\partial U}= \frac{\partial L_t}{\partial o_t}\frac{\partial o_t}{\partial h_t}\sum_{k=1}^t\left[\left(\prod_{i=k+1}^t\frac{\partial h_i}{\partial hs_{i-1}}\right)\frac{\partial h_k}{\partial U}\right] ULt=otLthtotk=1t[(i=k+1thsi1hi)Uhk]

得到隐层h时, 加入激活函数f (f 可以是Relu, Sigmoid, tanh)的,还需要包括激活函数求导
∏ i = k + 1 t ∂ h i ∂ h i − 1 = ∏ i = k + 1 t f ′ W \prod_{i=k+1}^t\frac{\partial h_i}{\partial h_{i-1}}=\prod_{i=k+1}^tf'W i=k+1thi1hi=i=k+1tfW
累乘会导致激活函数导数和权重矩阵的累乘,进而会导致“梯度消失“和“梯度爆炸“现象的发生

LSTM (Long Short Term Memory)

LSTM是RNN的一种变体,RNN由于梯度消失的原因只能有短期记忆,LSTM网络通过精妙的门控制将短期记忆与长期记忆结合起来,一定程度上解决了梯度消失的问题, 长短记忆相可以结合.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OcjvYWGR-1587817246618)(E:\Tensorflow\0.我的笔记\5.从RNN到LSTM实现气温数据预测\image\7.RNN与LSTM比较.png)]

LSTM相比RNN,除了隐层 h 随着时间流动,还多出一个随时间流动的细胞状态,这就是长记忆的关键. LSTM由遗忘门,输入门和输出门三部分构成,每个部分都是使用sigmoid函数作为选择工具,tanh函数作为变换工具来实现.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4g4DuOVy-1587817246628)(E:\Tensorflow\0.我的笔记\5.从RNN到LSTM实现气温数据预测\image\7.1sigmoid比较tanh.png)]

遗忘门

决定c(t-1)有多少被遗忘。sigmoid函数输出是(0,1)之间一个数(0代表不通过,1代表全通过),与c(t-1)相乘

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ggxXKhKc-1587817246630)(E:\Tensorflow\0.我的笔记\5.从RNN到LSTM实现气温数据预测\image\8.遗忘门.png)]

输入门

输入门会根据遗忘门的信息, 并增加此时输入x(t)h(t-1)的信息, 共同更新 c(t). 也就是说, 把前面的适当忘记一部分, 再加上新学的一部分.

在这里插入图片描述

输出门

输出h(t)由细胞状态c(t), x(t), h(t-1)决定. 把细胞状态c(t)通过 tanh 进行处理(得到一个在 -1 到 1 之间的值),x(t)h(t-1) 通过sigmoid 门,两者相乘, 得到输出. 简单来说, 就是很久之前学到的, 刚刚学到的, 正在学的综合在一起.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QO3XR461-1587817246637)(E:\Tensorflow\0.我的笔记\5.从RNN到LSTM实现气温数据预测\image\10.输出门.png)]

LSTM网络实现气温预测

任务目标:利用多组时间有关的数据来预测之后的某个时间/时间段的温度

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yL5eQFAC-1587817246639)(E:\Tensorflow\0.我的笔记\5.从RNN到LSTM实现气温数据预测\image\11.训练目标.png)]

数据集准备

1.读取数据

pandas读取,数据每隔10分钟记录一次

df = pd.read_csv('jena_climate_2009_2016.csv')
features_considered = ['p (mbar)', 'T (degC)', 'rho (g/m**3)']
features = df[features_considered]
dataset = features.values

在这里插入图片描述

2.数据预处理

前30w为训练数据,取训练数据均值和方差,将数据预处理。(只能用训练数据求均值方差)

TRAIN_SPLIT = 300000
data_mean = dataset[:TRAIN_SPLIT].mean(axis=0)
data_std = dataset[:TRAIN_SPLIT].std(axis=0)
dataset = (dataset-data_mean)/data_std

3.数据&标签制作

数据:取5天内每隔1小时的3个特征,表格是以10分钟记录一次的,所以取5* 24 * 6 = 720时间点,以6为间隔取值,最终一条数据维度为(120,3)

标签:12小时之后的温度值(12*6=72个时间点后)

  • dataset:训练数据,包括三个特征[‘p (mbar)’, ‘T (degC)’, ‘rho (g/m**3)’]
  • target:标签数据,只有温度特征 [‘T (degC)’]
  • start_index:开始索引,训练集为0,验证集为TRAIN_SPLIT
  • end_index:结束索引,训练集为TRAIN_SPLIT,验证集为None
  • history_size:窗口长度,选择训练窗口为5天的数据,5 * 24 *6=720条记录
  • target_size: 预测标签在多少时间点后取值。预测为12小时后的温度值,即12*6=72, 72个时间点
  • step: 每隔多长时间取数据,step= 6,720/6=120 ,索引为range(0, 720, 6)
  • single_step: 如果为True,标签为一个时间点的值,如果为False,标签为一个时间段的值
def multivariate_data(dataset, target, start_index, end_index, history_size,
                      target_size, step, single_step=False):
    data = []
    labels = []

    start_index = start_index + history_size
    if end_index is None:
        end_index = len(dataset) - target_size

    for i in range(start_index, end_index):
        indices = range(i-history_size, i, step) #训练集索引为range(0,720,6),range(1,721,6)
        data.append(dataset[indices])

        if single_step:
            labels.append(target[i+target_size]) #训练集(720+72),(721+72)
        else:
            labels.append(target[i:i+target_size])

    return np.array(data), np.array(labels)
past_history = 720
future_target = 72
STEP = 6

x_train_single, y_train_single = multivariate_data(dataset, dataset[:, 1], 0,
                                                   TRAIN_SPLIT, past_history,
                                                   future_target, STEP,
                                                   single_step=True)
x_val_single, y_val_single = multivariate_data(dataset, dataset[:, 1],
                                               TRAIN_SPLIT, None, past_history,
                                               future_target, STEP,
                                               single_step=True)

结果:

x_train_single 维度为(299280, 120, 3),299280组数据,每组数据包含120个时间点,3个不同特征

y_train_single 维度为(299280,),299280组标签

4.构建训练数据

把数据和标签放在一起,打乱并放入batch

train_data_single = tf.data.Dataset.from_tensor_slices((x_train_single, y_train_single))
train_data_single = train_data_single.cache().shuffle(BUFFER_SIZE).batch(BATCH_SIZE).repeat()

val_data_single = tf.data.Dataset.from_tensor_slices((x_val_single, y_val_single))
val_data_single = val_data_single.batch(BATCH_SIZE).repeat()

模型构建

Demo一下,越简单越好,只连接一个LSTM网络和全连接层。输入为(120,3)放入LSTM网络,输出一个32维向量,然后接全连接层,最终得到一个结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wXD6LsV3-1587817246646)(E:\Tensorflow\0.我的笔记\5.从RNN到LSTM实现气温数据预测\image\13.网络结构.png)]

single_step_model = tf.keras.models.Sequential()
single_step_model.add(tf.keras.layers.LSTM(32,
                                           input_shape=x_train_single.shape[-2:]))
single_step_model.add(tf.keras.layers.Dense(1))

single_step_model.compile(optimizer=tf.keras.optimizers.RMSprop(), loss='mae')

训练结果

为提高速度,每个epoch训练200组数据

VALUATION_INTERVAL=200
single_step_history = single_step_model.fit(train_data_single, epochs=EPOCHS,
                                            steps_per_epoch=EVALUATION_INTERVAL,
                                            validation_data=val_data_single,
                                            validation_steps=50)

结果看一下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-85gCyr37-1587817246649)(E:\Tensorflow\0.我的笔记\5.从RNN到LSTM实现气温数据预测\image\14.单预测结果.png)]

引申:预测某段时间温度

标签并不是一个值,而变成一组值, single_step设置为False,标签为一个时间段的值,此时 y_train_multi维度为(299280, 72),299280组数据,每组数据有72标签。

网络设计为多加一层LSTM,并且全连接层输出为72,因为我们有72个值

multi_step_model = tf.keras.models.Sequential()
# 因为后续还要接LSTM,所以return_sequences=True
multi_step_model.add(tf.keras.layers.LSTM(32,
                                          return_sequences=True,
                                          input_shape=x_train_multi.shape[-2:]))
multi_step_model.add(tf.keras.layers.LSTM(16, activation='relu'))
multi_step_model.add(tf.keras.layers.Dense(72))

multi_step_model.compile(optimizer=tf.keras.optimizers.RMSprop(clipvalue=1.0), loss='mae')

看看结果,趋势还可以但是不是很精确
在这里插入图片描述

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值