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 

  • 相关阅读:
    没有spring如何使用注解下篇
    在没有spring框架如何使用注解上篇
    oracle11g里sqldeveloper不能打开的问题
    java代码换行
    枚举接口Enumeration
    java开发环境的搭建(上班笔记01)
    2013.12.12-2013.12.22面试
    2013.12.12-2013.12.20面试
    supervisor superlance
    Laravel 返回日期问题2021-07-23T05:56:03.000000Z
  • 原文地址:https://www.cnblogs.com/DjangoBlog/p/9706705.html
Copyright © 2011-2022 走看看