zoukankan      html  css  js  c++  java
  • 使用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 

  • 相关阅读:
    Notes about "Exploring Expect"
    Reuse Sonar Checkstyle Violation Report for Custom Data Analysis
    Eclipse带参数调试的方法
    MIT Scheme Development on Ubuntu
    Manage Historical Snapshots in Sonarqube
    U盘自动弹出脚本
    hg的常用配置
    Java程序员的推荐阅读书籍
    使用shared memory 计算矩阵乘法 (其实并没有加速多少)
    CUDA 笔记
  • 原文地址:https://www.cnblogs.com/DjangoBlog/p/9706705.html
Copyright © 2011-2022 走看看