使用tensorflow的lstm網絡進行時間序列預測


https://blog.csdn.net/flying_sfeng/article/details/78852816
版權聲明:本文為博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/Flying_sfeng/article/details/78852816

這篇文章將講解如何使用lstm進行時間序列方面的預測,重點講lstm的應用,原理部分可參考以下兩篇文章:

Understanding LSTM Networks       LSTM學習筆記

編程環境:python3.5,tensorflow 1.0

本文所用的數據集來自於kesci平台,由雲腦機器學習實戰訓練營提供:真實業界數據的時間序列預測挑戰

數據集采用來自業界多組相關時間序列(約40組)與外部特征時間序列(約5組)。本文只使用其中一組數據進行建模。

加載常用的庫:

 

  1.  
    #加載數據分析常用庫
  2.  
    import pandas as pd
  3.  
    import numpy as np
  4.  
    import tensorflow as tf
  5.  
    from sklearn.metrics import mean_absolute_error,mean_squared_error
  6.  
    from sklearn.preprocessing import MinMaxScaler
  7.  
    import matplotlib.pyplot as plt
  8.  
    % matplotlib inline
  9.  
    import warnings
  10.  
    warnings.filterwarnings( 'ignore')
數據顯示:
  1.  
    path = '../input/industry/industry_timeseries/timeseries_train_data/11.csv'
  2.  
    data11 = pd.read_csv(path,names=[ '年','月','日','當日最高氣溫','當日最低氣溫','當日平均氣溫','當日平均濕度','輸出'])
  3.  
    data11.head()
  當日最高氣溫 當日最低氣溫 當日平均氣溫 當日平均濕度 輸出
0 2015 2 1 1.9 -0.4 0.7875 75.000 814.155800
1 2015 2 2 6.2 -3.9 1.7625 77.250 704.251112
2 2015 2 3 7.8 2.0 4.2375 72.750 756.958978
3 2015 2 4 8.5 -1.2 3.0375 65.875 640.645401
4 2015 2 5 7.9 -3.6 1.8625 55.375 631.725130
加載數據:
  1.  
    ##load data(本文以第一個表為例,其他表類似,不再贅述)
  2.  
    f=open( '../input/industry/industry_timeseries/timeseries_train_data/11.csv')
  3.  
    df=pd.read_csv(f) #讀入數據
  4.  
    data=df.iloc[:, 3:8].values #取第3-7列
定義常量並初始化權重:
  1.  
    #定義常量
  2.  
    rnn_unit= 10 #hidden layer units
  3.  
    input_size= 4
  4.  
    output_size= 1
  5.  
    lr= 0.0006 #學習率
  6.  
    tf.reset_default_graph()
  7.  
    #輸入層、輸出層權重、偏置
  8.  
    weights={
  9.  
    'in':tf.Variable(tf.random_normal([input_size,rnn_unit])),
  10.  
    'out':tf.Variable(tf.random_normal([rnn_unit,1]))
  11.  
    }
  12.  
    biases={
  13.  
    'in':tf.Variable(tf.constant(0.1,shape=[rnn_unit,])),
  14.  
    'out':tf.Variable(tf.constant(0.1,shape=[1,]))
  15.  
    }
分割數據集,將數據分為訓練集和驗證集(最后90天做驗證,其他做訓練):
  1.  
    def get_data(batch_size=60,time_step=20,train_begin=0,train_end=487):
  2.  
    batch_index=[]
  3.  
     
  4.  
    scaler_for_x=MinMaxScaler(feature_range=( 0,1)) #按列做minmax縮放
  5.  
    scaler_for_y=MinMaxScaler(feature_range=( 0,1))
  6.  
    scaled_x_data=scaler_for_x.fit_transform(data[:,: -1])
  7.  
    scaled_y_data=scaler_for_y.fit_transform(data[:, -1])
  8.  
     
  9.  
    label_train = scaled_y_data[train_begin:train_end]
  10.  
    label_test = scaled_y_data[train_end:]
  11.  
    normalized_train_data = scaled_x_data[train_begin:train_end]
  12.  
    normalized_test_data = scaled_x_data[train_end:]
  13.  
     
  14.  
    train_x,train_y=[],[] #訓練集x和y初定義
  15.  
    for i in range(len(normalized_train_data)-time_step):
  16.  
    if i % batch_size==0:
  17.  
    batch_index.append(i)
  18.  
    x=normalized_train_data[i:i+time_step,: 4]
  19.  
    y=label_train[i:i+time_step,np.newaxis]
  20.  
    train_x.append(x.tolist())
  21.  
    train_y.append(y.tolist())
  22.  
    batch_index.append((len(normalized_train_data)-time_step))
  23.  
     
  24.  
    size=(len(normalized_test_data)+time_step -1)//time_step #有size個sample
  25.  
    test_x,test_y=[],[]
  26.  
    for i in range(size-1):
  27.  
    x=normalized_test_data[i*time_step:(i+ 1)*time_step,:4]
  28.  
    y=label_test[i*time_step:(i+ 1)*time_step]
  29.  
    test_x.append(x.tolist())
  30.  
    test_y.extend(y)
  31.  
    test_x.append((normalized_test_data[(i+ 1)*time_step:,:4]).tolist())
  32.  
    test_y.extend((label_test[(i+ 1)*time_step:]).tolist())
  33.  
     
  34.  
    return batch_index,train_x,train_y,test_x,test_y,scaler_for_y
 
定義LSTM的網絡結構:
  1.  
    #——————————————————定義神經網絡變量——————————————————
  2.  
    def lstm(X):
  3.  
    batch_size=tf.shape(X)[ 0]
  4.  
    time_step=tf.shape(X)[ 1]
  5.  
    w_in=weights[ 'in']
  6.  
    b_in=biases[ 'in']
  7.  
    input=tf.reshape(X,[ -1,input_size]) #需要將tensor轉成2維進行計算,計算后的結果作為隱藏層的輸入
  8.  
    input_rnn=tf.matmul(input,w_in)+b_in
  9.  
    input_rnn=tf.reshape(input_rnn,[ -1,time_step,rnn_unit]) #將tensor轉成3維,作為lstm cell的輸入
  10.  
    cell=tf.contrib.rnn.BasicLSTMCell(rnn_unit)
  11.  
    #cell=tf.contrib.rnn.core_rnn_cell.BasicLSTMCell(rnn_unit)
  12.  
    init_state=cell.zero_state(batch_size,dtype=tf.float32)
  13.  
    output_rnn,final_states=tf.nn.dynamic_rnn(cell, input_rnn,initial_state=init_state, dtype=tf.float32) #output_rnn是記錄lstm每個輸出節點的結果,final_states是最后一個cell的結果
  14.  
    output=tf.reshape(output_rnn,[ -1,rnn_unit]) #作為輸出層的輸入
  15.  
    w_out=weights[ 'out']
  16.  
    b_out=biases[ 'out']
  17.  
    pred=tf.matmul(output,w_out)+b_out
  18.  
    return pred,final_states

模型訓練與預測:
  1.  
    #——————————————————訓練模型——————————————————
  2.  
    def train_lstm(batch_size=80,time_step=15,train_begin=0,train_end=487):
  3.  
    X=tf.placeholder(tf.float32, shape=[ None,time_step,input_size])
  4.  
    Y=tf.placeholder(tf.float32, shape=[ None,time_step,output_size])
  5.  
    batch_index,train_x,train_y,test_x,test_y,scaler_for_y = get_data(batch_size,time_step,train_begin,train_end)
  6.  
    pred,_=lstm(X)
  7.  
    #損失函數
  8.  
    loss=tf.reduce_mean(tf.square(tf.reshape(pred,[ -1])-tf.reshape(Y, [-1])))
  9.  
    train_op=tf.train.AdamOptimizer(lr).minimize(loss)
  10.  
    with tf.Session() as sess:
  11.  
    sess.run(tf.global_variables_initializer())
  12.  
    #重復訓練5000次
  13.  
    iter_time = 5000
  14.  
    for i in range(iter_time):
  15.  
    for step in range(len(batch_index)-1):
  16.  
    _,loss_=sess.run([train_op,loss],feed_dict={X:train_x[batch_index[step]:batch_index[step+ 1]],Y:train_y[batch_index[step]:batch_index[step+1]]})
  17.  
    if i % 100 == 0:
  18.  
    print( 'iter:',i,'loss:',loss_)
  19.  
    ####predict####
  20.  
    test_predict=[]
  21.  
    for step in range(len(test_x)):
  22.  
    prob=sess.run(pred,feed_dict={X:[test_x[step]]})
  23.  
    predict=prob.reshape(( -1))
  24.  
    test_predict.extend(predict)
  25.  
     
  26.  
    test_predict = scaler_for_y.inverse_transform(test_predict)
  27.  
    test_y = scaler_for_y.inverse_transform(test_y)
  28.  
    rmse=np.sqrt(mean_squared_error(test_predict,test_y))
  29.  
    mae = mean_absolute_error(y_pred=test_predict,y_true=test_y)
  30.  
    print ('mae:',mae,' rmse:',rmse)
  31.  
    return test_predict

調用train_lstm()函數,完成模型訓練與預測的過程,並統計驗證誤差(mae和rmse):
test_predict = train_lstm(batch_size=80,time_step=15,train_begin=0,train_end=487)
 
迭代5000次后的結果:
  1.  
    iter: 3900 loss: 0.000505382
  2.  
    iter: 4000 loss: 0.000502154
  3.  
    iter: 4100 loss: 0.000503413
  4.  
    iter: 4200 loss: 0.00140424
  5.  
    iter: 4300 loss: 0.000500015
  6.  
    iter: 4400 loss: 0.00050004
  7.  
    iter: 4500 loss: 0.000498159
  8.  
    iter: 4600 loss: 0.000500861
  9.  
    iter: 4700 loss: 0.000519379
  10.  
    iter: 4800 loss: 0.000499999
  11.  
    iter: 4900 loss: 0.000501265
  12.  
    mae: 121.183626208 rmse: 162.049017904

畫圖分析:
 
  1.  
    plt.figure(figsize=( 24,8))
  2.  
    plt.plot(data[:, -1])
  3.  
    plt.plot([ None for _ in range(487)] + [x for x in test_predict])
  4.  
    plt.show()

結果如下:
 
 
可以看到,lstm模型基本能預測出序列的趨勢。
為了簡化流程,本文在特征工程及參數調優方面並沒有下功夫,適合初學者探索lstm模型在時間序列問題上的應用。
ps:數據的歸一化很重要,必須保證把訓練集跟驗證集規范在同一個空間內,否則得到的效果會很差。(我以前做天池的降雨量預測問題時一開始用的就是lstm,就是這一步沒做好,導致最后得到的結果基本很相近,最后這個模型被我放棄了。我在做這個數據集的時候一開始也遇到這個問題,后來在歸一化時把樣本都設置在同個空間范疇,就解決問題了)。
數據集提供了大概45組數據,所以我們可以使用multi-task learning探索各組數據之間的關聯性,這部分我還沒具體了解,就不貽笑大方了。
 
 
        

--------------------- 本文來自 Flying_sfeng 的CSDN 博客 ,全文地址請點擊:https://blog.csdn.net/flying_sfeng/article/details/78852816?utm_source=copy 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM