zoukankan      html  css  js  c++  java
  • LSTM之Keras中Stateful参数

    一、Sateful参数介绍

           在Keras调用LSTM的参数中,有一个stateful参数,默认是False,也就是无状态模式stateless,为True的话就是有状态模式stateful,所以这里我们就归为两种模式:

    • 有状态模型(stateful LSTM)
    • 无状态模型(stateless LSTM)

           那两者到底是什么区别呢,怎么使用呢?

    二、区别

    • stateful LSTM
      • 除了正常的单个sample内部时间步之间的状态互相传递外(这个是LSTM的基本功能),sample之间的状态还能互相传递。但是需要确定batch_size大小,传递的时候是前一个batch的第i个sample最终输出状态,传递给后一个batch的第i个sample,作为其状态的初始化值。以“解放军第72集团军某旅500名抗洪子弟兵撤离安徽铜陵枞阳县,赶赴合肥庐江县继续抗洪。当地百姓冒着大雨追着驶出的车辆,递上自家的莲蓬、葡萄、熟鸡蛋等食物,送别子弟兵。”为例子,第一句话为一个sample,第二句话为第二个sample,每个sample内部的word为一个时间步,很明显前后两个sample是相互关联的。如果设置batch_size=1,则第一句话最终输出状态(即最后一个word的状态输出),就可以传递给第二句话作为其初始状态值。
      • 优点:后面的语句有了更合理的初始化状态值,显然会加快网络的收敛,所以需要更小的网络、更少的训练时间。
      • 缺点:每一个epoch后,要重置一下状态,因为训练一遍了,状态不能循环使用,要从头开始。
      • 使用注意事项:调用fit() 时指定 shuffle = False,要保证sample之间的前后顺序;可以使用 model.reset_states()来重置模型中所有层的状态,也可使用layer.reset_states()来重置指定有状态 RNN 层的状态。
    • stateless LSTM

                stateless就是与stateful相反了,就是sample之间没有前后状态传递的关系,输入samples后,默认就会shuffle,可以说是每个sample独立,适合输入一些没有关系的样本。

               

    三、问答

    1、在Keras中stateless LSTM中的stateless指的是?
      注意,此文所说的stateful是指的在Keras中特有的,是batch之间的记忆cell状态传递。而非说的是LSTM论文模型中表示那些记忆门,遗忘门,c,h等等在同一sequence中不同timesteps时间步之间的状态传递。假定我们的输入X是一个三维矩阵,shape = (nb_samples, timesteps, input_dim),每一个row代表一个sample,每个sample都是一个sequence小序列。X[i]表示输入矩阵中第i个sample。步长啥的我们先不用管。当我们在默认状态stateless下,Keras会在训练每个sequence小序列(=sample)开始时,将LSTM网络中的记忆状态参数reset初始化(指的是c,h而并非权重w),即调用model.reset_states()。

    2、为啥stateless LSTM每次训练都要初始化记忆参数?
      因为Keras在训练时会默认地shuffle samples,所以导致sequence之间的依赖性消失,sample和sample之间就没有时序关系,顺序被打乱,这时记忆参数在batch、小序列之间进行传递就没意义了,所以Keras要把记忆参数初始化。

     

    四、代码举例

      通过对cos函数的预测来分别对比stateless和stateful的差别

    1、 单层无状态LSTM模型(序列长度为20)

    import numpy as np
    from keras.models import Sequential
    from keras.layers import Dense, LSTM, Dropout
    import matplotlib.pyplot as plt
    
    # 创建数据集,每隔50个就是一个整Π,围绕Π的系数不断变化
    dataset = np.cos(np.arange(1000)*(20*np.pi/1000))#dataset的值域再-1~1之间。
     
    # 转换数据为LSTM输入格式: dataset matrix
    def create_dataset(dataset, look_back=1):
        dataX, dataY = [], []
        for i in range(len(dataset)-look_back):
            dataX.append(dataset[i:(i+look_back)])
            dataY.append(dataset[i + look_back])
        return np.array(dataX), np.array(dataY)
    
    # 20长度的滑动窗口进行预测
    look_back = 20
    
    # 归一化,y值域为(0,1)
    dataset = (dataset+1) / 2.
    
    # split into train and test sets
    train_size = int(len(dataset) * 0.8)
    test_size = len(dataset) - train_size
    train, test = dataset[:train_size], dataset[train_size:]
     
    trainX, trainY = create_dataset(train, look_back)
    testX, testY = create_dataset(test, look_back)
    print(trainX.shape)
    print(trainY.shape)
    
    trainX = np.reshape(trainX, (trainX.shape[0], trainX.shape[1], 1))
    testX = np.reshape(testX, (testX.shape[0], testX.shape[1], 1))
    '''
        trainX.shape =  (780, 20, 1)
        testX.shape =  (180, 20, 1)
        trainY.shape =  (780,)
        testY.shape =  (180,)
    '''
    
    #构建无状态LSTM模型
    batch_size = 1
    
    model = Sequential()
    model.add(LSTM(32, input_shape=(20, 1)))
    model.add(Dropout(0.2))
    model.add(Dense(1))
     
    model.compile(loss = 'mse', optimizer = 'adam')
    model.fit(trainX,trainY,batch_size = batch_size,epochs=30, verbose=2)
    
    #从训练集的最后一个sample样本截取后面的19个+y值得1个,构成一个新的sample(20,1),来预测一个值,其实这个值就是测试集的第一个值,
    x = np.vstack((trainX[-1][1:],(trainY[-1])))#vstack就是竖着拼起来
    preds=[]
    pred_num = 500
    
    for i in np.arange(pred_num):
        #重新转换成适合lstm的格式,并进行预测
        pred = model.predict(x.reshape((1,-1,1)),batch_size = batch_size)
        preds.append(pred.squeeze())
        x = np.vstack((x[1:],pred))
        
    #横坐标就是1~500
    plt.figure(figsize=(12,5))
    plt.plot(np.arange(pred_num),np.array(preds),'r',label='predctions')
    cos_y = (np.cos(np.arange(pred_num)*(20*np.pi/1000))+1)/ 2.
    plt.plot(np.arange(pred_num),cos_y,label='origin')
    plt.legend()
    plt.show()

    2、单层有状态LSTM模型(序列长度为40)

    # 单层有状态 LSTM network
    # 创建数据集,每隔50个就是一个整Π,围绕Π的系数不断变化
    dataset = np.cos(np.arange(1000)*(20*np.pi/1000))#dataset的值域再-1~1之间。
     
    # 转换数据为LSTM输入格式: dataset matrix
    def create_dataset(dataset, look_back=1):
        dataX, dataY = [], []
        for i in range(len(dataset)-look_back):
            dataX.append(dataset[i:(i+look_back)])
            dataY.append(dataset[i + look_back])
        return np.array(dataX), np.array(dataY)
    # 建立模型:双层stacked Stateful LSTM
    look_back =40
    dataset = np.cos(np.arange(1000)*(20*np.pi/1000))
    #归一化,y值域为(0,1)
    dataset = (dataset+1) / 2.
     
    # split into train and test sets
    train_size = int(len(dataset) * 0.8)
    test_size = len(dataset) - train_size
    train, test = dataset[:train_size], dataset[train_size:]
     
    trainX, trainY = create_dataset(train, look_back)
    testX, testY = create_dataset(test, look_back)
     
    trainX = np.reshape(trainX, (trainX.shape[0], trainX.shape[1], 1))
    testX = np.reshape(testX, (testX.shape[0], testX.shape[1], 1))
    
    batch_size = 1
    model2 = Sequential()
    model2.add(LSTM(32, batch_input_shape=(batch_size, look_back, 1), stateful=True))
    model2.add(Dropout(0.2))
    model2.add(Dense(1))
    model2.compile(loss='mse', optimizer='adam')
    for i in range(30):
        model2.fit(trainX, trainY, epochs=1, batch_size=batch_size,  shuffle=False)
        model2.reset_states()
    x = np.vstack((trainX[-1][1:],(trainY[-1])))
    preds = []
    pred_num = 500
    for i in np.arange(pred_num):
        pred = model2.predict(x.reshape((1,-1,1)),batch_size = batch_size)
        preds.append(pred.squeeze())
        x = np.vstack((x[1:],pred))
    
    plt.figure(figsize=(12,5))
    plt.plot(np.arange(pred_num),np.array(preds),'r',label='predctions')
    cos_y = (np.cos(np.arange(pred_num)*(20*np.pi/1000))+1)/ 2.
    plt.plot(np.arange(pred_num),cos_y,label='origin')
    plt.legend()
    plt.show()

    3、双层有状态LSTM模型(序列长度为40)

    # 创建数据集,每隔50个就是一个整Π,围绕Π的系数不断变化
    dataset = np.cos(np.arange(1000)*(20*np.pi/1000))#dataset的值域再-1~1之间。
     
    # 转换数据为LSTM输入格式: dataset matrix
    def create_dataset(dataset, look_back=1):
        dataX, dataY = [], []
        for i in range(len(dataset)-look_back):
            dataX.append(dataset[i:(i+look_back)])
            dataY.append(dataset[i + look_back])
        return np.array(dataX), np.array(dataY)
    # 建立模型:双层stacked Stateful LSTM
    look_back =40
    dataset = np.cos(np.arange(1000)*(20*np.pi/1000))
    #归一化,y值域为(0,1)
    dataset = (dataset+1) / 2.
     
    # split into train and test sets
    train_size = int(len(dataset) * 0.8)
    test_size = len(dataset) - train_size
    train, test = dataset[:train_size], dataset[train_size:]
     
    trainX, trainY = create_dataset(train, look_back)
    testX, testY = create_dataset(test, look_back)
     
    trainX = np.reshape(trainX, (trainX.shape[0], trainX.shape[1], 1))
    testX = np.reshape(testX, (testX.shape[0], testX.shape[1], 1))
     
    # 建立模型:有状态
    batch_size = 1
    model3 = Sequential()
    model3.add(LSTM(32, batch_input_shape=(batch_size, look_back, 1), stateful=True, return_sequences=True))
    model3.add(Dropout(0.3))
    model3.add(LSTM(32, batch_input_shape=(batch_size, look_back, 1), stateful=True))
    model3.add(Dropout(0.3))
    model3.add(Dense(1))
    model3.compile(loss='mean_squared_error', optimizer='adam')
    for i in range(100):
        print(i)
        model3.fit(trainX, trainY, epochs=1, batch_size=batch_size, verbose=0, shuffle=False)
        model3.reset_states()
    # 预测
    x = np.vstack((trainX[-1][1:],(trainY[-1])))
    preds = []
    pred_num = 500
    for i in np.arange(pred_num):
        pred = model3.predict(x.reshape((1,-1,1)),batch_size = batch_size)
        preds.append(pred.squeeze())
        x = np.vstack((x[1:],pred))
     
    # print(preds[:20])
    # print(np.array(preds).shape)
    plt.figure(figsize=(12,5))
    plt.plot(np.arange(pred_num),np.array(preds),'r',label='predctions')
    cos_y = (np.cos(np.arange(pred_num)*(20*np.pi/1000))+1)/ 2.
    plt.plot(np.arange(pred_num),cos_y,label='origin')
    plt.legend()
    plt.show()

     参考连接:

    https://blog.csdn.net/qq_27586341/article/details/88239404

    http://philipperemy.github.io/keras-stateful-lstm/

  • 相关阅读:
    2014,成为更好程序员的7个方法
    联想集团大裁员,血淋漓的教训:公司只能给你位置,却无法给你未来!(转)
    Oracel数据库连接时出现:ORA-12518:监听程序无法分发客户机连
    Could not find a version that satisfies.... No matching distribution found for .....
    深度学习(七)U-Net原理以及keras代码实现医学图像眼球血管分割
    深度学习(六)keras常用函数学习
    np.random.random()函数 参数用法以及numpy.random系列函数大全
    2019最新win10 安装tensorflow1.4(GPU/CPU)+cuda8.0+cudnn8.0-v6 + keras 安装CUDA失败 导入tensorflow失败报错问题解决
    c++ 网络编程课设代码 网络编程入门教程 ---目录
    c++ 网络编程(十一) LINUX下 初步制作基于HTTP的WEB服务器
  • 原文地址:https://www.cnblogs.com/gczr/p/13393883.html
Copyright © 2011-2022 走看看