循环神经网络

1 RNN概述

1.1 需要解决的问题

■对于序列(有序)数据,前面的结果会对后面的状态预测产生影响,顺序不可忽略。
        ➢时间序列数据:是指在不同时间点上收集到的数据,这类数据反映了某-事物、现象等,随时间的变化状态或程度(百度百科)。
        ➢其他序列数据:语音、光谱、文字....

        传统人工神经网络训练学习只是基于单- -的数据得出结果,没有考虑数据之间的顺序关联。传统神经网络输入和输出都是相互独立,如果针对输入和输出并不独立的问题,如何解决?如何上神经网络也能学习到数据之间的顺序关联呢?

 输出的预测结果不只依赖于input ,还依赖于之前的一部分信息,会把它存在memory.

 RNN可以看成是,在基础人工神经网络中,对应神经元的输出在下一-时间戳直接作用到自身,即神经元在t时刻的输入,除了该层神经元在该时刻的输出外,还包括其自身王t- 1时刻的输出。

2 RNN基础理论

2.1 RNN的基础结构

        基础的神经网络只在层与层之间建立了权连接, RNN最大的不同之处就是在层之间的神经元之间也建立的权连接。
                                         h^{(t)}=\Phi (Ux^{(t)}+Wh^{t-1}+b)

        x为输入、h^{(t)}为t时刻的状态描述、也是隐层单元、0为输出、y代表样本给出的确定值,L为损失函数
标准RNN的特点:
        1、权值共享,图中的W全是相同的, U和V也- -样。
        2、每一个输入值都只与它本身的那条路线建立权连接,不会和别的神经元连接。

2.2 RNN的基础结构的变种

双向RNN

  • 有些情况下,当前的输出不只依赖之前的序列元素,还可能依赖之后的序列元素。
  • 比如完形填空,剔掉部分词,让你补全。
  • 直观理解:双向RNN叠加

\overrightarrow{h_{t}}=f(\overrightarrow{W_{x_{t}}}+\overrightarrow{V}\overrightarrow{h_{t-1}}+\overrightarrow{b})                \overleftarrow{h_{t}}=f(\overleftarrow{W_{x_{t}}}+\overleftarrow{V}\overleftarrow{h_{t-1}}+\overleftarrow{b})

                                                y_{t}=g(U\left [ \overrightarrow{h_{t};} \overleftarrow{h_{t}}\right ]+c)

深层双向RNN

  •         和双向RNN的区别是每一步/每 个时间点我们设定多层结构。

                 \overrightarrow{h_{t}}^{(i)}=f(\overrightarrow{W^{(i)}}\overrightarrow{h}^{(i-1)}+\overrightarrow{V^{(i)}}\overrightarrow{h_{t-1}}^{(i)}+\overrightarrow{b^{(i)}}) 

                \overleftarrow{h_{t}}^{(i)}=f(\overleftarrow{W^{(i)}}\overleftarrow{h}^{(i-1)}+\overleftarrow{V^{(i)}}\overleftarrow{h_{t-1}}^{(i)}+\overleftarrow{b^{(i)}})

                                y_{t}=g(U\left [ \overrightarrow{h_{t}}^{L}; \overleftarrow{h_{t}}^{L}\right ]+c)

 2.3 RNN结构类型

 ( 1)一个输入对应一个输出( each to each )

 

         输入输出是一个等长序列,每一个输入都有一 个对应输出。例如股票预测中的RNN,输入是前N天的24小时的价格走势,输出明天的24小时的股市价格走势。

 (2)多输入单输出(manytoone)

                        

         输入是一个序列,输出只有一个状态。比如一个人说了一句话,判断这个人说的话带有的感情色彩是积极的还是消极的。

 (3)单输入多输出( one to many )

                        ​​​​​​​        

         输入只有一个,输出是一个序列。比如图片描述,输入为一-张图片,然后生成对图片描述的一段话或文字。

 ( 4)多输入多输出( many to many )

         输入与输出都是长序列。比如在语言翻译中,给出一-段英文,然后要求其翻译成中文。

 (5)单输入单输出(onetoone)

    

         输入与输出都只有一个。比如用于自动美颜的RNN ,输入是一-张图片,输出是一张图片。

2.4 RNN应用

RNN有趣应用

  • 语音识别:输入的语音数据,生成相应的语音文本信息。比如微信的语音转文字功能。
  • 机器翻译:不同语言之间的相互转换。像有道翻译、腾讯翻译官等。
  • 音乐生成:使用RNN网络生成音乐,一般会用到RNN中的LSTM算法(该算法可以解决RNN网络中相距较远的节点梯度消失的问题)。
  • 文本生成:利用RNN亦可以生成某种风格的文字。
  • 情感分类:输入文本或者语音的评论数据,输出相应的打分数据。
  • DNA序列分析:输入的DNA序列,输出蛋白质表达的子序列。
  • 视频行为识别:识别输入的视频帧序列中的人物行为。
  • 实体名字识别:从文本中识别实体的名字。
     

3 RNN的工作过程

3.1 RNN的弊端——长期依赖问题

        RNN网络会出现梯度消散和现误差爆炸,如果通过长序列训练误差是会传递的,若误差是0.9通过相乘误差会接近于0,若误差是1.1,通过相乘误差会很大。

4 长短时记忆网络LSML

4.1 LSML概述

        长短时记忆网络(LSTM) ,是- -种RNN特殊的类型,可以学习长期依赖信息。LSTM相比于普通的RNN ,多出了三个控制器:输入控制、输出控制和遗忘控制。

 

 4.2 细胞状态

        细胞状态类似于传送带。直接在整个链上运行,只有一-些少量的线性交互。信息在上面流传保持不变会很容易。

  •  LSTM通过“门”的结构来去除或者增加信息到细胞状态的能力。
  • 门是一种让信息选择式通过的方法。他们包含-个sigmoid神经网络层和一个pointwise乘法操作。
  • Sigmoid层输出0到1之间的数值描述每 个部分有多少量可以通过。 0代表 "不许任何量通过”, 1就指“充许任意量通过" !

4.3 LSTM的控制门

  •  遗忘门( forget gate )决定上一时刻的单元状态Ct-1有多少保留到当前时刻Ct
  • 输入门( input gate )决定当前时刻网络的输入x有多少保存到单元状态Ct
  • 输出门( output gate )控制单元状态C&有多少输出到LSTM的当前输出值ht

4.4 逐步理解LSTM

  • 第1步:决定从"细胞状态”中"遗忘”什么信息一- "遗忘门”
  • 比如此时的分线剧情改变了我们对之前剧情的想法,那么遗忘控制就会将之前的某些主线剧情忘记,按-定比例替换成现在的新剧情,主线剧情的更新就取决于输入和遗忘门控制。
  •  第2步:决定放什么信息到“细胞状态"中

                ①sigmoid层称"输入门层” 决定什么值我们将要更新
                ②tanh层创建一个新的候选值向量\widetilde{C_{t}}
                                        前两步(第1,2步)为“细胞状态”更新做准备

  • 第3步:更新“细胞状态”, 即更新C_{t-1}C_{t}

        ①把旧状态与ft相乘,丢弃掉我们确定需要丢弃的信息
        ②加上i_{t}\cdot C_{t},这就是新的候选值,根据我们决定更新每个状态的程度进行变化

  •  第4步:基于“细胞状态”得到输出

        ①首先运行一个sigmiod层来确定细胞状态的哪一 个部分将输出
        ②接着用tanh处理细胞状态(得到一个在-1到1之间的值 ) , 再将它和sigmoid门的输出相乘,输出我们确定输出的那部分

4.5 LSTM总结

  •  遗忘门( forget gate )决定上- -时刻的单元状态Ct- 1有多少保留到当前时刻Ct
  • 输入门( input gate )决定当前时刻网络的输入x有多少保存到单元状态Ct
  • 输出门( output gate )控制单元状态Ct有多少输出到LSTM的当前输出值ht

4.6 LSTM变种

变种1

        ➢增加了"peephole connection"窥视孔连接
        ➢让门层也会接受细胞状态的输入

 变种2
        ➢通过使用coupled忘记和输入门
        ➢不同于之前是分开确定什么忘记和需要添加什么新的信息,这里是- -同做出决定

变种3——Gated Recurrent Unit (GRU) (由Cho, et al. (2014)提出)
        ➢将忘记门和输入门J合成了一个单- -的更新门
        ➢同样还混合了细胞状态和隐藏状态,和其他一-些改动

        GRU只有两个门,分别为更新门和重置门,即图中的zt和rt ,更新[ ]用于控制前一-时刻的状态信息被带入到当前状态中的程度,更新]的值越大说明前一-时刻的状态信息带入越少。重置门用于控制忽略前- -时刻的状态信息的程度,重置门]的值越小说明忽略得越多。

LSTM其他变种
        ➢Yao, et al. (2015)提出的Depth Gated RNN
        ➢Koutnik, et al. (2014)提出的Clockwork RNN
        ➢Greff, et al. (2015)给出了流行变体的比较
        ➢Jozefowicz, et al. (2015)对RNN架构的测试

5 LSTM的Keras实战

        时序预测问题的数据(X)和标签( Y )分别是什么?

​​​​​​​                        数据是历史序列v(-n)...v(t-1)
                        标签是待预测的值v(t)

5.1 实战案例

单步预测:历史序列v(-n....v(t-1)是真实值;待预测的值v(t);逐点推进,每次都是使用真实值
多步预测:历史序列v(t-n)...v(t-1)是真实值;待预测的值v(t) , v(t+ 1)...v(t+ m);预测多步时加入之前的预测值
5.2 准备数据

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline


dataSize= 2000; #数据
valSize=200;    #测试集个数
testSize=200;   #验证集个数
t = np.linspace(0, 100, dataSize)   #从0到100中均匀地取100个值
y = np.sin(t)
plt.plot(t[:-valSize-testSize] ,y[:-valSize- -testSize],"b.")
plt. plot(t [-valSize- -testSize:-testSize] ,y [-valSize- -testSize:-testSize],"g.")
plt.plot(t [-testSize:],y[-testSize:],"r.")
plt. show( )

结果:

5.2 数据准备——滑动窗口

window_len=10
seq_y=rolling_window(y,window_len)  #滑窗函数提取段的值
print(seq_y.shape)
#训练集
trainX=seq_y[:-valSize-testSize--1] #提取测试集数据
trainY=y[window_len:-valSize-testSize]  #提取标签
print(trainX.shape)
print(trainY.shape)
#验证集
valX=seq_y[-valSize-testSize-1:-testSize-1]
valY=y[-valSize-testSize:-testSize]
print(valX.shape)
print(valY.shape)
#测试集
testX=seq_y[-testSize-1:-1]
testY=y[-testSize:]
print(testX.shape)
print(testY.shape)

5.3 LSTM模型

LSTM输入训练数据shape : [序列数量(样本数量)、序列长度(窗口大小)、特征维度]

#将训练集数据从两个维度变为三个维度
trainX=trainX.reshape(trainX.shape[0],trainX.shape[1],1)
valX=valX.reshape(valX.shape[0],valX.shape[1],1)
testX=testX.reshape(testX.shape[0],testX.shape[1],1)
print(trainX.shape)
print(valX.shape)
print(testX.shape)


from keras.models import Model
from keras.layers import Input, Dense,LSTM
from keras.callbacks import ReduceLROnPlateau,ModelCheckpoint , EarlyStopping
from keras.models import load_model
inp=Input(shape=(trainX.shape[1],trainX.shape[2]))  #输入序列长度shape1和特征维度shape2
x=LSTM(50,return_sequences=True)(inp)   #50个神经元的LSTM
x=LSTM(100,return_sequences=False)(x)  #100个神经元的LSTM,不需要输出隐含层序列:return_sequences=False
x=Dense(1,activation='linear',name='regression')(x)     #预测输出只有1个,线性激活函数linear(回归值)
model=Model(inp,x)  #定义模型
model.compile(optimizer='rmsprop',loss='mse')      #模型编译,使用rmsprop做优化器,用mse做误差值
model.summary()

5.4 模型训练

#=======模型训练========
modelfilepath='model.best.hdf5' #定义最好模型的名字

#定义自动结束
earlyStop=EarlyStopping(monitor='val_loss', #监视误差
                        patience=20,
                        verbose=1,
                        mode='auto')
#保存最好的
checkpoint=ModelCheckpoint(modelfilepath,
                           monitor='val_loss',
                           verbose=1,
                           save_best_only=True,
                           mode='auto')
#改变学习率
reduce_lr=ReduceLROnPlateau(monitor='val_loss',
                            factor=0.1,
                            patience=10,
                            verbose=1,
                            mode='auto',
                            min_delta=0.00001,
                            c00ldown=0,
                            min_lr=0)
history=model.fit(trainX,
                  trainY,
                  validation_data=(valX,valY),#由于需要预测,我们需要制定验证集
                  epochs=50,    #迭代50次
                  batch_size=32,
                  callbacks=[checkpoint,reduce_lr,earlyStop])
#测试
testmodel=load_model(modelfilepath)
result_train=testmodel.predict(trainX)
result_va1=testmodel.predict(valX)
result_test=testmodel.predict(testX)
#显示
t=np.linspace(0,100,dataSize)
y=np.sin(t)
plt.plot(t[:-valSize-testSize],y[:-valSize-testSize],"b")
plt.plot(t[-valSize-testSize:-testSize],y[-valSize-testSize:-testSize,"g")
plt.plot(t[-testSize:],y[-testSize:],"r")
#plt.plot(t[window_len:-valSize-testSize],result_train,"k")#训练集结果
#plt.plot(t[-valSize-testSize:-testSize],result_val,"k")    #验证集集结果
#plt.plot(t[-testSize:],result_test,"k")    #测试集结果
plt.show()

参考:【宅着宅着就学习惯了】机器学习——人工智能系列课程_哔哩哔哩_bilibili

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值