精华内容
下载资源
问答
  • 深度学习多变量时间序列预测:GRU算法构建时间序列多变量模型预测交通流量+代码实战
    千次阅读
    2021-06-07 15:14:35

    深度学习多变量时间序列预测:GRU算法构建时间序列多变量模型预测交通流量+代码实战

     

    GRU是LSTM网络的一种效果很好的变体,它较LSTM网络的结构更加简单,而且效果也很好,因此也是当前非常流形的一种网络。GRU既然是LSTM的变体,因此也是可以解决RNN网络中的长依赖问题。

    在LSTM中引入了三个门函数:输入门、遗忘门和输出门来控制输入值、记忆值和输出值。而在GRU模型中只有两个门:分别是更新门和重置门。

    GRU的结构如上图所示,虽然有时候GRU被视为LSTM的一个variation,不过两者差别还是比较大的,所以单独讨论。

    GRU不像LSTM的三门控,它虽然也有门,但是只有两个,分别叫做重置门(reset gate),和更新门(update gate)。重置门顾名思义,控制着是否重置,也就是说多大程度上擦除以前的状态state;更新门则表示,多大程度上要用candidate 来更新当前的hidden layer。下面是另一种示意图,以及它的公式:

    其实说到底,不论是LSTM还是GRU,重点都在于我们应该如何利用长期记忆这一点,在LSTM中长期记忆会影响到某一时刻的模型输出,而GRU则直接把某一时刻的长期记忆作为输出,一边修改长期记忆一边进行输出,所以这使得GRU比LSTM具有更少的输入(LSTM有三个输入,GRU只有两个࿰

    更多相关内容
  • 多变量时间序列开发通道深度卷积神经网络
  • 变量LSTM当前神经网络用于多变量时间序列的预测和解释 郭,田,陶林和Nino Antulov-Fantulin。 “在变量数据上探索可解释的LSTM神经网络。” 国际机器学习会议(ICML)。 2019。 郭涛,林涛,卢Y.自回归外生...
  • 介绍了多变量时间序列相空间重构理论. 提出一种新的基于平均预测误差最小化的重构参数确定方法, 阐 述了该方法的算法过程及一些重要特点. 此方法考虑了所有重构参数对平均预测误差的影响, 能够同时确定重构系...
  • 根据单变量时间序列相空间重构思想,提出了多变量时间序列描述的复杂系统的相空间延迟重构方法。对每一分量的时间序列,分别利用互信息最小法确定最佳延迟时间间隔,最小嵌入维数的选取方法是单变量时间序列情况下...
  • 使用VAR模型和复杂网络测度对多变量时间序列进行因果分析
  • Seglearn是一个使用滑动窗口分割的机器学习时间序列的python包。 它为分割,特征提取,特征处理和最终估计提供了一个集成管道。 Seglearn为分类,回归和预测问题提供了多元时间序列和上下文数据的灵活方法。 它与...
  • LS-Cluster:大规模多变量时间序列聚类方法
  • 根据时间尺度与多维超体体积之间的测度关系, 提出一种多变量时间序列分形维数的计算方法. 通过4 种典型混沌动力学系统所产生的多变量时间序列及其相应不同信噪比混杂序列的仿真计算表明, 所提出方法时间复杂度较低,...
  • LSTM多变量时间序列预测

    千次阅读 多人点赞 2021-03-27 20:40:42
    基于LSTM多变量时间序列预测

    从这篇博客你将学到

    (1) 何为时间序列
    (2) 多变量时间序列建模
    (3) 基于LSTM模型的时间序列预测
    (4) 如何免费加入交流群

    时间序列

    我们常说历史总是惊人的相似,时间序列预测正式依循这个道理来预测未来,时间序列英文名称为Time Series,简称TS,其假设某变量的值构成的序列依赖于时间,随着时间的变化而变化,如果时间确定了,这个变量的值也就确定了,任何一个时刻都是可以度量的,因为从现在起未来的某一时间是可以通过现在时间演算的,同时,随着时间的变化,变量往往会呈现出某些特殊的结构特征,如上升或下降的大体趋势,季节性变动,一些循环往复的周期变动,还有一些不规则变动,而这些特质往往是可以捕捉的,所以常用时间序列模型来预测未来某一确定时间的变量的值。下图是早些年某国的航空乘客人数统计数据

    Figure_1  航空乘客人数统计数据

    我们用折线图将每月的航空乘客人数描绘出来

    Figure_2  航空乘客人数曲线图

    很明显可以看到航空乘客人数总体呈上升趋势,同时出现每隔一段时间上升隔一段时间下降的周期性特征,每个周期变动之间又蕴含一些细微的波动。针对不同特征的时间序列数据可以构建不同的模型,常见的时间序列模型有
    (1) AR(Autoregressive model)自回归模型
    (2) MA(Moving Average Model)移动平均模型
    (3) ARMA(Auto Regressive and Moving Average Model)自回归滑动平均模型
    (4) ARIMA(Autoregressive Integrated Moving Average model)差分回归移动平均模型
    (5) VAR(Vector autoregression)矢量自回归模型模型
    (6) SVAR(Structural VAR)结构自回归模型

    多变量时间序列

    平常我们构建的大多属于单变量时间序列,在构建预测模型的时候往往只有时间和变量本身可以参考,而这样的变量往往会显得很单薄,同时,时间往往是解释性因子而不是因果性因子,就以每月航空乘客人数为例,如果说成因为是某年某月,所以航空乘客人数是多少多少,恐怕太牵强了,所以还需要考虑其他影响因素,比如天气,航线,节假日等,于是就有了多变量时间序列,多变量时间序列是指除了时间依赖外,还有其他因素共同影响某一结果的发生。例如下表是某地的气象监控数据

    Figure_3  某地气象监控数据

    其中包含时间,温度,云层覆盖率,露点、风速及风向等,在这种情况下,云层覆盖率,露点、风速及风向都有可能被认为是影响温度的因果原因,而时间只是恰巧发生在此时此刻的一个表现因子。这时候建模就可以建立既包含因果原因和又包含表现原因在内的多变量时间序列模型。

    多变量时间序列建模

    假设数据如下所示

    ( x 11 x 12 ⋯ x 1 n y 1 x 21 x 22 ⋯ x 2 n y 2 ⋮ ⋮ ⋮ ⋮ x m 1 x m 2 ⋯ x m n y m ) \left( \begin{matrix} x_{11} & x_{12} & \cdots & x_{1n} & y_1 \\ x_{21} & x_{22} & \cdots & x_{2n} & y_2 \\ \vdots & \vdots & & \vdots & \vdots \\ x_{m1} & x_{m2} & \cdots & x_{mn} & y_m \\ \end{matrix} \right) x11x21xm1x12x22xm2x1nx2nxmny1y2ym

    其中 x i j ( 1 ≤ i ≤ m , 1 ≤ j ≤ n ) x_{ij}(1\leq i\leq m, 1\leq j \leq n) xij(1im,1jn) 表示第 i i i期的第 j j j个特征的值,先从最简单的开始

    (1) 一阶滞后

    为了预测第 m m m 期的 y m y_m ym值,我们可以利用第 m − 1 m-1 m1期的所有信息

    ( x m − 1 , 1 , x m − 1 , 2 , ⋯   , x m − 1 , n , y m − 1 ) (x_{m-1,1} , x_{m-1,2} , \cdots , x_{m-1,n} , y_{m-1}) (xm1,1,xm1,2,,xm1,n,ym1)

    建立第 m m m 期的 y m y_m ym值与第 m − 1 m-1 m1期所有信息的线性模型
    y m = w 0 y m − 1 + w 1 x m − 1 , 1 + w 2 x m − 1 , 2 + ⋯ + w n x m − 1 , n + ϵ y_m= w_0y_{m-1}+w_1x_{m-1,1}+w_2x_{m-1,2} + \cdots + w_nx_{m-1,n}+\epsilon ym=w0ym1+w1xm1,1+w2xm1,2++wnxm1,n+ϵ

    而不是仅仅利用第 m − 1 m-1 m1期的表征 y m − 1 y_{m-1} ym1单一信息, 这就是多变量时间序列的优势,再推广到p阶滞后。

    (2) p阶滞后

    我们亦可以利用第 m − p m-p mp 到第 m − 1 m-1 m1期的所有信息来进行预测

    ( x m − p , 1 x m − p , 2 ⋯ x m − p , n y m − p x m − p + 1 , 1 x m − p + 1 , 2 ⋯ x m − p + 1 , n y m − p + 1 ⋮ ⋮ ⋮ ⋮ x m − 1 , 1 x m − 1 , 2 ⋯ x m − 1 , n y m − 1 ) \left( \begin{matrix} x_{m-p,1} & x_{m-p,2} & \cdots & x_{m -p, n} & y_{m-p} \\ x_{m-p+1,1} & x_{m-p+1,2} & \cdots & x_{m-p+1,n} & y_{m-p+1} \\ \vdots & \vdots & & \vdots & \vdots \\ x_{m-1,1} & x_{m-1,2} & \cdots & x_{m-1,n} & y_{m-1} \\ \end{matrix} \right) xmp,1xmp+1,1xm1,1xmp,2xmp+1,2xm1,2xmp,nxmp+1,nxm1,nympymp+1ym1

    写成向量形式就是

    y m = W 0 Y m − i + W m − 1 X m − 1 + W m − 2 X m − 2 + W m − 3 X m − 3 + ⋯ + W m − p X m − p + ϵ y_m = W_0Y_{m-i}+ W_{m-1}X_{m-1}+W_{m-2}X_{m-2}+W_{m-3}X_{m-3}+\cdots+W_{m-p}X_{m-p}+\epsilon ym=W0Ymi+Wm1Xm1+Wm2Xm2+Wm3Xm3++WmpXmp+ϵ

    其中 X m − i X_{m-i} Xmi表示前 i ( 1 ≤ i ≤ p ) i(1\leq i\leq p) i(1ip)期的特征向量
    ( x m − i , 1 , x m − i , 2 , ⋯   , x m − i , n , y m − i ) T (x_{m-i,1}, x_{m-i,2},\cdots,x_{m-i,n},y_{m-i} )^T (xmi,1,xmi,2,,xmi,n,ymi)T

    W m − i W_{m-i} Wmi表示前 i ( 1 ≤ i ≤ p ) i(1\leq i\leq p) i(1ip)期的特征向量的系数

    ( w m − i , 1 , w m − i , 2 , ⋯   , w m − i , n , w m − i ) (w_{m-i,1}, w_{m-i,2},\cdots,w_{m-i,n},w_{m-i} ) (wmi,1,wmi,2,,wmi,n,wmi)

    Y m − i Y_{m-i} Ymi表示前 i i i期的表征值, ϵ \epsilon ϵ服从均值为0的高斯分布,这样第 m m m期的表征完全可以通过第 m − p m-p mp到第 m − 1 m-1 m1期的特征变量线性表出。与单变量时间序列不同,多变量时间序列不仅利用了纵向的时间特征还利用横向的其他特征,所以多变量时间序列不仅能够时间带来的沧桑变化也能够理解和使用多个变量之间的关系,这有助于描述数据的动态行为,并提供更好的预测结果。

    LSTM模型

    LSTM是一种时间递归神经网络,它出现的原因是为了解决RNN的一个致命的缺陷。原生的RNN会遇到一个很大的问题,叫做The vanishing gradient problem for RNNs,也就是后面时间的节点会出现老年痴呆症,也就是忘事儿,这使得RNN在很长一段时间内都没有受到关注,网络只要一深就没法训练。后来有些大牛们开始使用递归神经网络来对时间关系进行建模。而根据深度学习三大牛的阐述,LSTM网络已被证明比传统的RNNS更加有效。

    适合多输入变量的神经网络模型一直让开发人员很头痛,但基于(LSTM)的循环神经网络能够几乎可以完美的解决多个输入变量的问题。

    基于LSTM的循环神经网络可以很好的利用在时间序列预测上,因为很多古典的线性方法难以适应多变量或多输入预测问题。下面我们通过一个案例来看看LSTM在多元时间序列预测上的表现。

    实践项目

    通过本案例实践,你将学会

    • 如何将原始数据集转换为可用于时间序列预测的数据集;
    • 如何准备数据并创建适应多变量时间序列预测问题的LSTM;
    • 如何做出预测并将结果重新调整到原始单位;

    原始pm2.5数据

    在这个案例中,我们将使用PM2.5空气质量数据集,是美国驻北京大使馆五年内收集的PM2.5污染水平及天气情况。字段包括时间、PM2.5浓度、以及一些关键天气信息,详细字段释义如下(需要这份数据的朋友可以来三行科创交流群获取)

    NO:行号。
    year:年。
    month:月。
    day:日。
    hour:小时。
    pm2.5:PM2.5浓度。
    DEWP:露点温度。
    TEMP:温度。
    PRES:压力。
    cbwd:风向。
    Iws:风速。
    ls:积雪的时间
    Ir:累积的下雨时数

    我们可以使用这些数据并构建一个预测问题,基于前一个或几个小时天气条件和PM2.5的污染,预测在下一个小时的PM2.5的污染值。

    第一步 导入用到的库

    本案例是基于keras深度学习库完成多变量时间序列模型的开发,涉及到的库比较多

    # -*- encoding: utf-8 -*-
    '''
    @Project :   LSTM多变量时间序列预测
    @Desc    :   利用LSTM模型进行多变量时间啊序列预测
    @Time    :   2021/03/21 12:16:13
    @Author  :   帅帅de三叔,zengbowengood@163.com
    '''
    
    import math
    import pandas as pd
    from datetime import datetime
    import matplotlib.pyplot as plt
    from pandas.core.algorithms import mode
    from sklearn.preprocessing import LabelEncoder, MinMaxScaler
    from tensorflow.python.keras.backend import concatenate
    from sklearn.metrics import mean_squared_error
    from tensorflow.python.keras.callbacks import History
    from series_to_supervised import series_to_supervised
    from keras.models import Sequential
    from keras.layers import Dense, Activation, Embedding, LSTM
    

    第二步 数据探索

    数据探索主要是查看原始数据的缺失情况,完整度怎么样,有没有明显的谬误等,对数据及数据之间有个感性的认真,如果能够画出原数据的图像那会更直观。

    dataset = pd.read_csv("raw.csv", index_col= "datetime", parse_dates = {"datetime":['year', 'month', 'day', 'hour']}, date_parser= lambda x:datetime.strptime(x,'%Y %m %d %H')) #读取数据并拼接时间
    dataset.drop("No", axis = 1, inplace = True) #去掉No列
    dataset.columns = ["pm25", "dew",  "temp", "press", "wnd_dir", "wnd_spd", "snow", "rain"] #重命名表头
    dataset.dropna(subset = ['pm25'], inplace = True) #去掉pm25为空的行
    values = dataset.values #数值特征变量
    groups = [0, 1, 2, 3, 5, 6, 7]
    i = 1
    plt.figure() #新建画布
    for group in groups:
        plt.subplot(len(groups), 1, i) #子图
        plt.plot(values[:, group]) #折线图
        plt.title(dataset.columns[group], y = 0.5, fontsize = 10, loc = "right") #取字段为子图标题
        i +=1
    plt.show()
    

    Figure_4 特征长什么模样

    第三步 特征工程

    将原数据处理成LSTM模型能够识别的格式,并且保持LSTM模型的输入格式要求(samples, timesteps, features),同时数据集进行划分,然后将训练集和测试集,要注意这里是需要学习到时间因数,所以在训练集和测试集划分上不能破坏数据原有的序列,可以按照时间切分,比如这里用第一年数据进行训练,用剩下的4年进行评估。

    encoder = LabelEncoder() #编码
    values[:,4] = encoder.fit_transform(values[:,4]) #将第4列编码
    values = values.astype('float32') #使得所有数值类型都是float类型
    scaler = MinMaxScaler(feature_range = (0, 1)) #0-1归一化
    scaled = scaler.fit_transform(values)
    reframed = series_to_supervised(scaled, 1, 1) #调用series_to_supervised函数将数据转为监督数据变成16列
    reframed.drop(reframed.columns[[9, 10, 11, 12, 13, 14, 15]], axis= 1,inplace = True) 
    values = reframed.values
    n_train_hours = 365*24 #一年的小时数
    train = values[:n_train_hours, :] #训练集
    test = values[n_train_hours:, :] #测试集
    train_x, train_y = train[:, :-1], train[:, -1] #训练集特征和标签 
    test_x, test_y = test[:, :-1], test[:, -1] #测试集的特征和标签
    train_x = train_x.reshape((train_x.shape[0], 1, train_x.shape[1])) #转为LSTM模型的输入格式(samples, timesteps, features)
    test_x = test_x.reshape((test_x.shape[0], 1, test_x.shape[1])) #转为LSTM模型的输入格式(samples, timesteps, features)
    

    第四步 设计LSTM模型

    模型的设计是很关键的一环,一个简洁高效的模型往往能够使得训练和验证结果事半功倍,这里隐藏层有50个神经元,输出层1个神经元(回归问题),输入变量是一个时间步(t-1)的特征,损失函数采用Mean Absolute Error(MAE),优化算法采用Adam,模型采用50个epochs并且每个batch的大小为72, shuffle要设置成False,随后画出测试集的误差曲线和训练集的误差曲线。

    model = Sequential()
    model.add(LSTM(50, input_shape = (train_x.shape[0], train_x.shape[2]))) #8760*8
    model.add(Dense(1))
    model.compile(loss = "mae",optimizer= "adam")
    history =model.fit(train_x, train_y, epochs= 50, batch_size=72, validation_data=(test_x, test_y), verbose=2, shuffle=False)
    plt.figure()
    plt.plot(history.history["loss"], label = "train")
    plt.plot(history.history["val_loss"], label = "test")
    plt.legend()
    plt.show()
    

    Figure_5  训练损失与测试损失

    第五步 模型的评估

    一个模型的好坏还需要进行严格的评估工作,需要将预测结果和部分测试集数据组合然后进行比例反转(invert the scaling),同时也需要将测试集上的预期值也进行比例转换。至于在这里为什么进行比例反转,是因为我们将原始数据进行了预处理(连同输出值y),此时的误差损失计算是在处理之后的数据上进行的,为了计算在原始比例上的误差需要将数据进行转化,同时反转时的矩阵大小一定要和原来的大小(shape)完全相同,否则就会报错。通过以上处理之后,再结合RMSE(均方根误差)计算损失。

    yhat = model.predict(test_x)
    test_x = test_x.reshape((test_x.shape[0], test_x.shape[2]))
    inv_yhat = concatenate((yhat,test_x[:, 1:]), axis = 1)
    inv_yhat = scaler.inverse_transform(inv_yhat)
    inv_yhat = inv_yhat[:, 0]
    
    test_y = test_y.reshape((len(test_y), 1))
    inv_y = concatenate((test_y, test_x[:, 1:]), axis =1)
    inv_y = scaler.inverse_transform(inv_y)
    inv_y = inv_y[:, 0]
    rmse = math.sqrt(mean_squared_error(inv_y, inv_yhat))
    print("the rmse is: %.3f" %rmse)
    

    最后均方根误差值保持在26附近。

    进一步思考

    (1)在数据处理可以尝试的

    1. 加入季节特征;
    2. 时间步长大于1。
    3. 舍去一些影响不大的特征

    (2)在设计模型的时候可以尝试

    1. 隐藏层神经元个数,
    2. 优化算法
    3. 模型的epochs数,每个batch的大小

    参考资料

    1,https://www.analyticsvidhya.com/blog/2016/02/time-series-forecasting-codes-python/
    2,https://blog.csdn.net/qq_28031525/article/details/79046718
    3,https://www.analyticsvidhya.com/blog/2016/02/time-series-forecasting-codes-python/
    在这里插入图片描述

    展开全文
  • 针对目前时间序列决策研究方法的一些缺陷,提出了多变量时间序列模糊决策树挖掘方法,并给出了该方法的实验分析。实验结果证明该方法能够找出多变量时间序列子序列的形态与某个序列的后期趋势或状态的决策信息。
  • 多变量时间序列的异常识别与分类研究,这是一篇博士论文,该论文详细介绍了时间序列方面的挖掘。详细介绍了分类。
  • 基于聚类和神经网络的多变量时间序列预测方法,单傲,闫丹凤,多变量时间序列数据在日常生活中分布广泛,并且在很领域中得到广泛研究。但是其中仍然存在着一些挑战,比如提取时间序列内部的
  • 目前时间序列半监督分类研究主要集中在单变量时间序列,由于多变量时间序列(MTS)变量之间存在复杂关系,MTS的半监督分类研究比较少.针对这种情况,提出一种基于二维奇异值分解的MTS半监督分类方法,该方法首先计算...
  • PyTorch搭建LSTM实现多变量时间序列预测(负荷预测)

    I. 前言

    在前面的一篇文章PyTorch搭建LSTM实现时间序列预测(负荷预测)中,我们利用LSTM实现了负荷预测,但我们只是简单利用负荷预测负荷,并没有利用到其他一些环境变量,比如温度、湿度等。

    本篇文章主要考虑用PyTorch搭建LSTM实现多变量时间序列预测。

    系列文章:

    1. 深入理解PyTorch中LSTM的输入和输出(从input输入到Linear输出)
    2. PyTorch搭建LSTM实现时间序列预测(负荷预测)
    3. PyTorch搭建LSTM实现多变量时间序列预测(负荷预测)
    4. PyTorch搭建双向LSTM实现时间序列预测(负荷预测)
    5. PyTorch搭建LSTM实现多变量多步长时间序列预测(一):直接多输出
    6. PyTorch搭建LSTM实现多变量多步长时间序列预测(二):单步滚动预测
    7. PyTorch中实现LSTM多步长时间序列预测的几种方法总结(负荷预测)

    II. 数据处理

    数据集为某个地区某段时间内的电力负荷数据,除了负荷以外,还包括温度、湿度等信息。

    本文中,我们根据前24个时刻的负荷以及该时刻的环境变量来预测下一时刻的负荷。

    def nn_seq_ms(B):
        print('data processing...')
        dataset = load_data()
        # split
        train = dataset[:int(len(dataset) * 0.7)]
        test = dataset[int(len(dataset) * 0.7):len(dataset)]
    
        def process(data, batch_size):
            load = data[data.columns[1]]
            load = load.tolist()
            data = data.values.tolist()
            m, n = np.max(load), np.min(load)
            load = (load - n) / (m - n)
            seq = []
            for i in range(len(data) - 24):
                train_seq = []
                train_label = []
                for j in range(i, i + 24):
                    x = [load[j]]
                    for c in range(2, 8):
                        x.append(data[j][c])
                    train_seq.append(x)
                train_label.append(load[i + 24])
                train_seq = torch.FloatTensor(train_seq)
                train_label = torch.FloatTensor(train_label).view(-1)
                seq.append((train_seq, train_label))
    
            # print(seq[-1])
            seq = MyDataset(seq)
            seq = DataLoader(dataset=seq, batch_size=batch_size, shuffle=False, num_workers=0, drop_last=True)
    
            return seq, [m, n]
    
        Dtr, lis1 = process(train, B)
        Dte, lis2 = process(test, B)
    
        return Dtr, Dte, lis1, lis2
    

    上面代码用了DataLoader来对原始数据进行处理,最终得到了batch_size=B的数据集Dtr和Dte,Dtr为训练集,Dte为测试集。

    任意输出Dte中的一条数据:

    [(tensor([[0.3513, 0.0000, 0.9091, 0.0000, 0.6667, 0.3023, 0.2439],
            [0.3333, 0.0000, 0.9091, 0.0435, 0.6667, 0.3023, 0.2439],
            [0.3396, 0.0000, 0.9091, 0.0870, 0.6667, 0.3023, 0.2439],
            [0.3427, 0.0000, 0.9091, 0.1304, 0.6667, 0.3023, 0.2439],
            [0.3838, 0.0000, 0.9091, 0.1739, 0.6667, 0.3023, 0.2439],
            [0.3700, 0.0000, 0.9091, 0.2174, 0.6667, 0.3023, 0.2439],
            [0.4288, 0.0000, 0.9091, 0.2609, 0.6667, 0.3023, 0.2439],
            [0.4474, 0.0000, 0.9091, 0.3043, 0.6667, 0.3023, 0.2439],
            [0.4406, 0.0000, 0.9091, 0.3478, 0.6667, 0.3023, 0.2439],
            [0.4657, 0.0000, 0.9091, 0.3913, 0.6667, 0.3023, 0.2439],
            [0.4540, 0.0000, 0.9091, 0.4348, 0.6667, 0.3023, 0.2439],
            [0.4939, 0.0000, 0.9091, 0.4783, 0.6667, 0.3023, 0.2439],
            [0.4328, 0.0000, 0.9091, 0.5217, 0.6667, 0.3023, 0.2439],
            [0.4238, 0.0000, 0.9091, 0.5652, 0.6667, 0.3023, 0.2439],
            [0.4779, 0.0000, 0.9091, 0.6087, 0.6667, 0.3023, 0.2439],
            [0.4591, 0.0000, 0.9091, 0.6522, 0.6667, 0.3023, 0.2439],
            [0.4651, 0.0000, 0.9091, 0.6957, 0.6667, 0.3023, 0.2439],
            [0.5102, 0.0000, 0.9091, 0.7391, 0.6667, 0.3023, 0.2439],
            [0.5067, 0.0000, 0.9091, 0.7826, 0.6667, 0.3023, 0.2439],
            [0.4635, 0.0000, 0.9091, 0.8261, 0.6667, 0.3023, 0.2439],
            [0.4224, 0.0000, 0.9091, 0.8696, 0.6667, 0.3023, 0.2439],
            [0.3796, 0.0000, 0.9091, 0.9130, 0.6667, 0.3023, 0.2439],
            [0.3292, 0.0000, 0.9091, 0.9565, 0.6667, 0.3023, 0.2439],
            [0.2940, 0.0000, 0.9091, 1.0000, 0.6667, 0.3023, 0.2439]]), tensor([0.3675]))]
    

    每一行对应一个时刻点的负荷以及环境变量,此时input_size=7。

    III. LSTM模型

    这里采用了深入理解PyTorch中LSTM的输入和输出(从input输入到Linear输出)中的模型:

    class LSTM(nn.Module):
        def __init__(self, input_size, hidden_size, num_layers, output_size, batch_size):
            super().__init__()
            self.input_size = input_size
            self.hidden_size = hidden_size
            self.num_layers = num_layers
            self.output_size = output_size
            self.num_directions = 1 # 单向LSTM
            self.batch_size = batch_size
            self.lstm = nn.LSTM(self.input_size, self.hidden_size, self.num_layers, batch_first=True)
            self.linear = nn.Linear(self.hidden_size, self.output_size)
    
        def forward(self, input_seq):
            batch_size, seq_len = input_seq[0], input_seq[1]
            h_0 = torch.randn(self.num_directions * self.num_layers, self.batch_size, self.hidden_size).to(device)
            c_0 = torch.randn(self.num_directions * self.num_layers, self.batch_size, self.hidden_size).to(device)
            # output(batch_size, seq_len, num_directions * hidden_size)
            output, _ = self.lstm(input_seq, (h_0, c_0))
            pred = self.linear(output)
            pred = pred[:, -1, :]
            return pred
    

    IV. 训练

    def train(args, path, flag):
        Dtr, Dte, lis1, lis2 = load_data(args, flag, args.batch_size)
        input_size, hidden_size, num_layers = args.input_size, args.hidden_size, args.num_layers
        output_size = args.output_size
        if args.bidirectional:
            model = BiLSTM(input_size, hidden_size, num_layers, output_size, batch_size=args.batch_size).to(device)
        else:
            model = LSTM(input_size, hidden_size, num_layers, output_size, batch_size=args.batch_size).to(device)
    
        loss_function = nn.MSELoss().to(device)
        if args.optimizer == 'adam':
            optimizer = torch.optim.Adam(model.parameters(), lr=args.lr,
                                         weight_decay=args.weight_decay)
        else:
            optimizer = torch.optim.SGD(model.parameters(), lr=args.lr,
                                        momentum=0.9, weight_decay=args.weight_decay)
        scheduler = StepLR(optimizer, step_size=args.step_size, gamma=args.gamma)
        # training
        loss = 0
        for i in tqdm(range(args.epochs)):
            cnt = 0
            for (seq, label) in Dtr:
                cnt += 1
                seq = seq.to(device)
                label = label.to(device)
                y_pred = model(seq)
                loss = loss_function(y_pred, label)
                optimizer.zero_grad()
                loss.backward()
                optimizer.step()
                # if cnt % 100 == 0:
                #     print('epoch', i, ':', cnt - 100, '~', cnt, loss.item())
            print('epoch', i, ':', loss.item())
    
            scheduler.step()
    
        state = {'model': model.state_dict(), 'optimizer': optimizer.state_dict()}
        torch.save(state, path)
    

    V. 测试

    def test(args, path, flag):
        Dtr, Dte, lis1, lis2 = load_data(args, flag, args.batch_size)
        pred = []
        y = []
        print('loading model...')
        input_size, hidden_size, num_layers = args.input_size, args.hidden_size, args.num_layers
        output_size = args.output_size
        if args.bidirectional:
            model = BiLSTM(input_size, hidden_size, num_layers, output_size, batch_size=args.batch_size).to(device)
        else:
            model = LSTM(input_size, hidden_size, num_layers, output_size, batch_size=args.batch_size).to(device)
        # model = LSTM(input_size, hidden_size, num_layers, output_size, batch_size=args.batch_size).to(device)
        model.load_state_dict(torch.load(path)['model'])
        model.eval()
        print('predicting...')
        for (seq, target) in tqdm(Dte):
            target = list(chain.from_iterable(target.data.tolist()))
            y.extend(target)
            seq = seq.to(device)
            with torch.no_grad():
                y_pred = model(seq)
                y_pred = list(chain.from_iterable(y_pred.data.tolist()))
                pred.extend(y_pred)
    
        y, pred = np.array(y), np.array(pred)
        m, n = lis2[0], lis2[1]
        y = (m - n) * y + n
        pred = (m - n) * pred + n
        print('mape:', get_mape(y, pred))
        # plot
        x = [i for i in range(1, 151)]
        x_smooth = np.linspace(np.min(x), np.max(x), 900)
        y_smooth = make_interp_spline(x, y[150:300])(x_smooth)
        plt.plot(x_smooth, y_smooth, c='green', marker='*', ms=1, alpha=0.75, label='true')
    
        y_smooth = make_interp_spline(x, pred[150:300])(x_smooth)
        plt.plot(x_smooth, y_smooth, c='red', marker='o', ms=1, alpha=0.75, label='pred')
        plt.grid(axis='y')
        plt.legend()
        plt.show()
    

    我只是训练了30轮,MAPE为7.83%:在这里插入图片描述
    在这里插入图片描述

    VI. 源码及数据

    源码及数据我放在了GitHub上,下载时请随手给个follow和star,感谢!
    LSTM-Load-Forecasting

    展开全文
  • matlab eof代码
  • 使用 LSTM 进行多变量时间序列预测

    万次阅读 多人点赞 2022-01-11 10:13:30
    使用 LSTM 进行端到端时间序列预测的完整代码和详细解释。 在本文中我们将使用深度学习方法 (LSTM) 执行多元时间序列预测...对于单变量时间序列数据,我们将使用单列进行预测。 正如我们所见,只有一列,因此即将到来

    使用 LSTM 进行端到端时间序列预测的完整代码和详细解释。

    在本文中我们将使用深度学习方法 (LSTM) 执行多元时间序列预测。

    我们先来了解两个主题——

    • 什么是时间序列分析?
    • 什么是 LSTM?

    时间序列分析:时间序列表示基于时间顺序的一系列数据。 它可以是秒、分钟、小时、天、周、月、年。 未来的数据将取决于它以前的值。

    在现实世界的案例中,我们主要有两种类型的时间序列分析——

    • 单变量时间序列
    • 多元时间序列

    对于单变量时间序列数据,我们将使用单列进行预测。

    正如我们所见,只有一列,因此即将到来的未来值将仅取决于它之前的值。

    但是在多元时间序列数据的情况下,将有不同类型的特征值并且目标数据将依赖于这些特征。

    正如在图片中看到的,在多元变量中将有多个列来对目标值进行预测。 (上图中“count”为目标值)

    在上面的数据中,count不仅取决于它以前的值,还取决于其他特征。因此,要预测即将到来的count值,我们必须考虑包括目标列在内的所有列来对目标值进行预测。

    在执行多元时间序列分析时必须记住一件事,我们需要使用多个特征预测当前的目标,让我们通过一个例子来理解 -

    在训练时,如果我们使用 5 列 [feature1, feature2, feature3, feature4, target] 来训练模型,我们需要为即将到来的预测日提供 4 列 [feature1, feature2, feature3, feature4]。

    LSTM

    本文中不打算详细讨论LSTM。所以只提供一些简单的描述,如果你对LSTM没有太多的了解,可以参考我们以前发布的文章。

    LSTM基本上是一个循环神经网络,能够处理长期依赖关系。

    假设你在看一部电影。所以当电影中发生任何情况时,你都已经知道之前发生了什么,并且可以理解因为过去发生的事情所以才会有新的情况发生。RNN也是以同样的方式工作,它们记住过去的信息并使用它来处理当前的输入。RNN的问题是,由于渐变消失,它们不能记住长期依赖关系。因此为了避免长期依赖问题设计了lstm。

    现在我们讨论了时间序列预测和LSTM理论部分。让我们开始编码。

    让我们首先导入进行预测所需的库

    import numpy as np
    import pandas as pd
    from matplotlib import pyplot as plt
    from tensorflow.keras.models import Sequential
    from tensorflow.keras.layers import LSTM
    from tensorflow.keras.layers import Dense, Dropout
    from sklearn.preprocessing import MinMaxScaler
    from keras.wrappers.scikit_learn import KerasRegressor
    from sklearn.model_selection import GridSearchCV
    

    加载数据,并检查输出-

    df=pd.read_csv("train.csv",parse_dates=["Date"],index_col=[0])
    df.head()
    

    df.tail()
    

    现在让我们花点时间看看数据:csv文件中包含了谷歌从2001-01-25到2021-09-29的股票数据,数据是按照天数频率的。

    [如果您愿意,您可以将频率转换为“B”[工作日]或“D”,因为我们不会使用日期,我只是保持它的现状。]

    这里我们试图预测“Open”列的未来值,因此“Open”是这里的目标列

    让我们看一下数据的形状

    df.shape
    (5203,5)
    

    现在让我们进行训练测试拆分。这里我们不能打乱数据,因为在时间序列中必须是顺序的。

    test_split=round(len(df)*0.20)
    df_for_training=df[:-1041]
    df_for_testing=df[-1041:]
    print(df_for_training.shape)
    print(df_for_testing.shape)
    
    (4162, 5)
    (1041, 5)
    

    可以注意到数据范围非常大,并且它们没有在相同的范围内缩放,因此为了避免预测错误,让我们先使用MinMaxScaler缩放数据。(也可以使用StandardScaler)

    scaler = MinMaxScaler(feature_range=(0,1))
    df_for_training_scaled = scaler.fit_transform(df_for_training)
    df_for_testing_scaled=scaler.transform(df_for_testing)
    df_for_training_scaled
    

    将数据拆分为X和Y,这是最重要的部分,正确阅读每一个步骤。

    def createXY(dataset,n_past):
        dataX = []
        dataY = []
        for i in range(n_past, len(dataset)):
                dataX.append(dataset[i - n_past:i, 0:dataset.shape[1]])
                dataY.append(dataset[i,0])
        return np.array(dataX),np.array(dataY)
    
    trainX,trainY=createXY(df_for_training_scaled,30)
    testX,testY=createXY(df_for_testing_scaled,30)
    

    让我们看看上面的代码中做了什么:

    N_past是我们在预测下一个目标值时将在过去查看的步骤数。

    这里使用30,意味着将使用过去的30个值(包括目标列在内的所有特性)来预测第31个目标值。

    因此,在trainX中我们会有所有的特征值,而在trainY中我们只有目标值。

    让我们分解for循环的每一部分

    对于训练,dataset = df_for_training_scaled, n_past=30

    当i= 30:

    data_X.addend (df_for_training_scaled[i - n_past:i, 0:df_for_training.shape[1]])

    从n_past开始的范围是30,所以第一次数据范围将是-[30 - 30,30,0:5] 相当于 [0:30,0:5]

    因此在dataX列表中,df_for_training_scaled[0:30,0:5]数组将第一次出现。

    现在, dataY.append(df_for_training_scaled[i,0])

    i = 30,所以它将只取第30行开始的open(因为在预测中,我们只需要open列,所以列范围仅为0,表示open列)。

    第一次在dataY列表中存储df_for_training_scaled[30,0]值。

    所以包含5列的前30行存储在dataX中,只有open列的第31行存储在dataY中。然后我们将dataX和dataY列表转换为数组,它们以数组格式在LSTM中进行训练。

    我们来看看形状。

    print("trainX Shape-- ",trainX.shape)
    print("trainY Shape-- ",trainY.shape)
    
    (4132, 30, 5)
    (4132,)
    
    print("testX Shape-- ",testX.shape)
    print("testY Shape-- ",testY.shape)
    
    (1011, 30, 5)
    (1011,)
    

    4132 是 trainX 中可用的数组总数,每个数组共有 30 行和 5 列, 在每个数组的 trainY 中,我们都有下一个目标值来训练模型。

    让我们看一下包含来自 trainX 的 (30,5) 数据的数组之一 和 trainX 数组的 trainY 值

    print("trainX[0]-- \n",trainX[0])
    print("trainY[0]-- ",trainY[0])
    

    如果查看 trainX[1] 值,会发现到它与 trainX[0] 中的数据相同(第一列除外),因为我们将看到前 30 个来预测第 31 列,在第一次预测之后它会自动移动 到第 2 列并取下一个 30 值来预测下一个目标值。

    让我们用一种简单的格式来解释这一切——

    trainX — — →trainY
    
    [0 : 30,0:5] → [30,0]
    
    [1:31, 0:5] → [31,0]
    
    [2:32,0:5] →[32,0]
    

    像这样,每个数据都将保存在 trainX 和 trainY 中

    现在让我们训练模型,我使用 girdsearchCV 进行一些超参数调整以找到基础模型。

    def build_model(optimizer):
        grid_model = Sequential()
        grid_model.add(LSTM(50,return_sequences=True,input_shape=(30,5)))
        grid_model.add(LSTM(50))
        grid_model.add(Dropout(0.2))
        grid_model.add(Dense(1))
    
    grid_model.compile(loss = 'mse',optimizer = optimizer)
        return grid_modelgrid_model = KerasRegressor(build_fn=build_model,verbose=1,validation_data=(testX,testY))
    
    parameters = {'batch_size' : [16,20],
                  'epochs' : [8,10],
                  'optimizer' : ['adam','Adadelta'] }
    
    grid_search  = GridSearchCV(estimator = grid_model,
                                param_grid = parameters,
                                cv = 2)
    

    如果你想为你的模型做更多的超参数调整,也可以添加更多的层。 但是如果数据集非常大建议增加 LSTM 模型中的时期和单位。

    在第一个 LSTM 层中看到输入形状为 (30,5)。 它来自 trainX 形状。 (trainX.shape[1],trainX.shape[2]) → (30,5)

    现在让我们将模型拟合到 trainX 和 trainY 数据中。

    grid_search = grid_search.fit(trainX,trainY)
    

    由于进行了超参数搜索,所以这将需要一些时间来运行。

    你可以看到损失会像这样减少——

    现在让我们检查模型的最佳参数。

    grid_search.best_params_
    
    {‘batch_size’: 20, ‘epochs’: 10, ‘optimizer’: ‘adam’}
    

    将最佳模型保存在 my_model 变量中。

    my_model=grid_search.best_estimator_.model
    

    现在可以用测试数据集测试模型。

    prediction=my_model.predict(testX)
    print("prediction\n", prediction)
    print("\nPrediction Shape-",prediction.shape)
    

    testY 和 prediction 的长度是一样的。 现在可以将 testY 与预测进行比较。

    但是我们一开始就对数据进行了缩放,所以首先我们必须做一些逆缩放过程。

    scaler.inverse_transform(prediction)
    

    报错了,这是因为在缩放数据时,我们每行有 5 列,现在我们只有 1 列是目标列。

    所以我们必须改变形状来使用 inverse_transform

    prediction_copies_array = np.repeat(prediction,5, axis=-1)
    

    5 列值是相似的,它只是将单个预测列复制了 4 次。所以现在我们有 5 列相同的值 。

    prediction_copies_array.shape
    (1011,5)
    

    这样就可以使用 inverse_transform 函数。

    pred=scaler.inverse_transform(np.reshape(prediction_copies_array,(len(prediction),5)))[:,0]
    

    但是逆变换后的第一列是我们需要的,所以我们在最后使用了 → [:,0]。

    现在将这个 pred 值与 testY 进行比较,但是 testY 也是按比例缩放的,也需要使用与上述相同的代码进行逆变换。

    original_copies_array = np.repeat(testY,5, axis=-1)
    original=scaler.inverse_transform(np.reshape(original_copies_array,(len(testY),5)))[:,0]
    

    现在让我们看一下预测值和原始值 →

    print("Pred Values-- " ,pred)
    print("\nOriginal Values-- " ,original)
    

    最后绘制一个图来对比我们的 pred 和原始数据。

    plt.plot(original, color = 'red', label = 'Real Stock Price')
    plt.plot(pred, color = 'blue', label = 'Predicted Stock Price')
    plt.title('Stock Price Prediction')
    plt.xlabel('Time')
    plt.ylabel('Google Stock Price')
    plt.legend()
    plt.show()
    

    看样子还不错,到目前为止,我们训练了模型并用测试值检查了该模型。 现在让我们预测一些未来值。

    从主 df 数据集中获取我们在开始时加载的最后 30 个值[为什么是 30? 因为这是我们想要的过去值的数量,来预测第 31 个值]

    df_30_days_past=df.iloc[-30:,:]
    df_30_days_past.tail()
    

    可以看到有包括目标列(“Open”)在内的所有列。现在让我们预测未来的 30 个值。

    在多元时间序列预测中,需要通过使用不同的特征来预测单列,所以在进行预测时我们需要使用特征值(目标列除外)来进行即将到来的预测。

    这里我们需要“High”、“Low”、“Close”、“Adj Close”列的即将到来的 30 个值来对“Open”列进行预测。

    df_30_days_future=pd.read_csv("test.csv",parse_dates=["Date"],index_col=[0])
    df_30_days_future
    

    剔除“Open”列后,使用模型进行预测之前还需要做以下的操作:

    缩放数据,因为删除了‘Open’列,在缩放它之前,添加一个所有值都为“0”的Open列。

    缩放后,将未来数据中的“Open”列值替换为“nan”

    现在附加 30 天旧值和 30 天新值(其中最后 30 个“打开”值是 nan)

    df_30_days_future["Open"]=0
    df_30_days_future=df_30_days_future[["Open","High","Low","Close","Adj Close"]]
    old_scaled_array=scaler.transform(df_30_days_past)
    new_scaled_array=scaler.transform(df_30_days_future)
    new_scaled_df=pd.DataFrame(new_scaled_array)
    new_scaled_df.iloc[:,0]=np.nan
    full_df=pd.concat([pd.DataFrame(old_scaled_array),new_scaled_df]).reset_index().drop(["index"],axis=1)
    

    full_df 形状是 (60,5),最后第一列有 30 个 nan 值。

    要进行预测必须再次使用 for 循环,我们在拆分 trainX 和 trainY 中的数据时所做的。 但是这次我们只有 X,没有 Y 值

    full_df_scaled_array=full_df.values
    all_data=[]
    time_step=30
    for i in range(time_step,len(full_df_scaled_array)):
        data_x=[]
        data_x.append(
         full_df_scaled_array[i-time_step :i , 0:full_df_scaled_array.shape[1]])
        data_x=np.array(data_x)
        prediction=my_model.predict(data_x)
        all_data.append(prediction)
        full_df.iloc[i,0]=prediction
    

    对于第一个预测,有之前的 30 个值,当 for 循环第一次运行时它会检查前 30 个值并预测第 31 个“Open”数据。

    当第二个 for 循环将尝试运行时,它将跳过第一行并尝试获取下 30 个值 [1:31] 。这里会报错错误因为Open列最后一行是 “nan”,所以需要每次都用预测替换“nan”。

    最后还需要对预测进行逆变换→

    new_array=np.array(all_data)
    new_array=new_array.reshape(-1,1)
    prediction_copies_array = np.repeat(new_array,5, axis=-1)
    y_pred_future_30_days = scaler.inverse_transform(np.reshape(prediction_copies_array,(len(new_array),5)))[:,0]
    print(y_pred_future_30_days)
    

    这样一个完整的流程就已经跑通了。

    如果你想看完整的代码,可以在这里查看:

    https://www.overfit.cn/post/1a36216705f2441b80fca567ea61e365

    作者:Sksujanislam

    展开全文
  • 该算法首先对原始多变量时间序列数据进行分块处理,然后对分块得到的子矩阵采用CPCA、2DSVD进行特征提取,从而得到代替原始模式的低维新模式,最后在低维空间中利用最小距离法构建分类器对多变量时间序列进行分类。...
  • 对于较为简单的时间序列预测问题,可以使用Exponential Smoothing和ARIMA等传统模型非常方便地求解。然而,对于复杂的时间序列预测问题,LSTM不失为一种很好的选择。因此,本文旨在探讨如何利用LSTM神经网络求解时间...
  • 多变量时间序列异常样本的识别 多变量时间序列异常样本的识别
  • 多变量时间序列相似度量

    千次阅读 2019-08-06 21:07:13
    变量时间序列可以看成是向量,其相似度量最常用的两种方法是欧式距离和DTW,将其应用到多元时间序列(可用矩阵存储表达)。 令Q为多元时间序列矩阵,该时间序列共有n个变量,即有n列,每一列维度为m。再令C为另一...
  • 基于异常序列剔除的多变量时间序列结构化预测.pdf
  • 变量 时间序列 降维 模式 异常 多变量时间序列的降维_模式匹配与异常检测
  • 深度学习多变量时间序列预测:GRU算法构建多变量时间序列预测模型+代码实战 注意参考:深度学习多变量时间序列预测:GRU算法构建单变量时间序列预测模型+代码实战 GRU(Gate Recurrent Unit)是循环神经网络...
  • 来源:机器之心本文长度为2527字,建议阅读5分钟本文为你介绍如何在Keras深度学习库中搭建用于多变量时间序列预测的LSTM模型。长短期记忆循环神经网络等几乎可以完美地模拟个输入变量的问题,这为时间序列预测带来...
  • DR 针对当前大部分时间序列异常检测方法未考虑不同时间序列间相关性的问题,论文中提出了一种新颖的自监督学习框架 MTAD-GAT 进行多变量时间序列异常检测。MTAD-GAT 考虑将每个单指标时间序列作为特征,然后利用 2...
  • 在Keras中使用LSTM模型进行多变量时间序列预测

    万次阅读 多人点赞 2019-08-25 20:59:50
    今天我给大家介绍一个国外深度学习大牛Jason Brownlee写的一篇关于多变量时间序列预测的博客,我在原文的代码基础上做了一点点修改,只是为了便于大家更好的理解。在本文中,您将了解如何在Keras深度学习库中为...
  • 根据时间序列的散点图、自相关函数和偏自相关函数图识别其平稳性。 2、对非平稳的时间序列数据进行平稳化处理。直到处理后的自相关函数和偏自相关函数的数值非显著非零。 3、根据所识别出来的特征建立相应的时间序列...
  • 本书 是关于时间序列一本经典教材,从网上找了很教材,这本教材还是比较生动和深刻的,想学习时间序列相关的原理和实践有空可以看一下。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 348,083
精华内容 139,233
关键字:

多变量时间序列

友情链接: 波动指标4.17.rar