当前位置:   article > 正文

lstm 预测未来多天_lstm预测未来多天数据

lstm预测未来多天数据

前言:

       由于原模型只能预测一天,不满足需求,所以在上篇的基础模型上进行修改,使原模型可以预测未来多天结果。

      修改之后,新模型可以根据多天的数据预测未来多天的结果。应用范围广泛,可以用于,股票预测,汇率预测,安全仓库预测,电力负荷预测等各种实际的应用。可以根据数据集的不同,使用该模型解决各种实际的预测问题。

       由于项目数据集不公开,本文使用公开数据集,Beijing PM2.5 Data Set进行仿真实验。具体来说,根据前五天的环境变量信息,预测未来五天的污染值。

(23条消息) lstm多变量预测_wh来啦的博客-CSDN博客

模型结构对比:

原模型:

 改进之后的模型:

 使用公开数据集:

Beijing PM2.5 Data Set

下载数据集地址:

http://archive.ics.uci.edu/ml/datasets/Beijing+PM2.5+Data

如果失效,百度直接搜索Beijing PM2.5 Data Set,也可以免费获取数据集。

数据预处理:

  对数据进行清洗,得到可以使用的数据。数据清洗时需要根据数据本身的特点,进行针对性的清洗。

数据划分:

首先将数据划分为X,Y。本次实验需要设计输入五天的变量,输出未来五天的预测值,所以,n_in=5,表示需要历史五天的数据,n_out=5,表示预测未来五天的值,代码如下:

  1. def series_to_supervised(data, n_in=5, n_out=5, dropnan=True):
  2. # convert series to supervised learning
  3. n_vars = 1 if type(data) is list else data.shape[1]
  4. df = pd.DataFrame(data)
  5. cols, names = list(), list()
  6. # input sequence (t-n, ... t-1)
  7. for i in range(n_in, 0, -1):
  8. cols.append(df.shift(i))
  9. names += [('var%d(t-%d)' % (j + 1, i)) for j in range(n_vars)]
  10. # forecast sequence (t, t+1, ... t+n)
  11. for i in range(0, n_out):
  12. cols.append(df.shift(-i))
  13. if i == 0:
  14. names += [('var%d(t)' % (j + 1)) for j in range(n_vars)]
  15. else:
  16. names += [('var%d(t+%d)' % (j + 1, i)) for j in range(n_vars)]
  17. # put it all together
  18. agg = pd.concat(cols, axis=1)
  19. agg.columns = names
  20. # drop rows with NaN values
  21. if dropnan:
  22. agg.dropna(inplace=True)
  23. # normalize features
  24. return agg

 将不需要预测的数据drop掉,得到我们希望预测的数据结构。

  1. def cs_to_sl():
  2. # load dataset
  3. dataset = pd.read_csv('pollution.csv', header=0, index_col=0)
  4. values = dataset.values
  5. # integer encode direction
  6. encoder = LabelEncoder()
  7. values[:, 4] = encoder.fit_transform(values[:, 4])
  8. # ensure all data is float
  9. values = values.astype('float32')
  10. # frame as supervised learning
  11. reframed = series_to_supervised(values, 5, 5)
  12. # drop columns we don't want to predict
  13. reframed.drop(reframed.columns[[41,42,43,44,45,46,47,49,50,51,52,53,54,55,57,58,59,60,61,62,63,65,66,67,68,69,70,71,73, 74, 75, 76, 77, 78, 79]], axis=1, inplace=True)
  14. print(reframed.head())
  15. return reframed

因为一天有八个变量,需要历史五天的数据,所有X就有8*5列(40列)数据,而要预测未来五天的污染物值,所以Y有5列数据,合在一起就有45列数据。,具体的历史数据,预测数据结构如下:

 然后将数据划分为训练集(train),测试集(test)。由于数据列表数发生变化,归一化的过程调整到这一部分,否者列数对应不上,反归一化时会报错。由于预测的列数发生变化,划分train_x,train_y,test_x,test_y时,需要调整相应的维度,这里调整为.[:,:-5][:,-5:]。具体代码如下:

  1. def train_test(reframed):
  2. # split into train and test sets
  3. values = reframed.values
  4. n_train_hours = 365 * 24*3
  5. scaler = MinMaxScaler(feature_range=(0, 1))
  6. values = scaler.fit_transform(values)
  7. train = values[:n_train_hours, :]
  8. test = values[n_train_hours:, :]
  9. # split into input and outputs
  10. train_X, train_y = train[:, :-5],train[:, -5:]
  11. test_X, test_y = test[:, :-5], test[:, -5:]
  12. # reshape input to be 3D [samples, timesteps, features]
  13. train_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))
  14. test_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))
  15. print(train_X.shape, train_y.shape, test_X.shape, test_y.shape)
  16. return train_X, train_y, test_X, test_y, scaler

构建模型并训练:

调整模型结构,从原来的一层lstm,调整到三层lstm。为了避免过拟合的问题,使用Dropout函数。由于要预测未来五天的数据,所以最后一个dense的输出,从原来的1,调整为5。同时,修改模型的学习率,使模型取得更好的效果。最后,在对应的列上,使用反归一化,得到未来预测的结果。其他参数,如epoch,batchsize等,可以自己调整,就不细说了。嘻嘻

  1. def fit_network(train_X, train_y, test_X, test_y, scaler):
  2. model = Sequential()
  3. model.add(LSTM(50, return_sequences=True,input_shape=(train_X.shape[1], train_X.shape[2])))
  4. model.add(Dropout(0.3))
  5. model.add(LSTM(50,return_sequences=True))
  6. model.add(Dropout(0.3))
  7. model.add(LSTM(50))
  8. model.add(Dense(5))
  9. model.compile(loss='mae', optimizer='adam')
  10. # fit network
  11. reduce_lr = ReduceLROnPlateau(monitor='val_loss', patience=10, mode='auto')
  12. history = model.fit(train_X, train_y, epochs=50, batch_size=72, validation_data=(test_X, test_y), verbose=2,
  13. shuffle=False, callbacks=[reduce_lr])
  14. # plot history
  15. pyplot.plot(history.history['loss'], label='train')
  16. pyplot.plot(history.history['val_loss'], label='test')
  17. pyplot.legend()
  18. pyplot.show()
  19. # make a prediction
  20. yhat = model.predict(test_X)
  21. test_X = test_X.reshape((test_X.shape[0], test_X.shape[2]))
  22. # invert scaling for forecast
  23. inv_yhat = concatenate((test_X, yhat),axis=1)
  24. inv_yhat = scaler.inverse_transform(inv_yhat)
  25. print(inv_yhat[-1:])
  26. inv_yhat = inv_yhat[:, -5:]
  27. # invert scaling for actual
  28. inv_y = concatenate((test_X, test_y), axis=1)
  29. inv_y = scaler.inverse_transform(inv_y)
  30. inv_y = inv_y[:, -5:]
  31. # calculate RMSE
  32. rmse = sqrt(mean_squared_error(inv_y, inv_yhat))
  33. print('Test RMSE: %.3f' % rmse)

最后展示一下运行结果:

    结果分析: 至于为什么自己误差那么大,可能是因为数据选得不好;或者是因为模型结构不够完美,需要微调;或者是因为一次预测五天,相比预测一天,误差本来就会很大。这个就得慢慢分析,调整了,嘻嘻。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/485009
推荐阅读
相关标签
  

闽ICP备14008679号