一、问题背景

    现实生活中,在一系列时间点上观测数据是司空见惯的活动,在农业、商业、气象军事和医疗等研究领域都包含大量的时间序列数据。时间序列的预测指的是基于序列的历史数据,以及可能对结果产生影响的其他相关序列,对序列未来的可能取值做出预测。现实生活中的时间序列数据预测问题有很多,包括语音分析、噪声消除以及股票期货市场的分析等,其本质主要是根据前T个时刻的观测数据推算出T+1时刻的时间序列的值。

    那么面对时间序列的预测问题,我们可以用传统的ARIMA模型,也可以用基于时间序列分解的STL模型或者Facebook开源的Prophet模型。在机器学习或者人工智能大热的现在,深度学习等机器学习方法也可以用于时间序列的预测。今天介绍的就是如何基于Keras和Python,实现时间序列的LSTM模型预测。

二、LSTM模型介绍

    长短时记忆网络(Long Short Term Memory,简称LSTM)模型,本质上是一种特定形式的循环神经网络(Recurrent Neural Network,简称RNN)。LSTM模型在RNN模型的基础上通过增加门限(Gates)来解决RNN短期记忆的问题,使得循环神经网络能够真正有效地利用长距离的时序信息。LSTM在RNN的基础结构上增加了输入门限(Input Gate)、输出门限(Output Gate)、遗忘门限(Forget Gate)3个逻辑控制单元,且各自连接到了一个乘法元件上(见图1),通过设定神经网络的记忆单元与其他部分连接的边缘处的权值控制信息流的输入、输出以及细胞单元(Memory cell)的状态。其具体结构如下图所示。


图1:LSTM概念图

    上图中相关部件的描述如下:

    Input Gate:控制信息是否流入Memory cell中,记为。

    Forget Gate:控制上一时刻Memory cell中的信息是否积累到当前时刻Memory cell中,记为。

    Output Gate:控制当前时刻Memory cell中的信息是否流入当前隐藏状态中,记为。

    cell:记忆单元,表示神经元状态的记忆,使得LSTM单元有保存、读取、重置和更新长距离历史信息的能力,记为。

    在t时刻,LSTM神经网络定义的公式如下:

    除了前文提及的、、和,分别代表其相应门限的递归连接权重,sigmoid和tanh为两种激活函数。

    隐藏层cell结构图如图2所示。在LSTM神经网络的训练过程中,首先将t时刻的数据特征输入至输入层,经过激励函数输出结果。将输出结果、t-1时刻的隐藏层输出和t-1时刻cell单元存储的信息输入LSTM结构的节点中,通过Input Gate,Output Gate,Forget Gate和cell单元的处理,输出数据到下一隐藏层或输出层,输出LSTM结构节点的结果到输出层神经元,计算反向传播误差,更新各个权值。


图2:LSTM细节图

三、LSTM模型准备

3.1 加载需要的包

from math import sqrtfrom numpy import concatenatefrom matplotlib import pyplotfrom pandas import read_csvfrom pandas import DataFramefrom pandas import concatfrom sklearn.preprocessing import MinMaxScalerfrom sklearn.preprocessing import LabelEncoderfrom sklearn.metrics import mean_squared_errorfrom keras.models import Sequentialfrom keras.layers import Densefrom keras.layers import LSTMimport pandas as pdimport numpy as np

3.2 定义将时间序列预测问题转化为监督学习问题的函数

    前文已经提及,时间序列预测的本质主要是根据前T个时刻的观测数据推算出T+1时刻的时间序列的值。这就转化为机器学习中的监督学习问题,输入值为历史值,输出值为预测值。因此,利用LSTM模型进行时间序列预测的第一步便是将数据集整理成监督学习中常见的数据类型,一行为一个样本,行数为样本数,列数为变量总数。这里利用的是pandas库中dataframe的shift函数。

def series_to_supervised(data, n_in=1, n_out=1, dropnan=True):    n_vars = 1 if type(data) is list else data.shape[1]    df = DataFrame(data)    cols, names = [], []    #i: n_in, n_in-1, ..., 1,为滞后期数    #分别代表t-n_in, ... ,t-1期    for i in range(n_in, 0, -1):        cols.append(df.shift(i))        names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]    #i: 0, 1, ..., n_out-1,为超前预测的期数    #分别代表t,t+1, ... ,t+n_out-1期    for i in range(0, n_out):        cols.append(df.shift(-i))        if i == 0:            names += [('var%d(t)' % (j+1)) for j in range(n_vars)]        else:            names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]    agg = concat(cols, axis=1)    agg.columns = names    if dropnan:        agg.dropna(inplace=True)    return agg

3.3 定义准备数据的函数

def prepare_data(filepath, n_in, n_out=30, n_vars=4, train_proportion=0.8):    #读取数据集    dataset = read_csv(filepath, encoding='utf-8')    #设置时间戳索引    dataset['日期'] = pd.to_datetime(dataset['日期'])    dataset.set_index("日期", inplace=True)    values = dataset.values    #保证所有数据都是float32类型    values = values.astype('float32')    #变量归一化    scaler = MinMaxScaler(feature_range=(0, 1))    scaled = scaler.fit_transform(values)    #将时间序列问题转化为监督学习问题    reframed = series_to_supervised(scaled, n_in, n_out)    #取出保留的变量    contain_vars = []    for i in range(1, n_in+1):        contain_vars += [('var%d(t-%d)' % (j, i)) for j in range(1,n_vars+1)]      data = reframed [ contain_vars + ['var1(t)'] + [('var1(t+%d)' % (j)) for j in range(1,n_out)]]    #修改列名    col_names = ['Y', 'X1', 'X2', 'X3']    contain_vars = []    for i in range(n_vars):        contain_vars += [('%s(t-%d)' % (col_names[i], j)) for j in range(1,n_in+1)]      data.columns = contain_vars +  ['Y(t)'] + [('Y(t+%d)' % (j)) for j in range(1,n_out)]    #分隔数据集,分为训练集和测试集    values = data.values    n_train = round(data.shape[0]*train_proportion)    train = values[:n_train, :]    test = values[n_train:, :]    #分隔输入X和输出y    train_X, train_y = train[:, :n_in*n_vars], train[:, n_in*n_vars:]    test_X, test_y = test[:, :n_in*n_vars], test[:, n_in*n_vars:]    #将输入X改造为LSTM的输入格式,即[samples,timesteps,features]    train_X = train_X.reshape((train_X.shape[0], n_in, n_vars))    test_X = test_X.reshape((test_X.shape[0], n_in, n_vars))    return scaler, data, train_X, train_y, test_X, test_y, dataset

3.4 定义拟合LSTM模型的函数

def fit_lstm(data_prepare, n_neurons=50, n_batch=72, n_epoch=100, loss='mae', optimizer='adam', repeats=1):    train_X = data_prepare[2]    train_y = data_prepare[3]    test_X = data_prepare[4]    test_y = data_prepare[5]    model_list = []    for i in range(repeats):        #设计神经网络        model = Sequential()        model.add(LSTM(n_neurons, input_shape=(train_X.shape[1], train_X.shape[2])))        model.add(Dense(train_y.shape[1]))        model.compile(loss=loss, optimizer=optimizer)        #拟合神经网络        history = model.fit(train_X, train_y, epochs=n_epoch, batch_size=n_batch, validation_data=(test_X, test_y), verbose=0, shuffle=False)        #画出学习过程        p1 = pyplot.plot(history.history['loss'], color='blue', label='train')        p2 = pyplot.plot(history.history['val_loss'], color='yellow',label='test')        #保存model        model_list.append(model)    pyplot.legend(["train","test"])    pyplot.show()    return model_list

3.5 定义预测的函数

def lstm_predict(model, data_prepare):    scaler = data_prepare[0]    test_X = data_prepare[4]    test_y = data_prepare[5]    #做出预测    yhat = model.predict(test_X)    #将测试集上的预测值还原为原来的数据维度    scale_new = MinMaxScaler()    scale_new.min_, scale_new.scale_ = scaler.min_[0], scaler.scale_[0]    inv_yhat = scale_new.inverse_transform(yhat)    #将测试集上的实际值还原为原来的数据维度    inv_y = scale_new.inverse_transform(test_y)    return inv_yhat, inv_y

3.6 定义预测评价的函数(RMSE)

# 计算每一步预测的RMSEdef evaluate_forecasts(test, forecasts, n_out):    rmse_dic = {}    for i in range(n_out):        actual = [float(row[i]) for row in test]        predicted = [float(forecast[i]) for forecast in forecasts]        rmse = sqrt(mean_squared_error(actual, predicted))        rmse_dic['t+' + str(i+1) + ' RMSE'] = rmse    return rmse_dic

3.7 定义将预测可视化的函数

#以原始数据为背景画出预测数据def plot_forecasts(series, forecasts):    #用蓝色画出原始数据集    pyplot.plot(series.values)    n_seq = len(forecasts[0])    #用红色画出预测值    for i in range(1,len(forecasts)+1):        xaxis = [x for x in range(i, i+n_seq+1)]        yaxis = [float(series.iloc[i-1,0])] + list(forecasts[i-1])        pyplot.plot(xaxis, yaxis, color='red')    #展示图像    pyplot.show()

四、建立LSTM模型

4.1 建立模型(n_in = 15,n_neuron = 5,n_batch = 16,n_epoch = 200)

    为了减少随机性,重复建立五次模型,取五次结果的平均作为最后的预测。

#定义需要的变量filepath = r'C:\Users\87689\Desktop\国贸实习\Premium\导出文件.csv'n_in = 15n_out = 30n_vars = 4n_neuron = 5n_batch = 16n_epoch = 200repeats = 5inv_yhat_list = []inv_y_list = []

data_prepare = prepare_data(filepath,n_in, n_out)scaler, data, train_X, train_y, test_X, test_y, dataset = data_preparemodel_list = fit_lstm(data_prepare, n_neuron, n_batch, n_epoch,repeats=repeats)for i in range(len(model_list)):    model = model_list[i]    inv_yhat = lstm_predict(model, data_prepare)[0]    inv_y = lstm_predict(model, data_prepare)[1]    inv_yhat_list.append(inv_yhat)    inv_y_list.append(inv_y)

图3:模型训练结果

    求出平均预测结果。

inv_yhat_ave = np.zeros(inv_y.shape)for i in range(repeats):    inv_yhat_ave += inv_yhat_list[i]

inv_yhat_ave = inv_yhat_ave/repeats

4.2 模型评价

    求出五次预测结果inv_yhat及最终平均预测结果inv_yhat_ave的每步预测RMSE。

rmse_dic_list = []for i in range(len(model_list)):    inv_yhat = inv_yhat_list[i]    inv_y = inv_y_list[i]    rmse_dic = evaluate_forecasts(inv_y, inv_yhat, n_out)    rmse_dic_list.append(rmse_dic)

rmse_dic_list.append(evaluate_forecasts(inv_y, inv_yhat_ave, n_out))

df_dic = {}for i in range(len(rmse_dic_list) - 1):    df_dic['第' + str(i+1) + '次'] = pd.Series(rmse_dic_list[i])

df_dic['平均'] = pd.Series(rmse_dic_list[i+1])rmse_df = DataFrame(df_dic)rmse_df

表1:预测RMSE结果表

第1次 第2次 第3次 第4次 第5次 平均
t+1 RMSE 6.054318 5.910827 6.574757 5.514524 5.930769 5.608112
t+2 RMSE 6.799496 5.919717 7.129066 5.930466 6.346187 6.065158
t+3 RMSE 6.961642 6.410686 7.275462 6.546540 6.857233 6.618044
t+4 RMSE 7.707383 6.725169 7.962916 7.179770 7.364481 7.175948
t+5 RMSE 8.543821 7.359477 8.997917 7.591111 8.004835 7.831434
t+6 RMSE 8.826944 8.790049 9.158018 8.390160 8.501117 8.547602
t+7 RMSE 9.372653 8.842808 9.847240 8.818847 8.995596 9.000587
t+8 RMSE 9.869172 9.206043 10.790298 9.389183 9.621195 9.657852
t+9 RMSE 10.224256 10.113056 11.275415 9.925362 10.320555 10.177834
t+10 RMSE 10.730779 10.613619 11.738241 10.547615 10.858770 10.750603
t+11 RMSE 11.217751 11.153954 12.502412 11.135731 11.692412 11.458523
t+12 RMSE 11.975135 12.117445 13.382915 11.581188 12.537667 12.201281
t+13 RMSE 12.431174 12.648199 14.090454 12.092397 12.351822 12.579149
t+14 RMSE 13.060560 13.141831 14.255130 12.452494 13.279099 13.074444
t+15 RMSE 13.879692 13.775036 15.346088 13.138019 13.793227 13.845060
t+16 RMSE 14.670389 14.491605 16.118887 13.422946 14.143394 14.421311
t+17 RMSE 15.237153 15.503956 16.679258 13.896419 14.108534 14.909649
t+18 RMSE 15.390742 15.054655 16.010253 14.280028 15.037541 15.060793
t+19 RMSE 16.030557 15.657191 16.441218 14.518066 15.145838 15.417519
t+20 RMSE 15.671409 15.547522 16.150036 14.704495 15.150355 15.359049
t+21 RMSE 15.757660 15.787190 16.898795 14.751765 15.152527 15.546924
t+22 RMSE 15.208240 17.009959 16.376563 14.852501 15.567227 15.670801
t+23 RMSE 15.162898 16.254727 16.888183 15.513842 15.526986 15.738396
t+24 RMSE 15.516408 16.282854 16.762683 15.109268 15.232268 15.642263
t+25 RMSE 15.338432 16.417778 16.450235 15.218523 15.879392 15.764465
t+26 RMSE 15.215581 16.714160 16.687302 15.704890 15.650851 15.860303
t+27 RMSE 15.410981 16.711455 17.264010 15.838977 15.801374 16.052185
t+28 RMSE 15.969366 16.453532 16.564865 15.876696 16.078542 16.110161
t+29 RMSE 16.291474 16.447350 16.771656 15.870124 16.276672 16.236876
t+30 RMSE 16.122111 16.578749 16.643779 16.260352 16.013707 16.189853

    下面求最终平均预测结果inv_yhat_ave的每步预测错误率的平均,平均来看,预测结果会比真实结果偏高。

s = inv_yhat_ave[0].shapeerro_rate = np.zeros(s)for i in range(len(inv_y)):    erro_rate += inv_yhat_ave[i]/inv_y[i]-1

erro_rate_ave = erro_rate/len(inv_y)err_df = DataFrame(pd.Series(erro_rate_ave))err_df.columns = ['平均预测错误率']err_df.index = ['超前%d步预测' % (i+1) for i in range(n_out)]err_df

表2:按步平均预测错误率结果表

平均预测错误率
超前1步预测 0.046550
超前2步预测 0.047578
超前3步预测 0.050722
超前4步预测 0.052867
超前5步预测 0.059091
超前6步预测 0.063377
超前7步预测 0.064786
超前8步预测 0.064920
超前9步预测 0.065614
超前10步预测 0.066760
超前11步预测 0.074791
超前12步预测 0.077122
超前13步预测 0.076288
超前14步预测 0.076228
超前15步预测 0.085402
超前16步预测 0.089160
超前17步预测 0.090592
超前18步预测 0.096903
超前19步预测 0.099449
超前20步预测 0.096841
超前21步预测 0.099562
超前22步预测 0.100283
超前23步预测 0.093786
超前24步预测 0.091290
超前25步预测 0.091107
超前26步预测 0.086526
超前27步预测 0.086098
超前28步预测 0.085978
超前29步预测 0.085980
超前30步预测 0.077837

4.3 预测结果可视化

    测试集的前十个样本

dataset = data_prepare[6]test_X = data_prepare[4]n_real = len(dataset)-len(test_X)-len(inv_yhat_ave[0])#多画一个y_real = DataFrame(dataset['Y'][n_real:n_real+10+30])plot_forecasts(y_real, inv_yhat_ave[0:10])

图4:预测结果可视化1

    整个测试集

n_real = len(dataset)-len(test_X)-len(inv_yhat[0])#多画一个y_real = DataFrame(dataset['Y'][n_real:])plot_forecasts(y_real, inv_yhat_ave)

图4:预测结果可视化2

4.4 结果导出

    Yhat

pre_df = DataFrame(inv_yhat_ave)#时间戳处理,让它只显示到日date_index = dataset.index[n_in-1+len(train_X)-1:n_in-1+len(train_X)+len(test_X)-1]pydate_array = date_index.to_pydatetime()date_only_array = np.vectorize(lambda s: s.strftime('%Y-%m-%d'))(pydate_array )date_only_series = pd.Series(date_only_array)pre_df = pre_df.set_index(date_only_series)names_columns = ['未来%d期' % (i+1) for i in range(n_out)]pre_df.columns = names_columnspre_df = pre_df.round(decimals=2)#小数点

    Y

actual_df = DataFrame(inv_y)names_columns = ['未来%d期' % (i+1) for i in range(n_out)]actual_df.columns = names_columnsactual_df = actual_df.set_index(date_only_series)actual_df = actual_df.round(decimals=2)

    导出xlsx

writer = pd.ExcelWriter('Y-结果导出.xlsx')pre_df.to_excel(writer,"Yhat")actual_df.to_excel(writer,"Y")writer.save()

参考资料:

https://machinelearningmastery.com/multivariate-time-series-forecasting-lstms-keras/

https://machinelearningmastery.com/multi-step-time-series-forecasting-long-short-term-memory-networks-python/

https://blog.csdn.net/qq_28031525/article/details/79046718

https://cloud.tencent.com/developer/article/1645547

https://machinelearningmastery.com/update-lstm-networks-training-time-series-forecasting/

bagging和时间序列预测_时间序列的LSTM模型预测——基于Keras相关推荐

  1. 时间序列深度学习:状态 LSTM 模型预测太阳黑子

    目录 时间序列深度学习:状态 LSTM 模型预测太阳黑子 教程概览 商业应用 长短期记忆(LSTM)模型 太阳黑子数据集 构建 LSTM 模型预测太阳黑子 1 若干相关包 2 数据 3 探索性数据分析 ...

  2. LSTM模型(基于Keras框架)预测特定城市或者区域的太阳光照量实战

    LSTM模型(基于Keras框架)预测特定城市或者区域的太阳光照量实战 LSTM在解决序列预测的问题时非常强大,因为它们能够存储之前的信息. LSTM是一种时间递归神经网络,它出现的原因是为了解决RN ...

  3. python预测股票 keras_使用LSTM模型预测股价基于Keras

    本期作者:Derrick Mwiti 本期翻译:HUDPinkPig 未经授权,严禁转载 编者按:本文介绍了如何使用LSTM模型进行时间序列预测.股票市场的数据由于格式规整和非常容易获得,是作为研究的 ...

  4. 时间序列预测(四)—— LSTM模型

    时间序列预测(四)-- LSTM模型 欢迎大家来我的个人博客网站观看原文:https://xkw168.github.io/2019/05/20/时间序列预测-四-LSTM模型.html 文章链接 ( ...

  5. 时间序列深度学习:状态 LSTM 模型预測太阳黑子(一)

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/kMD8d5R/article/details/82111558 作者:徐瑞龙,量化分析师,R语言中文 ...

  6. baostock证券数据集下使用LSTM模型预测A股走势

    baostock证券数据集下使用LSTM模型预测A股走势 作者信息:edencfc 更新日期:2022 年 11 月 10 日 摘要: 本示例将会演示如何使用飞桨完成多变量输入的时序数据预测任务.这个 ...

  7. 【金融】【pytorch】使用深度学习预测期货收盘价涨跌——LSTM模型构建与训练

    [金融][pytorch]使用深度学习预测期货收盘价涨跌--LSTM模型构建与训练 LSTM 创建模型 模型训练 查看指标 LSTM 创建模型 指标函数参考<如何用keras/tf/pytorc ...

  8. bagging和时间序列预测_时间序列多步预测的五种策略

    通常,时间序列预测描述了预测下一个时间步长的观测值.这被称为"一步预测",因为仅要预测一个时间步.在一些时间序列问题中,必须预测多个时间步长.与单步预测相比,这些称为多步时间序列预 ...

  9. LSTM模型预测时间序列(快速上手)

    写在前面 LSTM模型的一个常见用途是对长时间序列数据进行学习预测,例如得到了某商品前一年的日销量数据,我们可以用LSTM模型来预测未来一段时间内该商品的销量.但对于不熟悉神经网络或者对没有了解过RN ...

最新文章

  1. python3.8.5是python3吗_Python 升级到3.8.5
  2. ASP.NET页面进行GZIP压缩优化的几款压缩模块的使用简介及应用测试!(附源码)
  3. 验证E-mail是否正确
  4. canoe开发从入门到精通pdf_阿里技术官手写801页PDF《精通Java Web整合开发》
  5. boost::lower_bound相关的测试程序
  6. 文件磁盘相关函数[9]-获取当前文件夹 GetCurrentDir
  7. 中兴通讯:已具备完整的5G端到端解决方案的能力
  8. ASP.NET MVC3 系列教程 - 如何使项目Debug进MVC3源代码
  9. Load error: undefined path variables 记录一次IDEA崩溃
  10. python从入门到精通 明日科技 电子书-python从入门到项目实践 (明日科技) 配套视频教程+源码...
  11. 爬虫套路知多少?反爬策略是关键
  12. C#常用操作类库一(验证类)
  13. cad导出pdf_手机如何一键分享CAD图纸?(差点成了背锅大侠)
  14. 毕业设计之 ---- 基于JAVA WEB的网上购物系统的设计与实现
  15. python 直方图匹配_python库skimage 绘制直方图;绘制累计直方图;实现直方图匹配(histogram matching)...
  16. 爬取国家统计局数据正式篇
  17. 惠普打印机双击之后没有扫描_惠普打印机 找不到 扫描图标 怎么办,急需扫描一些证件 ,求救...
  18. c语言统计大写英文字母的个数,c语言 对任意输入的字符串,统计其中的大写字母和小写字母的个数...
  19. 8.15美团笔试和奇葩赛码网的输入坑
  20. 基于servlet+jsp 个人博客系统

热门文章

  1. 最新28个很棒的 jQuery 教程
  2. Java Selenium Actions模拟鼠标拖动dragAndDrop总结
  3. 监控聚币网行情 并实时发送到微信
  4. php实现多进程、多线程
  5. Go笔试题目Go与PHP分别实现方法
  6. Vue的axios与ajax的区别:axios是对ajax的封装
  7. Git的强制操作:强制推送[项目中千万不要用] 强制下拉
  8. Git的配置SSHKey
  9. jQuery的eval
  10. 原生APP与web APP的区别