欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

用实验证明深度学习中梯度消失的存在与LSTM的有效性

程序员文章站 2022-07-02 12:08:09
...

一直都听说传统RNN有个致命的缺陷,即梯度消失,导致其无法有效处理长序列

今天我们来用实验证明其存在,并且测试LSTM的有效性.


实验思路很简单,设置数据如下.

随机生成X 

X=[Ran0,Ran1,Ran2,Ran3,Ran4,Ran5,Ran6,Ran7,Ran8,Ran9]

Y=[Ran9] ,Y与X最后的数相同


实验猜想

如果梯度消失不存在,那使用传统RNN拟合Y时,无论X是正序还是逆序,拟合精度都应该一样


实验过程与结果分析

1.X使用正序

   Ran9在序列的最后输入,在反向传播训练时其权重首先被训练,预测精度良好,

   为什么达不到100%呢? 训练时间不够长,神经网络在0~8的权重还"舍不得"置为0.

   用实验证明深度学习中梯度消失的存在与LSTM的有效性

2.X使用逆序

    Ran9在序列的最先输入,在反向传播训练时其权重最后被训练,预测精度完全没有!!!

    神经网络完全"忘了"最开始的输入才是最重要的.

用实验证明深度学习中梯度消失的存在与LSTM的有效性


3.使用LSTM

X使用正序

用实验证明深度学习中梯度消失的存在与LSTM的有效性

X使用逆序

可以看出,LSTM确实可以克服梯度消失的问题,不像SimpleRNN一样直接蒙了.

但同样需要更长的训练时间和更好的训练设置才可以取得理想精度.

有兴趣的同学试试加入批标准化层,或者Multi-LSTM试试.


    用实验证明深度学习中梯度消失的存在与LSTM的有效性


完整代码,复制粘贴就能跑! 

欢迎留言指正!

#验证RNN的梯度消失
#LSTM确实有用

import numpy as np
import pandas as pd
import copy
import matplotlib.pyplot as plt

from sklearn.preprocessing import StandardScaler

from keras.models import Sequential,Model
from keras.layers import Dense,SimpleRNN,LSTM,Input


def create_RNN_data(data_in,timestep,label):#生成RNN形式的数据,label是因变量Y
    data_in=pd.DataFrame(data_in)
    data_=copy.deepcopy(data_in)
    
    for columns in data_.columns:
        if columns!=label:#不是因变量的label
            for i in range(1,timestep):
                data_[columns+'-'+str(i)]=data_[columns].shift(+i)
        
    data_.dropna(inplace=True)
    data_.index=np.arange(0,len(data_))
    return data_


time_step=10
data=pd.DataFrame({'X':np.random.randint(0,10,1000)}) #随机生成数据


data['Y']=data['X'].shift(time_step-1) 
#重要的一步,使得Y与前time_step步的X相同
#本文中,Y与[9]完全相同


data.dropna(inplace=True) #删除由于shift引入的空行
data.index=np.arange(0,len(data)) #重设index


rnn_data=create_RNN_data(data,time_step,'Y') #生成RNN形式的数据


#选择自变量
X_raw=rnn_data[['X','X-1','X-2','X-3','X-4','X-5','X-6','X-7','X-8','X-9']]
scaler = StandardScaler().fit(X_raw) #标准化能加速训练
X_raw1=scaler.transform(X_raw)


X_raw2=np.array(X_raw1)
X=np.reshape(X_raw2,(-1,time_step,1)) #reshape
Y=np.array(rnn_data['Y'])




#构建神经网络
input01=Input(shape=(time_step,1))
RNN01=LSTM(units=5,
                go_backwards=False)(input01) #返回的是一个数组,[output,state]
               #实验核心变量,go_backwards设置是否翻转输入的序列.
               #False,正序X,0,1,2,3,4,5,6,7,8,9
               #True,逆序X,9,8,7,6,5,4,3,2,1,0
               
               #[9]就是Y值,在使用True时,因此在反向传播训练时,[9]是最后一个,
               #梯度消失了无法得到有效训练
               
output01=Dense(1)(RNN01)


model=Model(inputs=input01,outputs=output01)
model.compile(optimizer='adam',loss='mse')


model.fit(X,
          Y,
          batch_size=20,
          validation_split=0.5,
          verbose=1,
          epochs=200,
          initial_epoch=0,
          shuffle=True)


pred=model.predict(X)


plt.scatter(Y,pred)
plt.xlabel('True')
plt.ylabel('Predict')