精华内容
下载资源
问答
  • 时间序列预测模型

    2017-06-22 22:07:03
    时间序列模型时间序列预测资料)
  • lstm时间序列预测模型 时间序列-LSTM模型 (Time Series - LSTM Model) Advertisements 广告 Previous Page 上一页 Next Page 下一页 Now, we are familiar with statistical modelling on time series...
    lstm时间序列预测模型

    lstm时间序列预测模型

    时间序列-LSTM模型 (Time Series - LSTM Model)

    Now, we are familiar with statistical modelling on time series, but machine learning is all the rage right now, so it is essential to be familiar with some machine learning models as well. We shall start with the most popular model in time series domain − Long Short-term Memory model.

    现在,我们已经很熟悉时间序列的统计建模,但是机器学习现在非常流行,因此也必须熟悉某些机器学习模型。 我们将从时间序列域中最流行的模型开始-长短期记忆模型。

    LSTM is a class of recurrent neural network. So before we can jump to LSTM, it is essential to understand neural networks and recurrent neural networks.

    LSTM是一类递归神经网络。 因此,在进入LSTM之前,必须了解神经网络和递归神经网络。

    神经网络 (Neural Networks)

    An artificial neural network is a layered structure of connected neurons, inspired by biological neural networks. It is not one algorithm but combinations of various algorithms which allows us to do complex operations on data.

    人工神经网络是受生物神经网络启发的连接神经元的分层结构。 它不是一种算法,而是多种算法的组合,使我们能够对数据进行复杂的操作。

    递归神经网络 (Recurrent Neural Networks)

    It is a class of neural networks tailored to deal with temporal data. The neurons of RNN have a cell state/memory, and input is processed according to this internal state, which is achieved with the help of loops with in the neural network. There are recurring module(s) of ‘tanh’ layers in RNNs that allow them to retain information. However, not for a long time, which is why we need LSTM models.

    它是为处理时间数据而量身定制的一类神经网络。 RNN的神经元具有细胞状态/内存,并根据此内部状态处理输入,这是借助神经网络中的循环来实现的。 RNN中有“ tanh”层的重复模块,可让它们保留信息。 但是,不是很长一段时间,这就是为什么我们需要LSTM模型。

    LSTM (LSTM)

    It is special kind of recurrent neural network that is capable of learning long term dependencies in data. This is achieved because the recurring module of the model has a combination of four layers interacting with each other.

    它是一种特殊的循环神经网络,能够学习数据的长期依赖性。 之所以能够实现这一目标,是因为模型的重复模块具有相互交互的四层组合。

    Neural Network

    The picture above depicts four neural network layers in yellow boxes, point wise operators in green circles, input in yellow circles and cell state in blue circles. An LSTM module has a cell state and three gates which provides them with the power to selectively learn, unlearn or retain information from each of the units. The cell state in LSTM helps the information to flow through the units without being altered by allowing only a few linear interactions. Each unit has an input, output and a forget gate which can add or remove the information to the cell state. The forget gate decides which information from the previous cell state should be forgotten for which it uses a sigmoid function. The input gate controls the information flow to the current cell state using a point-wise multiplication operation of ‘sigmoid’ and ‘tanh’ respectively. Finally, the output gate decides which information should be passed on to the next hidden state

    上图显示了黄色方框中的四个神经网络层,绿色圆圈中的点智能算子,黄色圆圈中的输入,蓝色圆圈中的单元状态。 LSTM模块具有单元状态和三个门,这三个门为它们提供了从每个单元中选择性地学习,取消学习或保留信息的能力。 LSTM中的单元状态仅允许一些线性交互作用,从而使信息流经这些单元而不会被更改。 每个单元都有一个输入,输出和一个忘记门,可以将信息添加或删除到单元状态。 遗忘门决定使用S形函数应忘记先前单元状态中的哪些信息。 输入门分别使用“ Sigmoid”和“ tanh”的逐点乘法运算将信息流控制为当前单元状态。 最后,输出门决定应将哪些信息传递到下一个隐藏状态

    Now that we have understood the internal working of LSTM model, let us implement it. To understand the implementation of LSTM, we will start with a simple example − a straight line. Let us see, if LSTM can learn the relationship of a straight line and predict it.

    现在我们已经了解了LSTM模型的内部工作原理,让我们实现它。 为了理解LSTM的实现,我们将从一个简单的示例开始-一条直线。 让我们看看,LSTM是否可以学习直线的关系并对其进行预测。

    First let us create the dataset depicting a straight line.

    首先,让我们创建描述直线的数据集。

    In [402]:

    在[402]中:

    
    x = numpy.arange (1,500,1)
    y = 0.4 * x + 30
    plt.plot(x,y)
    
    

    Out[402]:

    出[402]:

    
    [<matplotlib.lines.Line2D at 0x1eab9d3ee10>]
    
    
    Code Snippet 19

    In [403]:

    在[403]中:

    
    trainx, testx = x[0:int(0.8*(len(x)))], x[int(0.8*(len(x))):]
    trainy, testy = y[0:int(0.8*(len(y)))], y[int(0.8*(len(y))):]
    train = numpy.array(list(zip(trainx,trainy)))
    test = numpy.array(list(zip(trainx,trainy)))
    
    

    Now that the data has been created and split into train and test. Let’s convert the time series data into the form of supervised learning data according to the value of look-back period, which is essentially the number of lags which are seen to predict the value at time ‘t’.

    现在已经创建了数据,并将其拆分为训练和测试。 让我们根据回溯期的值将时间序列数据转换为监督学习数据的形式,回溯期的值本质上是指可以预测时间“ t”时的滞后次数。

    So a time series like this −

    所以这样的时间序列-

    
    time variable_x
    t1  x1
    t2  x2
     :   :
     :   :
    T   xT
    
    

    When look-back period is 1, is converted to −

    当回溯期为1时,转换为-

    
    x1   x2
    x2   x3
     :    :
     :    :
    xT-1 xT
    
    

    In [404]:

    在[404]中:

    
    def create_dataset(n_X, look_back):
       dataX, dataY = [], []
       for i in range(len(n_X)-look_back):
          a = n_X[i:(i+look_back), ]
          dataX.append(a)
          dataY.append(n_X[i + look_back, ])
       return numpy.array(dataX), numpy.array(dataY)
    
    

    In [405]:

    在[405]中:

    
    look_back = 1
    trainx,trainy = create_dataset(train, look_back)
    testx,testy = create_dataset(test, look_back)
    
    trainx = numpy.reshape(trainx, (trainx.shape[0], 1, 2))
    testx = numpy.reshape(testx, (testx.shape[0], 1, 2))
    
    

    Now we will train our model.

    现在,我们将训练模型。

    Small batches of training data are shown to network, one run of when entire training data is shown to the model in batches and error is calculated is called an epoch. The epochs are to be run ‘til the time the error is reducing.

    将小批量的训练数据显示给网络,一次将整个训练数据分批显示给模型并且计算出误差时的一次运行称为时期。 直到错误减少的时间段为止。

    In [ ]:

    在[]中:

    
    from keras.models import Sequential
    from keras.layers import LSTM, Dense
    
    model = Sequential()
    model.add(LSTM(256, return_sequences = True, input_shape = (trainx.shape[1], 2)))
    model.add(LSTM(128,input_shape = (trainx.shape[1], 2)))
    model.add(Dense(2))
    model.compile(loss = 'mean_squared_error', optimizer = 'adam')
    model.fit(trainx, trainy, epochs = 2000, batch_size = 10, verbose = 2, shuffle = False)
    model.save_weights('LSTMBasic1.h5')
    
    

    In [407]:

    在[407]中:

    
    model.load_weights('LSTMBasic1.h5')
    predict = model.predict(testx)
    
    

    Now let’s see what our predictions look like.

    现在,让我们看看我们的预测是什么样的。

    In [408]:

    在[408]中:

    
    plt.plot(testx.reshape(398,2)[:,0:1], testx.reshape(398,2)[:,1:2])
    plt.plot(predict[:,0:1], predict[:,1:2])
    
    

    Out[408]:

    出[408]:

    
    [<matplotlib.lines.Line2D at 0x1eac792f048>]
    
    
    Code Snippet 22

    Now, we should try and model a sine or cosine wave in a similar fashion. You can run the code given below and play with the model parameters to see how the results change.

    现在,我们应该尝试以类似方式对正弦波或余弦波建模。 您可以运行下面给出的代码,并使用模型参数来查看结果如何变化。

    In [409]:

    在[409]中:

    
    x = numpy.arange (1,500,1)
    y = numpy.sin(x)
    plt.plot(x,y)
    
    

    Out[409]:

    出[409]:

    
    [<matplotlib.lines.Line2D at 0x1eac7a0b3c8>]
    
    
    Code Snippet 23

    In [410]:

    在[410]中:

    
    trainx, testx = x[0:int(0.8*(len(x)))], x[int(0.8*(len(x))):]
    trainy, testy = y[0:int(0.8*(len(y)))], y[int(0.8*(len(y))):]
    train = numpy.array(list(zip(trainx,trainy)))
    test = numpy.array(list(zip(trainx,trainy)))
    
    

    In [411]:

    在[411]中:

    
    look_back = 1
    trainx,trainy = create_dataset(train, look_back)
    testx,testy = create_dataset(test, look_back)
    trainx = numpy.reshape(trainx, (trainx.shape[0], 1, 2))
    testx = numpy.reshape(testx, (testx.shape[0], 1, 2))
    
    

    In [ ]:

    在[]中:

    
    model = Sequential()
    model.add(LSTM(512, return_sequences = True, input_shape = (trainx.shape[1], 2)))
    model.add(LSTM(256,input_shape = (trainx.shape[1], 2)))
    model.add(Dense(2))
    model.compile(loss = 'mean_squared_error', optimizer = 'adam')
    model.fit(trainx, trainy, epochs = 2000, batch_size = 10, verbose = 2, shuffle = False)
    model.save_weights('LSTMBasic2.h5')
    
    

    In [413]:

    在[413]中:

    
    model.load_weights('LSTMBasic2.h5')
    predict = model.predict(testx)
    
    

    In [415]:

    在[415]中:

    
    plt.plot(trainx.reshape(398,2)[:,0:1], trainx.reshape(398,2)[:,1:2])
    plt.plot(predict[:,0:1], predict[:,1:2])
    
    

    Out [415]:

    出[415]:

    
    [<matplotlib.lines.Line2D at 0x1eac7a1f550>]
    
    
    Code Snippet 23

    Now you are ready to move on to any dataset.

    现在您可以继续使用任何数据集了。

    翻译自: https://www.tutorialspoint.com/time_series/time_series_lstm_model.htm

    lstm时间序列预测模型

    展开全文
  • 为公交规划科学合理的进行,建立公交客运量时间序列预测模型.通过对公交客运量影响因素进行分析,选取市区人口数、从业人员数、在校学生数、工业生产总值、职工年平均工资、公交车辆数、运营线路数等7个指标自变量,...
  • 在分析经典模糊时间序列预测模型的基础上, 指出了传统的模型不能处理多因素的情形; 然后分析并 改进了证据理论中关于证据合成的方法, 提出了基于证据理论的多因素模糊时间序列预测模型; 最后用1997 年∼ ...
  • 提出一种高阶直觉模糊时间序列预测模型。模型首先应用模糊聚类算法实现论域的非等分划分;然后,针对直觉模糊时间序列的数据特性,提出一种更具客观性的直觉模糊集隶属度和非隶属度函数的确定方法;最后,利用直觉...
  • 基于ARMA模型和BP网络的时间序列预测模型,杨杰,孙旭东,摘要:本文主要介绍了时间序列和BP网络基础理论以及其预测的应用,并以2006年上证指数的开盘数据为例建立了基于这两种方法的预测模
  • 针对现有直觉模糊时间序列模型中直觉模糊关系组和确定性转换规则过度依赖训练数据规模的问题,提出一种基于动态时间弯曲(DTW,dynamic time warping)距离的长期直觉模糊时间序列预测模型。通过直觉模糊C均值(IFCM,...
  • 基于时间序列预测模型的簇型数据收集机制
  • 基于奇异谱分析的机场噪声时间序列预测模型
  • 基于GM-LSSVR的机场噪声时间序列预测模型
  • 时间序列预测模型笔记

    千次阅读 2019-08-29 11:07:21
    详细解释时间序列预测模型相关基础概念:差分、白噪声、残差序列、ADF结果如何查看、pq值如何确定。ARIMA模型具体实现步骤。

    时间序列预测模型有四种:AR、MA、ARMA和ARIMA模型。本文首先介绍四种模型的含义及对比,然后详细介绍ARIMA模型实现步骤。

    一、四种模型含义及对比

    1、AR、MA、ARMA和ARIMA模型

    AR可以解决当前数据与后期数据之间的关系,MA则可以解决随机变动也就是噪声的问题。ARMA模型是与自回归和移动平均模型两部分组成。所以可以表示为ARMA(p, q)。p是自回归阶数,q是移动平均阶数。
    在这里插入图片描述在这里插入图片描述在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    注意,采用ARIMA模型预测时序数据,必须是稳定的,如果不稳定的数据,是无法捕捉到规律的。比如股票数据用ARIMA无法预测的原因就是股票数据是非稳定的,常常受政策和新闻的影响而波动。

    二、ARIMA模型实现步骤

    1)获取时间序列数据
    
    2)检查序列是否为平稳非白噪声时间序列
    检验平稳性方法:绘图观察、ADF单位根平稳型检验
    
    对于不平稳的序列,可做**d阶**差分运算,或者取对数操作。
    
    检验白噪声方法:
    statsmodels 库acorr_ljungbox方法
    
    3)通过第二步的处理,得到平稳的时间序列。通过平稳的时间序列,求最佳**p和q**。
    
    实际编码中,可通过遍历p、q,取使得Bic值最小的方法求得。
    
    4)由以上得到的d、q、p ,得到ARIMA模型。然后对模型进行检验和优化。最后运用最终模型进行预测。
    
    预测方法:predict函数和forecast函数。
    

    三、相关基础概念

    1、差分
    用现在的观测值减去上一个时刻值就可得到差分结果。
    差分的原因:降低时间对数据的影响。
    滞后差分:连续观测值之间的差分变换叫做一阶滞后差分。滞后差分的步长根据时间结果做调整。

    如何利用python 对数据进行差分:numpy diff函数**

    参数:

    a:输入矩阵

    n:可选,代表要执行几次差值

    axis:默认是最后一个

    示例:

    import numpy as np     
    
    A = np.arange(2 , 14).reshape((3 , 4))    
       
    A[1 , 1] = 8    
       
    print('A:' , A)
    
     #  A: [[ 2  3  4  5]
          
    #       [ 6  8   8  9]
    
    #       [10 11 12 13]]
       
    
    print(np.diff(A))
    
    # [[1 1 1]
    #  [2 0 1]
    #  [1 1 1]]
    

    从输出结果可以看出,其实diff函数就是执行的是后一个元素减去前一个元素。

    参考:https://blog.csdn.net/hanshuobest/article/details/78558826
    如何利用python 对数据进行差分: http://www.360doc.com/content/17/0605/12/42308479_660150397.shtml
    在这里插入图片描述

    其他差分方法
    https://blog.csdn.net/tmb8z9vdm66wh68vx1/article/details/84207895

    2、adf检验**
    含义:
    adf检验就是单位根检验。
    指检验序列中是否存在单位根,因为存在单位根就是非平稳时间序列了。单位根就是指单位根过程,可以证明,序列中存在单位根过程就不平稳,会使回归分析中存在伪回归。

    ADF原假设为,序列存在单位根,即非平稳,对于一个平稳的时序数据,就需要在给定的置信水平上显著,拒绝原假设。

    ADF结果查看方法,有两种:
    1、若得到的统计量显著小于3个置信度(1%,5%,10%)的临界统计值时,说明是拒绝原假设的。即:查看统计量的值,若统计量的值都小于3个置信度的值,则说明序列平稳。

    2、另外是看P-value是否非常接近0.(4位小数基本即可)
    查看adf检验结果P-value:
    值要求小于给定的显著性水平,一般是0.05、0.01等,p越接近于0越好;

    例如,一个adf检验结果如下:

    adf 结果: (-7.703453304753249, 1.3205161280050353e-11, 0, 84, {'1%': -3.510711795769895, '5%': -2.8966159448223734, '10%': -2.5854823866213152}, 520.0070353452603)
    

    第一个值-7.703453304753249:ADF Test result(即统计量)
    第二个值1.3205161280050353e-11:P-Value
    第三部分{‘1%’: -3.510711795769895, ‘5%’: -2.8966159448223734, ‘10%’: -2.5854823866213152}:三个程度下拒绝原假设的统计值

    那么,此序列是否平稳呢?可以从两个方面看出:
    1、ADF Test result明显小于第三部分3个值,可以判定其为平稳的。
    2、P-Value为1e-11,很接近于0,可以判定此序列为平稳的。

    其实在第1点中,若是看到ADF Test result已经小于1%统计量的值,就可显著的拒绝原假设(数据非平稳),认为数据平稳。
    对于ADF结果在1% 以上 5%以下的结果,也不能说不平稳,关键看检验要求是什么样子的。

    如何在python中做adf检验呢?
    可通过statsmodels.tsa.stattools.adfuller函数进行adf校验。例如有一个时间序列day_max,则对其进行单位根检验可用如下语句:

     print("adf 结果:",str(adfuller(day_max)))
    

    得出的结果就是上例中的结果。

    参考链接:Python时间序列中ADF检验详解 :https://blog.csdn.net/weixin_42382211/article/details/81332431

    参考:
    时间序列分析之AR、MA、ARMA和ARIMA模型:https://blog.csdn.net/FrankieHello/article/details/80883147
    时间序列预测之–ARIMA模型:https://www.cnblogs.com/bradleon/p/6827109.html

    3、什么是残差?残差序列?白噪声?白噪声检验方法?

    残差:预测值减去真实值,即为残差。所有预测值序列减去真实值序列,即为残差序列。

    什么是白噪声检验?

    白噪声是一种特殊的弱平稳过程,通常时间序列分析到白噪声这一层就没什么好分析的了。
    做时间序列分析,之前需要做两个准备工作,即检查序列是否是平稳的,如果是平稳的,还要检查是否是白噪声。

    对残差序列进行白噪声检验,若残差序列是白噪声,则说明原始序列中已经没有什么可提取的价值了。
    python中如何进行白噪声检验?

    #导入acorr_ljungbox库          
    from statsmodels.stats.diagnostic import acorr_ljungbox          
    #检验。其中参数D_df是一个差分序列,dataframe类型          
    print("差分序列的白噪声检验结果:" +str(acorr_ljungbox(D_df, lags= 1)))   
    

    输出如下:

    差分序列的白噪声检验结果:(array([16.3875593]), array([5.16229461e-05]))
    

    第一个值是统计量,第二个值是P-value。ljungbox检验的原假设,时间序列是一个白噪声。若p-value小于0.05,则可以拒绝原假设,证明原序列非白噪声。若大于0.05,则不能拒绝原假设,原序列是一个白噪声。很明显,上述结果显示,该序列非白噪声,可以继续进行时间序列建模。

    参考:时间序列经过差分后变成了白噪声,还如何利用ARIMA建模?http://www.dataguru.cn/thread-639947-1-1.html

    4、p、q值的确定

    两种方法:

    1、根据自相关,偏自相关图初步确定p,q。

    2、取一个p、q的上限值,一般是小于10,然后遍历取所有p、q组合,分别求bic值,使bic值最小的p、q值即为最终的p、q。

    p,q值确定,即可得到ARIMA模型了。

    具体实现代码如下:

    from statsmodels.tsa.arima_model import ARIMA
    
    #定阶
    pmax = int(len(xdata)/10) #一般阶数不超过length/10
    qmax = int(len(xdata)/10) #一般阶数不超过length/10
    bic_matrix = [] #bic矩阵
    for p in range(pmax+1):
      tmp = []
      for q in range(qmax+1):
        try: #存在部分报错,所以用try来跳过报错。
          tmp.append(ARIMA(xdata, (p,1,q)).fit().bic)
        except:
          tmp.append(None)
      bic_matrix.append(tmp)
    print(bic_matrix)
    #[[1275.6868239439104, 1273.190434524266, 1273.5749982328914, 1274.4669152438114, None], 
    #[1276.7491283595593, 1271.8999324285992, None, None, None], 
    #[1279.6942963992901, 1277.5553412371614, None, 1280.0924824267408, None],
    # [1278.0659994468958, 1278.9885944429066, 1282.782534558853, 1285.943493708969, None], [1281.220790614283, 1282.6999920212124, 1286.2975191780365, 1290.1950373803218, None]]
    bic_matrix = pd.DataFrame(bic_matrix) #从中可以找出最小值
    print(bic_matrix)
            0            1            2            3     4
     0  1275.686824  1273.190435  1273.574998  1274.466915  None
     1  1276.749128  1271.899932          NaN          NaN  None
     2  1279.694296  1277.555341          NaN  1280.092482  None
     3  1278.065999  1278.988594  1282.782535  1285.943494  None
     4  1281.220791  1282.699992  1286.297519  1290.195037  None
    print(bic_matrix.stack())
     0  0    1275.69
        1    1273.19
        2    1273.57
        3    1274.47
     1  0    1276.75
        1     1271.9
     2  0    1279.69
        1    1277.56
        3    1280.09
     3  0    1278.07
        1    1278.99
        2    1282.78
        3    1285.94
    4  0     1281.22
       1     282.7
       2     1286.3
       3     1290.2
    p,q = bic_matrix.stack().astype('float64').idxmin() #先用stack展平,然后用idxmin找出最小值位置。
    print(u'BIC最小的p值和q值为:%s、%s' %(p,q))
    参考:ARIMA模型识别、计算p、q值:https://www.cnblogs.com/ggzhangxiaochao/p/9122619.html
    

    5、模型预测
    ARIMA模型进

    行预测。预测的方法有两种,一种是用predict函数,一种是用forecast函数。Predict函数只能对原数据进行预测,forecast函数可对未来数据进行单步或多步预测。

    predict函数的dynamic参数为True表示对未知数据进行预测,false表示对原数据预测。
    样本内预测:利用模型对训练数据进行预测,可将训练数据实际值和预测值做一个对比。
    样本外预测:利用训练出的模型对未来的数据进行预测。

    样本外预测的话,ARIMA模型只适合短期预测。长期的话你还是看看时间序列的趋势预测。预测的时间特别长的话,只能用传统的时间序列的乘法模型。预测还是不要看趋势,如果是个指数模型,你拟合成线性的肯定误差大。一般误差在5%以内就差不多了。数据多,模型合适,误差可以在1%内。

    ARIMA模型适合做稳定时间序列的预测,非稳定数据,例如股票、期货之类的预测,auto.arima就不合适了。
    一般取对数后,趋势就小很多。经过季节性差分(差分步长是季节周期的长度)就可以消除季节性影响。

    预测的最长期数不要超过N/5。例如25个月的数据,样本外最多预测到25/5=5年的数据。所以预测9个月的数据,最少最少要45个月的样本。除非你有足够的数据支撑你的预测数据,否则不适合做长时间的预测。

    6、置信区间
    较窄的置信区间比较宽的置信区间能提供更多的有关总体参数的信息 [1] 。举例说明如下:
    假设全班考试的平均分数为65分,则有如下表格中的理解:
    在这里插入图片描述

    7、dropna()

    详解:https://blog.csdn.net/weixin_38168620/article/details/79596798

    滤除缺失数据,可通过设置参数滤除包含NAN值的行,或者所有字段都为NAN值的行.默认滤除所有包含NaN的行

    8、ACF:自相关系数 PACF:偏自相关函数

    相关系数度量指的是两个不同事件彼此之间的相互影响程度;而自相关系数度量的是同一事件在两个不同时期之间的相关程度,形象的讲就是度量自己过去的行为对自己现在的影响。
    计量经济与时间序列_时间序列分析的几个基本概念(自相关函数,偏自相关函数等):https://www.cnblogs.com/noah0532/p/8449638.html
    代码及解析:https://www.cnblogs.com/bradleon/p/6832867.html

    9、衡量机器学习模型的三大指标:准确率、精度和召回率
    https://www.cnblogs.com/xuexuefirst/p/8858274.html

    10、Pandas中loc和iloc函数
    在这里插入图片描述
    11、pandas的to_csv()使用方法

    to_csv()是DataFrame类的方法,read_csv()是pandas的方法

    import os
    
    os.getcwd() #获取当前工作路径 
    
    dt.to_csv('Result.csv') #相对位置,保存在getwcd()获得的路径下,dt是Dataframe的一个实例
    dt.to_csv('C:/Users/think/Desktop/Result.csv')    #绝对位置
    

    12、datetime
    datetime是Python处理日期和时间的标准库。

    datetime是模块,datetime模块还包含一个datetime类,通过from datetime import datetime导入的才是datetime这个类。如果仅导入import datetime,则必须引用全名datetime.datetime。datetime.now()返回当前日期和时间,其类型是datetime。
    原文:Python学习笔记——datatime和pandas.to_datetime:https://blog.csdn.net/qq_32607273/article/details/81809986

    13、BIC值
    表示模型对数据的释度,BIC值越小,该模型对数据解释力越强,你可以理解成BIC越小越好,如果值为负,是要带上负号比较的。

    hon] 时间序列分析之ARIMA:https://blog.csdn.net/u010414589/article/details/49622625

    AR(I)MA时间序列建模过程——步骤和python代码:https://www.jianshu.com/p/cced6617b423

    14、pandas相关操作

    astype()函数

    astype()函数可用于转化dateframe某一列的数据类型

    15、对列、行求最大、最小值

    pandas的数据结构常用到一维(series),二维(DataFrame)等:
    对于二维数据,二维数据包含行索引和列索引
    行索引叫index,axis=0  列索引叫columns,axis=1
    #对列求最大值
    test_data_frame.max(0)  
    对行求最大值  
    test_data_frame.max(1)  
    求最小值同理  
    test_data_frame.max(0)
    对列求最小值  
    test_data_frame.max(1)
    对行求最小值

    获取最大值和最小值的位置  
    获取列最大值的位置  
    test_data_frame.idxmax(axis=0)  # 获取行最大值的位置  test_data_frame.idxmax(axis=1)  # 获取列最小值得位置  test_data_frame.idxmin(axis=0)  # 获取行最小值得位置,默认是0  test_data_frame.idxmin(axis=1)

    累计求和

    # 累计求第二列的值 
    test_data_frame.column1.cumsum() 
    不能使用test_data_frame.row1.cumsum()累计求行的和

    参考:https://blog.51cto.com/14335413/2428815

    ARIMA模型原理及实现:https://www.jianshu.com/p/305c4961ee06

    展开全文
  • 该文档包括混沌时间序列预测模型研究硕士论文及预测模型的原型系统(Matlab编程),论文部分详细阐述了预测模型构建等方面研究。
  • 时间序列预测模型及其算法研究, 时间序列预测模型及其算法研究
  • 利用相空间重构和预测模型参数的互相关系,提出一种混沌时间序列预测模型参数同步优化方法。首先采用均匀设计方法对影响模型预测精度的参数进行均匀设计,然后采用自调用最小二乘支持向量机进行参数同步优化,得到...
  • 具有输入和输出不确定性的新型在线自适应时间序列预测模型
  • 目的建立一种新的具有抗噪声能力的神经网络时间序列预测模型。方法通过将非单点模糊系统引入正则神经网络结构来建立模型。结果具有很强的抗噪声能力,且收敛速度快,全局搜索能力强。将该模型用于实例样本的预测,并...
  • 不同时间序列预测模型的示例。 前处理 时间序列生成 正弦波和随机噪声的时间序列生成 具有趋势,季节性和随机噪声的时间序列生成 归因 外推法 相似 特征提取 TSFresh的时间序列功能 楷模 传统统计模型 天真/季节性...
  • 卷积神经网络模型(CNN)可以应用于时间序列预测。有许多类型的CNN模型可用于每种特定类型的时间序列预测问题。在本介绍了在以TF2.1为后端的Keras中如何开发用于时间序列预测的不同的CNN模型。这些模型是在比较小的...

    【时间序列预测/分类】 全系列45篇由浅入深的博文汇总:传送门


    卷积神经网络模型(CNN)可以应用于时间序列预测。有许多类型的CNN模型可用于每种特定类型的时间序列预测问题。在本介绍了在以TF2.1为后端的Keras中如何开发用于时间序列预测的不同的CNN模型。这些模型是在比较小的人为构造的时间序列问题上演示的,模型配置也是任意的,并没有进行调参优化,这些内容会在以后的文章中介绍。

    先看一下思维导图,本文讲解了开发CNN时间序列预测模型中的前两个知识点:单变量CNN模型和多变量CNN模型(思维导图中的1、2):
    在这里插入图片描述



    1. 单变量CNN模型(Univariate CNN Models)

    尽管传统上是针对二维图像数据开发的,但CNNs可以用来对单变量时间序列预测问题进行建模。单变量时间序列是由具有时间顺序的单个观测序列组成的数据集,需要一个模型从过去的观测序列中学习以预测序列中的下一个值。本节分为两部分:

    • Data Preparation
    • CNN Model

    1.1 数据准备

    假设有如下序列数据:

    [10, 20, 30, 40, 50, 60, 70, 80, 90]
    

    我们可以将序列分成多个输入/输出模式,称为样本(samples),其中三个时间步(time steps)作为输入,一个时间步作为输出,并据此来预测一个时间步的输出值y。

    X,  		 y
    10, 20, 30,  40
    20, 30, 40,  50
    30, 40, 50,  60
    ...
    

    我们可以通过一个 split_sequence() 函数来实现上述操作,该函数可以将给定的单变量序列拆分为多个样本,其中每个样本具有指定数量的时间步,并且输出是单个时间步。因为这些函数在之前的文章已经介绍过,为了增加文章的可读性,此处就不逐一讲解了,会在每章结束之后,给出完整代码,如果有不懂的地方,可以查看之前的一篇文章。经过此函数处理之后,单变量序列变为:

    [10 20 30] 40
    [20 30 40] 50
    [30 40 50] 60
    [40 50 60] 70
    [50 60 70] 80
    [60 70 80] 90
    

    其中,每一行作为一个样本,其中三个时间步长值是样本数据,每一行中的最后一个单值是输出(y),因为是单变量,所以特征数(features)为1。


    1.2 CNN 模型

    1D CNN是一个CNN模型,它有一个卷积隐藏层,在一维序列上工作。在某些情况下,这之后可能是第二卷积层,例如非常长的输入序列,然后是池化层,其任务是将卷积层的输出提取到最显著的元素。卷积层和池化层之后是全连接层,用于解释模型卷积部分提取的特征。在卷积层和全连接层之间使用展平层(Flatten)将特征映射简化为一个一维向量。代码实现:

    model = Sequential()
    model.add(Conv1D(filters=64, kernel_size=2, activation='relu', input_shape=(n_steps,
    n_features)))
    model.add(MaxPooling1D(pool_size=2))
    model.add(Flatten())
    model.add(Dense(50, activation='relu'))
    model.add(Dense(1))
    model.compile(optimizer='adam', loss='mse')
    

    模型的关键是输入的形状 input_shape 参数;这是模型在时间步数和特征数方面期望作为每个样本的输入。我们使用的是一个单变量序列,因此特征数为1。时间步数是在划分数据集时 split_sequence() 函数的参数中定义的。

    每个样本的输入形状在第一个隐藏层定义的输入形状参数中指定。因为有多个样本,因此,模型期望训练数据的输入维度或形状为:[样本,时间步,特征]([samples, timesteps, features])split_sequence() 函数输出的训练数据 X 的形状为 [samples,timesteps],因此应该对 X 重塑形状,增加一个特征维度,以满足CNN模型的输入要求。代码实现:

    n_features = 1
    X = X.reshape((X.shape[0], X.shape[1], n_features))
    

    CNN实际上并不认为数据具有时间步,而是将其视为可以执行卷积读取操作的序列,如一维图像。上例中,我们定义了一个卷积层,它有64个filter,kernel大小为2。接下来是一个最大池化层和一个全连接层(Dense)来解释输入特性。最后,输出层预测单个数值。该模型利用有效的随机梯度下降Adam进行拟合,利用均方误差(mse)损失函数进行优化。处理好训练数据和定义完模型之后,接下来开始训练,代码实现:

    model.fit(X, y, epochs=1000, verbose=0)
    

    在模型拟合后,可以利用它进行预测。假设输入[70,80,90]来预测序列中的下一个值,并期望模型能预测类似于[100]的数据。该CNN模型期望输入形状是三维的,形状为 [样本、时间步长、特征] ,因此,在进行预测之前,必须重塑单个输入样本为三维形状。代码实现:

    x_input = array([70, 80, 90])
    x_input = x_input.reshape((1, n_steps, n_features))
    yhat = model.predict(x_input, verbose=0)
    

    完整代码:

    import numpy as np
    from tensorflow.keras.models import Sequential
    from tensorflow.keras.layers import Dense, Flatten, Conv1D, MaxPooling1D
    
    # 该该函数将序列数据分割成样本
    def split_sequence(sequence, sw_width, n_features):
        '''
        这个简单的示例,通过for循环实现有重叠截取数据,滑动步长为1,滑动窗口宽度为sw_width。
        以后的文章,会介绍使用yield方法来实现特定滑动步长的滑动窗口的实例。
        '''
        X, y = [], []
        
        for i in range(len(sequence)):
            # 获取单个样本中最后一个元素的索引,因为python切片前闭后开,索引从0开始,所以不需要-1
            end_element_index = i + sw_width
            # 如果样本最后一个元素的索引超过了序列索引的最大长度,说明不满足样本元素个数,则这个样本丢弃
            if end_element_index > len(sequence) - 1:
                break
            # 通过切片实现步长为1的滑动窗口截取数据组成样本的效果
            seq_x, seq_y = sequence[i:end_element_index], sequence[end_element_index]
            
            X.append(seq_x)
            y.append(seq_y)
            
            process_X, process_y = np.array(X), np.array(y)
            process_X = process_X.reshape((process_X.shape[0], process_X.shape[1], n_features))
        
        print('split_sequence:\nX:\n{}\ny:\n{}\n'.format(np.array(X), np.array(y)))
        print('X_shape:{},y_shape:{}\n'.format(np.array(X).shape, np.array(y).shape))
        print('train_X:\n{}\ntrain_y:\n{}\n'.format(process_X, process_y))
        print('train_X.shape:{},trian_y.shape:{}\n'.format(process_X.shape, process_y.shape))
        return process_X, process_y
    
        
    def oned_cnn_model(sw_width, n_features, X, y, test_X, epoch_num, verbose_set):
        model = Sequential()
        
        # 对于一维卷积来说,data_format='channels_last'是默认配置,该API的规则如下:
        # 输入形状为:(batch, steps, channels);输出形状为:(batch, new_steps, filters),padding和strides的变化会导致new_steps变化
        # 如果设置为data_format = 'channels_first',则要求输入形状为: (batch, channels, steps).
        model.add(Conv1D(filters=64, kernel_size=2, activation='relu',
                         strides=1, padding='valid', data_format='channels_last',
                         input_shape=(sw_width, n_features)))
        
        # 对于一维池化层来说,data_format='channels_last'是默认配置,该API的规则如下:
        # 3D 张量的输入形状为: (batch_size, steps, features);输出3D张量的形状为:(batch_size, downsampled_steps, features)
        # 如果设置为data_format = 'channels_first',则要求输入形状为:(batch_size, features, steps)
        model.add(MaxPooling1D(pool_size=2, strides=None, padding='valid', 
                               data_format='channels_last')) 
        
        # data_format参数的作用是在将模型从一种数据格式切换到另一种数据格式时保留权重顺序。默认为channels_last。
        # 如果设置为channels_last,那么数据输入形状应为:(batch,…,channels);如果设置为channels_first,那么数据输入形状应该为(batch,channels,…)
        # 输出为(batch, 之后参数尺寸的乘积)
        model.add(Flatten())
        
        # Dense执行以下操作:output=activation(dot(input,kernel)+bias),
        # 其中,activation是激活函数,kernel是由层创建的权重矩阵,bias是由层创建的偏移向量(仅当use_bias为True时适用)。
        # 2D 输入:(batch_size, input_dim);对应 2D 输出:(batch_size, units)
        model.add(Dense(units=50, activation='relu',
                    use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros',))
        
        # 因为要预测下一个时间步的值,因此units设置为1
        model.add(Dense(units=1))
        
        # 配置模型
        model.compile(optimizer='adam', loss='mse',
                     metrics=['accuracy'], loss_weights=None, sample_weight_mode=None, weighted_metrics=None, target_tensors=None)
        
        print('\n',model.summary())
        # X为输入数据,y为数据标签;batch_size:每次梯度更新的样本数,默认为32。
        # verbose: 0,1,2. 0=训练过程无输出,1=显示训练过程进度条,2=每训练一个epoch打印一次信息
        
        history = model.fit(X, y, batch_size=32, epochs=epoch_num, verbose=verbose_set)
        
        
        yhat = model.predict(test_X, verbose=0)
        print('\nyhat:', yhat)
        
        return model, history
    
    if __name__ == '__main__':
        
        train_seq = [10, 20, 30, 40, 50, 60, 70, 80, 90]
        sw_width = 3
        n_features = 1
        epoch_num = 1000
        verbose_set = 0
        
        train_X, train_y = split_sequence(train_seq, sw_width, n_features)
    
        # 预测
        x_input = np.array([70, 80, 90])
        x_input = x_input.reshape((1, sw_width, n_features))
        
        model, history = oned_cnn_model(sw_width, n_features, train_X, train_y, x_input, epoch_num, verbose_set)
        
        print('\ntrain_acc:%s'%np.mean(history.history['accuracy']), '\ntrain_loss:%s'%np.mean(history.history['loss']))
    

    输出:

    split_sequence:
    X:
    [[10 20 30]
     [20 30 40]
     [30 40 50]
     [40 50 60]
     [50 60 70]
     [60 70 80]]
    y:
    [40 50 60 70 80 90]
    
    X_shape:(6, 3),y_shape:(6,)
    
    train_X:
    [[[10]
      [20]
      [30]]
    
     [[20]
      [30]
      [40]]
    
     [[30]
      [40]
      [50]]
    
     [[40]
      [50]
      [60]]
    
     [[50]
      [60]
      [70]]
    
     [[60]
      [70]
      [80]]]
    train_y:
    [40 50 60 70 80 90]
    
    train_X.shape:(6, 3, 1),trian_y.shape:(6,)
    
    Model: "sequential"
    _________________________________________________________________
    Layer (type)                 Output Shape              Param #   
    =================================================================
    conv1d (Conv1D)              (None, 2, 64)             192       
    _________________________________________________________________
    max_pooling1d (MaxPooling1D) (None, 1, 64)             0         
    _________________________________________________________________
    flatten (Flatten)            (None, 64)                0         
    _________________________________________________________________
    dense (Dense)                (None, 50)                3250      
    _________________________________________________________________
    dense_1 (Dense)              (None, 1)                 51        
    =================================================================
    Total params: 3,493
    Trainable params: 3,493
    Non-trainable params: 0
    _________________________________________________________________
    
     None
    
    yhat: [[101.824524]]
    
    train_acc:0.0 
    train_loss:83.09048912930488
    

    2. 多变量 CNN 模型 (Multivariate CNN Models)

    多变量(多元)时间序列数据是指每一时间步有多个观测值的数据。对于多变量时间序列数据,有两种主要模型:

    • 多输入序列;
    • 多并行序列

    2.1 多输入序列

    一个问题可能有两个或多个并行输入时间序列和一个依赖于输入时间序列的输出时间序列。输入时间序列是并行的,因为每个序列在同一时间步上都有观测值。我们可以通过两个并行输入时间序列的简单示例来演示这一点,其中输出序列是输入序列的简单相加。代码实现:

    in_seq1 = array([10, 20, 30, 40, 50, 60, 70, 80, 90])
    in_seq2 = array([15, 25, 35, 45, 55, 65, 75, 85, 95])
    out_seq = array([in_seq1[i]+in_seq2[i] for i in range(len(in_seq1))])
    

    我们可以将这三个数据数组重塑为单个数据集,其中每一行是一个时间步,每一列是一个单独的时间序列。这是在CSV文件中存储并行时间序列的标准方法。代码实现:

    in_seq1 = in_seq1.reshape((len(in_seq1), 1)) 
    in_seq2 = in_seq2.reshape((len(in_seq2), 1))
    out_seq = out_seq.reshape((len(out_seq), 1))
    # 对于二维数组,hstack方法沿第二维堆叠,即沿着列堆叠,列数增加。
    dataset = hstack((in_seq1, in_seq2, out_seq)
    

    最后结果:

    [[ 10 15 25]
    [ 20 25 45]
    [ 30 35 65]
    [ 40 45 85]
    [ 50 55 105]
    [ 60 65 125]
    [ 70 75 145]
    [ 80 85 165]
    [ 90 95 185]]
    

    与单变量时间序列一样,我们必须将这些数据构造成具有输入和输出样本的样本。一维CNN模型需要足够的上下文信息来学习从输入序列到输出值的映射。CNNs可以支持并行输入时间序列作为独立的通道,可以类比图像的红色、绿色和蓝色分量。因此,我们需要将数据分成样本,保持两个输入序列的观测顺序。如果我们选择三个输入时间步骤,那么第一个示例将如下所示:

    输入:

    10, 15
    20, 25
    30, 35
    

    输出:

    65
    

    这里可能会看不明白,其实之前的文章已经介绍过了,这里再说一遍。看上边的9×3数组,也就是说,将每个并行序列(列)的前三个时间步(行)的值(3×2,三行两列)作为输入样本提供给模型,并且把第三个时间步(列)的值(本例中为65),作为样本标签提供给模型。还要注意,在将时间序列转换为输入/输出样本以训练模型时,不得不放弃输出时间序列中的一些值(前两行的第三列25和45没有使用),因为在先前的时间步,输入时间序列中没有值,所以没法预测。这个操作可以通过类似上节的oned_split_sequence函数来实现,为了增加文章的可读性,这里只放出结果,相关代码在完整代码部分中。划分结果:

    [[10 15]
    [20 25]
    [30 35]] 65
    [[20 25]
    [30 35]
    [40 45]] 85
    [[30 35]
    [40 45]
    [50 55]] 105
    [[40 45]
    [50 55]
    [60 65]] 125
    [[50 55]
    [60 65]
    [70 75]] 145
    [[60 65]
    [70 75]
    [80 85]] 165
    [[70 75]
    [80 85]
    [90 95]] 185
    

    看到这里,其实就很好理解了。每个样本中,三行相当于滑动窗口的宽度为3,上述划分是以滑动步长为1来取值的,每个样本之间的值是有重叠的,两列相当于有两个特征,然后用这些数据来预测下一步的输出,这个输出是单值的。这种方式可以用于时间序列分类任务,之后的文章中会介绍,比如人类行为识别。

    之前也在滑动窗口取值卡了一段时间,经过这段时间的学习,想明白了,画个图吧,方便填坑。这个图一看就明白了,还是拿上边的数据,来分析,如下图:
    在这里插入图片描述
    如果要做时间序列分类任务,只需要把最后一列数据换为标签就行了,每个采样点一个标签,然后取滑动窗口宽度结束索引的行的标签为样本标签;如果想要增加特征,增加列数就可以了。比如做降雨量预测,每一列数据就代表一个特征的采样数据,例如温度、湿度、风速等等,每一行就表示在不同时间戳上这些特征的采样值。


    2.1.1 CNN Model

    完整代码:

    import numpy as np
    from tensorflow.keras.models import Sequential
    from tensorflow.keras.layers import Dense, Flatten, Conv1D, MaxPooling1D
    
    def split_sequences(first_seq, secend_seq, sw_width):
        '''
        该函数将序列数据分割成样本
        '''
        input_seq1 = np.array(first_seq).reshape(len(first_seq), 1)
        input_seq2 = np.array(secend_seq).reshape(len(secend_seq), 1)
        out_seq = np.array([first_seq[i]+secend_seq[i] for i in range(len(first_seq))])
        out_seq = out_seq.reshape(len(out_seq), 1)
        
        dataset = np.hstack((input_seq1, input_seq2, out_seq))
        print('dataset:\n',dataset)
        
        X, y = [], []
        
        for i in range(len(dataset)):
            # 切片索引从0开始,区间为前闭后开,所以不用减去1
            end_element_index = i + sw_width
            # 同样的道理,这里考虑最后一个样本正好取到最后一行的数据,那么索引不能减1,如果减去1的话最后一个样本就取不到了。
            if end_element_index > len(dataset):
                break
            
            # 该语句实现步长为1的滑动窗口截取数据功能;
            # 以下切片中,:-1 表示取除最后一列的其他列数据;-1表示取最后一列的数据
            seq_x, seq_y = dataset[i:end_element_index, :-1], dataset[end_element_index-1, -1]
            
            X.append(seq_x)
            y.append(seq_y)
            
            process_X, process_y = np.array(X), np.array(y)
        
        n_features = process_X.shape[2]
        print('train_X:\n{}\ntrain_y:\n{}\n'.format(process_X, process_y))
        print('train_X.shape:{},trian_y.shape:{}\n'.format(process_X.shape, process_y.shape))
        print('n_features:',n_features)
        return process_X, process_y, n_features
    
        
    def oned_cnn_model(sw_width, n_features, X, y, test_X, epoch_num, verbose_set):
        model = Sequential()
        
        model.add(Conv1D(filters=64, kernel_size=2, activation='relu',
                         strides=1, padding='valid', data_format='channels_last',
                         input_shape=(sw_width, n_features)))
        
        model.add(MaxPooling1D(pool_size=2, strides=None, padding='valid', 
                               data_format='channels_last')) 
        
        model.add(Flatten())
        
        model.add(Dense(units=50, activation='relu',
                    use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros',))
        
        model.add(Dense(units=1))
        
        model.compile(optimizer='adam', loss='mse',
                     metrics=['accuracy'], loss_weights=None, sample_weight_mode=None, weighted_metrics=None, target_tensors=None)
        
        print('\n',model.summary())
        
        history = model.fit(X, y, batch_size=32, epochs=epoch_num, verbose=verbose_set)
        
        
        yhat = model.predict(test_X, verbose=0)
        print('\nyhat:', yhat)
        
        return model, history
    
    if __name__ == '__main__':
        
        train_seq1 = [10, 20, 30, 40, 50, 60, 70, 80, 90]
        train_seq2 = [15, 25, 35, 45, 55, 65, 75, 85, 95]
        sw_width = 3
    
        epoch_num = 1000
        verbose_set = 0
        
        train_X, train_y, n_features = split_sequences(train_seq1, train_seq2, sw_width)
    
        # 预测
        x_input = np.array([[80, 85], [90, 95], [100, 105]])
        x_input = x_input.reshape((1, sw_width, n_features))
        
        model, history = oned_cnn_model(sw_width, n_features, train_X, train_y, x_input, epoch_num, verbose_set)
        
        print('\ntrain_acc:%s'%np.mean(history.history['accuracy']), '\ntrain_loss:%s'%np.mean(history.history['loss']))
    

    输出:

    dataset:
     [[ 10  15  25]
     [ 20  25  45]
     [ 30  35  65]
     [ 40  45  85]
     [ 50  55 105]
     [ 60  65 125]
     [ 70  75 145]
     [ 80  85 165]
     [ 90  95 185]]
    train_X:
    [[[10 15]
      [20 25]
      [30 35]]
    
     [[20 25]
      [30 35]
      [40 45]]
    
     [[30 35]
      [40 45]
      [50 55]]
    
     [[40 45]
      [50 55]
      [60 65]]
    
     [[50 55]
      [60 65]
      [70 75]]
    
     [[60 65]
      [70 75]
      [80 85]]
    
     [[70 75]
      [80 85]
      [90 95]]]
    train_y:
    [ 65  85 105 125 145 165 185]
    
    train_X.shape:(7, 3, 2),trian_y.shape:(7,)
    
    n_features: 2
    Model: "sequential_2"
    _________________________________________________________________
    Layer (type)                 Output Shape              Param #   
    =================================================================
    conv1d_2 (Conv1D)            (None, 2, 64)             320       
    _________________________________________________________________
    max_pooling1d_2 (MaxPooling1 (None, 1, 64)             0         
    _________________________________________________________________
    flatten_2 (Flatten)          (None, 64)                0         
    _________________________________________________________________
    dense_4 (Dense)              (None, 50)                3250      
    _________________________________________________________________
    dense_5 (Dense)              (None, 1)                 51        
    =================================================================
    Total params: 3,621
    Trainable params: 3,621
    Non-trainable params: 0
    _________________________________________________________________
    
     None
    
    yhat: [[205.84216]]
    
    train_acc:0.0 
    train_loss:290.3450777206163
    

    2.1.2 Multi-headed CNN Model

    有另一种更精细的方法来解决多变量输入序列问题。每个输入序列可以由单独的CNN处理,并且在对输出序列进行预测之前,可以组合这些子模型中的每个的输出。我们可以称之为 Multi-headed CNN模型。它可能提供更多的灵活性或更好的性能,这取决于正在建模的问题的具体情况。例如,它允许每个输入序列配置不同的子模型,例如过滤器映射的数量和内核大小。这种类模型可以用Keras API定义。首先,可以将第一个输入模型定义为一个一维CNN,其输入层要求输入为n个步骤和1个特征。代码实现:

    visible1 = Input(shape=(n_steps, n_features))
    cnn1 = Conv1D(filters=64, kernel_size=2, activation='relu')(visible1)
    cnn1 = MaxPooling1D(pool_size=2)(cnn1)
    cnn1 = Flatten()(cnn1)
    
    visible2 = Input(shape=(n_steps, n_features))
    cnn2 = Conv1D(filters=64, kernel_size=2, activation='relu')(visible2)
    cnn2 = MaxPooling1D(pool_size=2)(cnn2)
    cnn2 = Flatten()(cnn2)
    

    定义好两个输入子模型后,可以将每个模型的输出合并为一个长向量,在对输出序列进行预测之前可以对其进行解释。最后,将输入和输出绑定在一起。代码实现:

    merge = concatenate([cnn1, cnn2])
    dense = Dense(50, activation='relu')(merge)
    output = Dense(1)(dense)
    
    model = Model(inputs=[visible1, visible2], outputs=output)
    

    此模型要求将输入作为两个元素的列表提供,其中列表中的每个元素都包含其中一个子模型的数据。为了实现这一点,我们可以将3D输入数据分割成两个独立的输入数据数组,即从一个形状为 [7,3,2] 的数组分割成两个形状为 [7,3,1] 的3D数组。代码实现:

    n_features = 1
    # separate input data
    X1 = X[:, :, 0].reshape(X.shape[0], X.shape[1], n_features)
    X2 = X[:, :, 1].reshape(X.shape[0], X.shape[1], n_features)
    

    开始训练:

    model.fit([X1, X2], y, epochs=1000, verbose=0)
    

    完整代码:

    import numpy as np
    from tensorflow.keras.models import Sequential, Model
    from tensorflow.keras.layers import Dense, Flatten, Conv1D, MaxPooling1D, Input, concatenate
    from tensorflow.keras.utils import plot_model
    
    def split_sequences2(first_seq, secend_seq, sw_width, n_features):
        '''
        该函数将序列数据分割成样本
        '''
        input_seq1 = np.array(first_seq).reshape(len(first_seq), 1)
        input_seq2 = np.array(secend_seq).reshape(len(secend_seq), 1)
        out_seq = np.array([first_seq[i]+secend_seq[i] for i in range(len(first_seq))])
        out_seq = out_seq.reshape(len(out_seq), 1)
        
        dataset = np.hstack((input_seq1, input_seq2, out_seq))
        print('dataset:\n',dataset)
        
        X, y = [], []
        
        for i in range(len(dataset)):
            # 切片索引从0开始,区间为前闭后开,所以不用减去1
            end_element_index = i + sw_width
            # 同样的道理,这里考虑最后一个样本正好取到最后一行的数据,那么索引不能减1,如果减去1的话最后一个样本就取不到了。
            if end_element_index > len(dataset):
                break
            
            # 该语句实现步长为1的滑动窗口截取数据功能;
            # 以下切片中,:-1 表示取除最后一列的其他列数据;-1表示取最后一列的数据
            seq_x, seq_y = dataset[i:end_element_index, :-1], dataset[end_element_index-1, -1]
            
            X.append(seq_x)
            y.append(seq_y)
            
            process_X, process_y = np.array(X), np.array(y)
        
        # [:,:,0]表示三维数组前两个维度的数据全取,第三个维度取第一个数据,可以想象成一摞饼干,取了一块。
        # 本例中 process_X的shape为(7,3,2),所以下式就很好理解了,
        X1 = process_X[:,:,0].reshape(process_X.shape[0], process_X.shape[1], n_features)
        X2 = process_X[:,:,1].reshape(process_X.shape[0], process_X.shape[1], n_features)
    
        print('train_X:\n{}\ntrain_y:\n{}\n'.format(process_X, process_y))
        print('train_X.shape:{},trian_y.shape:{}\n'.format(process_X.shape, process_y.shape))
        print('X1.shape:{},X2.shape:{}\n'.format(X1.shape, X2.shape))
        
        return X1, X2, process_y
    
        
    def oned_cnn_model(n_steps, n_features, X_1, X_2, y, x1, x2, epoch_num, verbose_set):
        
        visible1 = Input(shape=(n_steps, n_features))
        cnn1 = Conv1D(filters=64, kernel_size=2, activation='relu')(visible1)
        cnn1 = MaxPooling1D(pool_size=2)(cnn1)
        cnn1 = Flatten()(cnn1)
    
        visible2 = Input(shape=(n_steps, n_features))
        cnn2 = Conv1D(filters=64, kernel_size=2, activation='relu')(visible2)
        cnn2 = MaxPooling1D(pool_size=2)(cnn2)
        cnn2 = Flatten()(cnn2)
        
        merge = concatenate([cnn1, cnn2])
        dense = Dense(50, activation='relu')(merge)
        output = Dense(1)(dense)
    
        model = Model(inputs=[visible1, visible2], outputs=output)
    
        model.compile(optimizer='adam', loss='mse',
                     metrics=['accuracy'], loss_weights=None, sample_weight_mode=None, weighted_metrics=None, target_tensors=None)
        
        print('\n',model.summary())
        plot_model(model, to_file='multi_head_cnn_model.png', show_shapes=True, show_layer_names=True, rankdir='TB', dpi=200)
        
        history = model.fit([X_1, X_2], y, batch_size=32, epochs=epoch_num, verbose=verbose_set)
    
        yhat = model.predict([x1,x2], verbose=0)
        print('\nyhat:', yhat)
        
        return model, history
    
    if __name__ == '__main__':
        
        train_seq1 = [10, 20, 30, 40, 50, 60, 70, 80, 90]
        train_seq2 = [15, 25, 35, 45, 55, 65, 75, 85, 95]
        sw_width = 3
        n_features = 1
        epoch_num = 1000
        verbose_set = 0
        
        train_X1, train_X2, train_y = split_sequences2(train_seq1, train_seq2, sw_width, n_features)
    
        # 预测
        x_input = np.array([[80, 85], [90, 95], [100, 105]])
        x_1 = x_input[:, 0].reshape((1, sw_width, n_features))
        x_2 = x_input[:, 1].reshape((1, sw_width, n_features))
        
        model, history = oned_cnn_model(sw_width, n_features, train_X1, train_X2, train_y, x_1, x_2, epoch_num, verbose_set)
    
        print('\ntrain_acc:%s'%np.mean(history.history['accuracy']), '\ntrain_loss:%s'%np.mean(history.history['loss']))
    

    输出:

    dataset:
     [[ 10  15  25]
     [ 20  25  45]
     [ 30  35  65]
     [ 40  45  85]
     [ 50  55 105]
     [ 60  65 125]
     [ 70  75 145]
     [ 80  85 165]
     [ 90  95 185]]
    train_X:
    [[[10 15]
      [20 25]
      [30 35]]
    
     [[20 25]
      [30 35]
      [40 45]]
    
     [[30 35]
      [40 45]
      [50 55]]
    
     [[40 45]
      [50 55]
      [60 65]]
    
     [[50 55]
      [60 65]
      [70 75]]
    
     [[60 65]
      [70 75]
      [80 85]]
    
     [[70 75]
      [80 85]
      [90 95]]]
    train_y:
    [ 65  85 105 125 145 165 185]
    
    train_X.shape:(7, 3, 2),trian_y.shape:(7,)
    
    X1.shape:(7, 3, 1),X2.shape:(7, 3, 1)
    
    Model: "model_8"
    __________________________________________________________________________________________________
    Layer (type)                    Output Shape         Param #     Connected to                     
    ==================================================================================================
    input_17 (InputLayer)           [(None, 3, 1)]       0                                            
    __________________________________________________________________________________________________
    input_18 (InputLayer)           [(None, 3, 1)]       0                                            
    __________________________________________________________________________________________________
    conv1d_16 (Conv1D)              (None, 2, 64)        192         input_17[0][0]                   
    __________________________________________________________________________________________________
    conv1d_17 (Conv1D)              (None, 2, 64)        192         input_18[0][0]                   
    __________________________________________________________________________________________________
    max_pooling1d_16 (MaxPooling1D) (None, 1, 64)        0           conv1d_16[0][0]                  
    __________________________________________________________________________________________________
    max_pooling1d_17 (MaxPooling1D) (None, 1, 64)        0           conv1d_17[0][0]                  
    __________________________________________________________________________________________________
    flatten_16 (Flatten)            (None, 64)           0           max_pooling1d_16[0][0]           
    __________________________________________________________________________________________________
    flatten_17 (Flatten)            (None, 64)           0           max_pooling1d_17[0][0]           
    __________________________________________________________________________________________________
    concatenate_8 (Concatenate)     (None, 128)          0           flatten_16[0][0]                 
                                                                     flatten_17[0][0]                 
    __________________________________________________________________________________________________
    dense_16 (Dense)                (None, 50)           6450        concatenate_8[0][0]              
    __________________________________________________________________________________________________
    dense_17 (Dense)                (None, 1)            51          dense_16[0][0]                   
    ==================================================================================================
    Total params: 6,885
    Trainable params: 6,885
    Non-trainable params: 0
    __________________________________________________________________________________________________
    
     None
    
    yhat: [[205.66142]]
    
    train_acc:0.0 
    train_loss:201.12432714579907
    

    保存的网络结构图:
    在这里插入图片描述


    2.2 多并行序列

    假设有如下序列:

    [[ 10 15 25]
    [ 20 25 45]
    [ 30 35 65]
    [ 40 45 85]
    [ 50 55 105]
    [ 60 65 125]
    [ 70 75 145]
    [ 80 85 165]
    [ 90 95 185]]
    

    输入:

    10, 15, 25
    20, 25, 45
    30, 35, 65
    

    输出:

    40, 45, 85
    

    对于整个数据集:

    [[10 15 25]
    [20 25 45]
    [30 35 65]] [40 45 85]
    [[20 25 45]
    [30 35 65]
    [40 45 85]] [ 50 55 105]
    [[ 30 35 65]
    [ 40 45 85]
    [ 50 55 105]] [ 60 65 125]
    [[ 40 45 85]
    [ 50 55 105]
    [ 60 65 125]] [ 70 75 145]
    [[ 50 55 105]
    [ 60 65 125]
    [ 70 75 145]] [ 80 85 165]
    [[ 60 65 125]
    [ 70 75 145]
    [ 80 85 165]] [ 90 95 185]
    

    2.2.1 Vector-Output CNN Model

    要在该数据集上建立一个一维CNN模型。在该模型中,通过input_shape参数为输入层指定时间步数和并行序列(特征)。代码实现:

    model = Sequential()
    model.add(Conv1D(filters=64, kernel_size=2, activation='relu', input_shape=(n_steps,
    n_features)))
    model.add(MaxPooling1D(pool_size=2))
    model.add(Flatten())
    model.add(Dense(50, activation='relu'))
    model.add(Dense(n_features))
    model.compile(optimizer='adam', loss='mse')
    

    完整代码:

    import numpy as np
    from tensorflow.keras.models import Sequential
    from tensorflow.keras.layers import Dense, Flatten, Conv1D, MaxPooling1D
    
    def split_sequences(first_seq, secend_seq, sw_width):
        '''
        该函数将序列数据分割成样本
        '''
        input_seq1 = np.array(first_seq).reshape(len(first_seq), 1)
        input_seq2 = np.array(secend_seq).reshape(len(secend_seq), 1)
        out_seq = np.array([first_seq[i]+secend_seq[i] for i in range(len(first_seq))])
        out_seq = out_seq.reshape(len(out_seq), 1)
        
        dataset = np.hstack((input_seq1, input_seq2, out_seq))
        print('dataset:\n',dataset)
        
        X, y = [], []
        
        for i in range(len(dataset)):
            end_element_index = i + sw_width
            if end_element_index > len(dataset) - 1:
                break
            
            # 该语句实现步长为1的滑动窗口截取数据功能;
            seq_x, seq_y = dataset[i:end_element_index, :], dataset[end_element_index, :]
            
            X.append(seq_x)
            y.append(seq_y)
            
            process_X, process_y = np.array(X), np.array(y)
        
        n_features = process_X.shape[2]
        print('train_X:\n{}\ntrain_y:\n{}\n'.format(process_X, process_y))
        print('train_X.shape:{},trian_y.shape:{}\n'.format(process_X.shape, process_y.shape))
        print('n_features:',n_features)
        return process_X, process_y, n_features
    
        
    def oned_cnn_model(sw_width, n_features, X, y, test_X, epoch_num, verbose_set):
        model = Sequential()
        
        model.add(Conv1D(filters=64, kernel_size=2, activation='relu',
                         strides=1, padding='valid', data_format='channels_last',
                         input_shape=(sw_width, n_features)))
        
        model.add(MaxPooling1D(pool_size=2, strides=None, padding='valid', 
                               data_format='channels_last')) 
        
        model.add(Flatten())
        
        model.add(Dense(units=50, activation='relu',
                    use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros',))
        
        model.add(Dense(units=n_features))
        
        model.compile(optimizer='adam', loss='mse',
                     metrics=['accuracy'], loss_weights=None, sample_weight_mode=None, weighted_metrics=None, target_tensors=None)
        
        print('\n',model.summary())
        
        history = model.fit(X, y, batch_size=32, epochs=epoch_num, verbose=verbose_set)
        
        
        yhat = model.predict(test_X, verbose=0)
        print('\nyhat:', yhat)
        
        return model, history
    
    if __name__ == '__main__':
        
        train_seq1 = [10, 20, 30, 40, 50, 60, 70, 80, 90]
        train_seq2 = [15, 25, 35, 45, 55, 65, 75, 85, 95]
        sw_width = 3
    
        epoch_num = 3000
        verbose_set = 0
        
        train_X, train_y, n_features = split_sequences(train_seq1, train_seq2, sw_width)
    
        # 预测
        x_input = np.array([[70,75,145], [80,85,165], [90,95,185]])
        x_input = x_input.reshape((1, sw_width, n_features))
        
        model, history = oned_cnn_model(sw_width, n_features, train_X, train_y, x_input, epoch_num, verbose_set)
        
        print('\ntrain_acc:%s'%np.mean(history.history['accuracy']), '\ntrain_loss:%s'%np.mean(history.history['loss']))
    

    输出:

    dataset:
     [[ 10  15  25]
     [ 20  25  45]
     [ 30  35  65]
     [ 40  45  85]
     [ 50  55 105]
     [ 60  65 125]
     [ 70  75 145]
     [ 80  85 165]
     [ 90  95 185]]
    train_X:
    [[[ 10  15  25]
      [ 20  25  45]
      [ 30  35  65]]
    
     [[ 20  25  45]
      [ 30  35  65]
      [ 40  45  85]]
    
     [[ 30  35  65]
      [ 40  45  85]
      [ 50  55 105]]
    
     [[ 40  45  85]
      [ 50  55 105]
      [ 60  65 125]]
    
     [[ 50  55 105]
      [ 60  65 125]
      [ 70  75 145]]
    
     [[ 60  65 125]
      [ 70  75 145]
      [ 80  85 165]]]
    train_y:
    [[ 40  45  85]
     [ 50  55 105]
     [ 60  65 125]
     [ 70  75 145]
     [ 80  85 165]
     [ 90  95 185]]
    
    train_X.shape:(6, 3, 3),trian_y.shape:(6, 3)
    
    n_features: 3
    Model: "sequential"
    _________________________________________________________________
    Layer (type)                 Output Shape              Param #   
    =================================================================
    conv1d (Conv1D)              (None, 2, 64)             448       
    _________________________________________________________________
    max_pooling1d (MaxPooling1D) (None, 1, 64)             0         
    _________________________________________________________________
    flatten (Flatten)            (None, 64)                0         
    _________________________________________________________________
    dense (Dense)                (None, 50)                3250      
    _________________________________________________________________
    dense_1 (Dense)              (None, 3)                 153       
    =================================================================
    Total params: 3,851
    Trainable params: 3,851
    Non-trainable params: 0
    _________________________________________________________________
    
     None
    
    yhat: [[100.58862 106.20969 207.11055]]
    
    train_acc:0.9979444 
    train_loss:36.841995810692595
    

    2.2.2 Multi-output CNN Model

    与多个输入序列一样,还有另一种更精细的方法来建模问题。每个输出序列可以由单独的输出CNN模型处理。我们可以称之为多输出CNN模型。它可能提供更多的灵活性或更好的性能,这取决于正在建模的问题的具体情况。代码实现:

    visible = Input(shape=(n_steps, n_features))
    cnn = Conv1D(filters=64, kernel_size=2, activation='relu')(visible)
    cnn = MaxPooling1D(pool_size=2)(cnn)
    cnn = Flatten()(cnn)
    cnn = Dense(50, activation='relu')(cnn)
    

    然后,我们可以为希望预测的三个序列中的每一个定义一个输出层,其中每个输出子模型将预测一个时间步。

    output1 = Dense(1)(cnn)
    output2 = Dense(1)(cnn)
    output3 = Dense(1)(cnn)
    

    绑定模型,编译模型:

    model = Model(inputs=visible, outputs=[output1, output2, output3])
    model.compile(optimizer='adam', loss='mse')
    

    在训练模型时,每个样本需要三个独立的输出数组。可以通过将具有形状[7,3]的输出训练数据转换为具有形状[7,1]的三个数组来实现这一点。

    y1 = y[:, 0].reshape((y.shape[0], 1))
    y2 = y[:, 1].reshape((y.shape[0], 1))
    y3 = y[:, 2].reshape((y.shape[0], 1))
    

    开始训练:

    model.fit(X, [y1,y2,y3], epochs=2000, verbose=0)
    

    完整代码:

    import numpy as np
    from tensorflow.keras.models import Sequential, Model
    from tensorflow.keras.layers import Dense, Flatten, Conv1D, MaxPooling1D, Input, concatenate
    from tensorflow.keras.utils import plot_model
    
    def split_sequences(first_seq, secend_seq, sw_width):
        '''
        该函数将序列数据分割成样本
        '''
        input_seq1 = np.array(first_seq).reshape(len(first_seq), 1)
        input_seq2 = np.array(secend_seq).reshape(len(secend_seq), 1)
        out_seq = np.array([first_seq[i]+secend_seq[i] for i in range(len(first_seq))])
        out_seq = out_seq.reshape(len(out_seq), 1)
        
        dataset = np.hstack((input_seq1, input_seq2, out_seq))
        print('dataset:\n',dataset)
        
        X, y = [], []
        
        for i in range(len(dataset)):
            end_element_index = i + sw_width
            if end_element_index > len(dataset) - 1:
                break
            
            # 该语句实现步长为1的滑动窗口截取数据功能;
            seq_x, seq_y = dataset[i:end_element_index, :], dataset[end_element_index, :]
            
            X.append(seq_x)
            y.append(seq_y)
            
            process_X, process_y = np.array(X), np.array(y)
        
        n_features = process_X.shape[2]
        y1 = process_y[:, 0].reshape((process_y.shape[0], 1))
        y2 = process_y[:, 1].reshape((process_y.shape[0], 1))
        y3 = process_y[:, 2].reshape((process_y.shape[0], 1))
        
        print('train_X:\n{}\ntrain_y:\n{}\n'.format(process_X, process_y))
        print('train_X.shape:{},trian_y.shape:{}\n'.format(process_X.shape, process_y.shape))
        print('n_features:',n_features)
        return process_X, process_y, n_features, y1, y2, y3
    
        
    def oned_cnn_model(n_steps, n_features, X, y, test_X, epoch_num, verbose_set):
        visible = Input(shape=(n_steps, n_features))
        cnn = Conv1D(filters=64, kernel_size=2, activation='relu')(visible)
        cnn = MaxPooling1D(pool_size=2)(cnn)
        cnn = Flatten()(cnn)
        cnn = Dense(50, activation='relu')(cnn)
        
        output1 = Dense(1)(cnn)
        output2 = Dense(1)(cnn)
        output3 = Dense(1)(cnn)
        
        model = Model(inputs=visible, outputs=[output1, output2, output3])
        
        model.compile(optimizer='adam', loss='mse',
                     metrics=['accuracy'], loss_weights=None, sample_weight_mode=None, weighted_metrics=None, target_tensors=None)
        
        print('\n',model.summary())
        plot_model(model, to_file='vector_output_cnn_model.png', show_shapes=True, show_layer_names=True, rankdir='TB', dpi=200)
    
        model.fit(X, y, batch_size=32, epochs=epoch_num, verbose=verbose_set)
        
        
        yhat = model.predict(test_X, verbose=0)
        print('\nyhat:', yhat)
        
        return model
    
    if __name__ == '__main__':
        
        train_seq1 = [10, 20, 30, 40, 50, 60, 70, 80, 90]
        train_seq2 = [15, 25, 35, 45, 55, 65, 75, 85, 95]
        sw_width = 3
    
        epoch_num = 2000
        verbose_set = 0
        
        train_X, train_y, n_features, y1, y2, y3 = split_sequences(train_seq1, train_seq2, sw_width)
    
        # 预测
        x_input = np.array([[70,75,145], [80,85,165], [90,95,185]])
        x_input = x_input.reshape((1, sw_width, n_features))
        
        model = oned_cnn_model(sw_width, n_features, train_X, [y1, y2, y3], x_input, epoch_num, verbose_set)
        
    

    输出:

    dataset:
     [[ 10  15  25]
     [ 20  25  45]
     [ 30  35  65]
     [ 40  45  85]
     [ 50  55 105]
     [ 60  65 125]
     [ 70  75 145]
     [ 80  85 165]
     [ 90  95 185]]
    train_X:
    [[[ 10  15  25]
      [ 20  25  45]
      [ 30  35  65]]
    
     [[ 20  25  45]
      [ 30  35  65]
      [ 40  45  85]]
    
     [[ 30  35  65]
      [ 40  45  85]
      [ 50  55 105]]
    
     [[ 40  45  85]
      [ 50  55 105]
      [ 60  65 125]]
    
     [[ 50  55 105]
      [ 60  65 125]
      [ 70  75 145]]
    
     [[ 60  65 125]
      [ 70  75 145]
      [ 80  85 165]]]
    train_y:
    [[ 40  45  85]
     [ 50  55 105]
     [ 60  65 125]
     [ 70  75 145]
     [ 80  85 165]
     [ 90  95 185]]
    
    train_X.shape:(6, 3, 3),trian_y.shape:(6, 3)
    
    n_features: 3
    Model: "model_2"
    __________________________________________________________________________________________________
    Layer (type)                    Output Shape         Param #     Connected to                     
    ==================================================================================================
    input_4 (InputLayer)            [(None, 3, 3)]       0                                            
    __________________________________________________________________________________________________
    conv1d_4 (Conv1D)               (None, 2, 64)        448         input_4[0][0]                    
    __________________________________________________________________________________________________
    max_pooling1d_4 (MaxPooling1D)  (None, 1, 64)        0           conv1d_4[0][0]                   
    __________________________________________________________________________________________________
    flatten_4 (Flatten)             (None, 64)           0           max_pooling1d_4[0][0]            
    __________________________________________________________________________________________________
    dense_14 (Dense)                (None, 50)           3250        flatten_4[0][0]                  
    __________________________________________________________________________________________________
    dense_15 (Dense)                (None, 1)            51          dense_14[0][0]                   
    __________________________________________________________________________________________________
    dense_16 (Dense)                (None, 1)            51          dense_14[0][0]                   
    __________________________________________________________________________________________________
    dense_17 (Dense)                (None, 1)            51          dense_14[0][0]                   
    ==================================================================================================
    Total params: 3,851
    Trainable params: 3,851
    Non-trainable params: 0
    __________________________________________________________________________________________________
    
     None
    
    yhat: [array([[101.1264]], dtype=float32), array([[106.274635]], dtype=float32), array([[207.64928]], dtype=float32)]
    

    网络结构图:
    在这里插入图片描述


    由于字数过多(已经28000多字)页面变卡,下篇继续将剩下的两类模型。
    在这里插入图片描述


    参考:
    https://machinelearningmastery.com/how-to-develop-convolutional-neural-network-models-for-time-series-forecasting/

    展开全文
  • 针对风电功率混沌序列的特点,提出一种基于改进局域Volterra自适应滤波器的风电功率混沌时间序列预测模型。首先,针对邻近点及其坐标分量在时间上与预测点距离不同、对预测点的影响不同的特点,提出一种考虑时间影响...
  • 论文研究-基于贝叶斯框架下LS-SVM的时间序列预测模型 .pdf,
  • 基于贝叶斯框架下LSSVM的时间序列预测模型 基于贝叶斯框架下LSSVM的时间序列预测模型
  • 基于新颖输入表达的CRBM时间序列预测模型,任永攀,毛京丽,深度学习通过多层神经网络能够提取更深层次的信息,已经在图像预测领域取得了较好的性能,其中条件受限玻耳兹曼机(CRBM)模型,因考
  • 时间序列定义: 时间序列是按照一定的时间间隔排列的一组数据,其时间间隔可以...对于时间序列预测,由于很难确定它与其他变量之间的关系,这时我们就不能用回归去预测,而应使用时间序列方法进行预测。 采用时间序列

    时间序列系列文章:

    时间序列(一):时间序列数据与时间序列预测模型
    时间序列(二):时间序列平稳性检测
    时间序列(三):ARIMA模型实战

    时间序列及其预测是日常工作中建模,分析,预测的重要组成部分。本系列我们将从0开始介绍时间序列的含义,模型及其分析。本篇为第一部分,我们主要介绍时间序列,与其常用的预测模型。

    时间序列定义:

    时间序列是按照一定的时间间隔排列的一组数据,其时间间隔可以是任意的时间单位,如小时、日、周月等。比如,每天某产品的用户数量,每个月的销售额,这些数据形成了以一定时间间隔的数据。

    通过对这些时间序列的分析,从中发现和揭示现象发展变化的规律,并将这些知识和信息用于预测。比如销售量是上升还是下降,销售量是否与季节有关,是否可以通过现有的数据预测未来一年的销售额是多少等。

    对于时间序列的预测,由于很难确定它与其他变量之间的关系,这时我们就不能用回归去预测,而应使用时间序列方法进行预测。

    采用时间序列分析进行预测时需要一系列的模型,这种模型称为时间序列模型。

    时间序列预测模型与方法

    注:本部分只关注相关模型与分析的方法,模型的选择,调参与优化会放在后续文章中详细讲解

    原始数据

    本文所使用原始数据与代码,可以在公众号:Smilecoc的杂货铺 中回复“时间序列”获取。可直接扫描文末二维码关注!

    朴素法

    朴素法就是预测值等于实际观察到的最后一个值。它假设数据是平稳且没有趋势性与季节性的。通俗来说就是以后的预测值都等于最后的值。

    这种方法很明显适用情况极少,所以我们重点通过这个方法来熟悉一下数据可视化与模型的评价及其相关代码。

    #朴素法
    dd = np.asarray(train['Count'])#训练组数据
    y_hat = test.copy()#测试组数据
    y_hat['naive'] = dd[len(dd) - 1]#预测组数据
    
    #数据可视化
    plt.figure(figsize=(12, 8))
    plt.plot(train.index, train['Count'], label='Train')
    plt.plot(test.index, test['Count'], label='Test')
    plt.plot(y_hat.index, y_hat['naive'], label='Naive Forecast')
    plt.legend(loc='best')
    plt.title("Naive Forecast")
    plt.show()
    

    得到结果:
    在这里插入图片描述
    我们通过计算均方根误差,检查模型在测试数据集上的准确率。
    其中均方根误差(RMSE)是各数据偏离真实值的距离平方和的平均数的开方

    #计算均方根误差RMSE
    from sklearn.metrics import mean_squared_error
    from math import sqrt
    
    # mean_squared_error求均方误差
    rmse = sqrt(mean_squared_error(test['Count'], y_hat['naive']))
    print(rmse)
    

    得到均方根误差为1053

    简单平均法

    简单平均法就是预测的值为之前过去所有值的平均.当然这不会很准确,但这种预测方法在某些情况下效果是最好的。

    #简单平均法
    y_hat_avg = test.copy()
    y_hat_avg['avg_forecast'] = train['Count'].mean()
    

    其后续可视化与模型效果评估方法与上述一致,这里不再赘述,需要详细代码可以查看相关源码。得到RMSE值为2637

    移动平均法

    我们经常会遇到这种数据集,比如价格或销售额某段时间大幅上升或下降。如果我们这时用之前的简单平均法,就得使用所有先前数据的平均值,但在这里使用之前的所有数据是说不通的,因为用开始阶段的价格值会大幅影响接下来日期的预测值。因此,我们只取最近几个时期的价格平均值。很明显这里的逻辑是只有最近的值最要紧。这种用某些窗口期计算平均值的预测方法就叫移动平均法。

    #移动平均法
    y_hat_avg = test.copy()
    #利用时间窗函数rolling求平均值u
    y_hat_avg['moving_avg_forecast'] = train['Count'].rolling(60).mean().iloc[-1]
    

    其后续可视化与模型效果评估方法与上述一致,这里不再赘述,需要详细代码可以查看相关源码。得到RMSE值为1121

    指数平滑法

    在做时序预测时,一个显然的思路是:认为离着预测点越近的点,作用越大。比如我这个月体重100斤,去年某个月120斤,显然对于预测下个月体重而言,这个月的数据影响力更大些。假设随着时间变化权重以指数方式下降——最近为0.8,然后0.8**2,0.8**3…,最终年代久远的数据权重将接近于0。将权重按照指数级进行衰减,这就是指数平滑法的基本思想。

    指数平滑法有几种不同形式:一次指数平滑法针对没有趋势和季节性的序列,二次指数平滑法针对有趋势但没有季节性的序列,三次指数平滑法针对有趋势也有季节性的序列。“

    所有的指数平滑法都要更新上一时间步长的计算结果,并使用当前时间步长的数据中包含的新信息。它们通过”混合“新信息和旧信息来实现,而相关的新旧信息的权重由一个可调整的参数来控制。

    一次指数平滑

    一次指数平滑法的递推关系如下:

    si=αxi+(1α)si10α1s_{i}=\alpha x_{i}+(1-\alpha)s_{i-1},其中 0 \leq \alpha \leq 1

    其中,sis_{i}是时间步长i(理解为第i个时间点)上经过平滑后的值,xix_{i} 是这个时间步长上的实际数据。 α\alpha可以是0和1之间的任意值,它控制着新旧信息之间的平衡:当 α\alpha 接近1,就只保留当前数据点;当α\alpha 接近0时,就只保留前面的平滑值(整个曲线都是平的)。我们展开它的递推关系式:

    我们展开它的递推关系式:
    si=αxi+(1α)si1=αxi+(1α)[αxi1+(1α)si2]=αxi+(1α)[αxi1+(1α)[αxi2+(1α)si3]]=α[xi+(1α)xi1+(1α)2xi2+(1α)3si3]=...=αj=0i(1α)jxij\begin{aligned} s_{i}&=\alpha x_{i}+(1-\alpha)s_{i-1} \\ &=\alpha x_{i}+(1-\alpha)[\alpha x_{i-1}+(1-\alpha)s_{i-2}]\\ &=\alpha x_{i}+(1-\alpha)[\alpha x_{i-1}+(1-\alpha)[\alpha x_{i-2}+(1-\alpha)s_{i-3}]]\\ &=\alpha[x_{i}+(1-\alpha)x_{i-1}+(1-\alpha)^{2}x_{i-2}+(1-\alpha)^{3}s_{i-3}]\\ &=... \\ &=\alpha\sum_{j=0}^{i}(1-\alpha)^{j}x_{i-j} \end{aligned}

    可以看出,在指数平滑法中,所有先前的观测值都对当前的平滑值产生了影响,但它们所起的作用随着参数 α\alpha 的幂的增大而逐渐减小。那些相对较早的观测值所起的作用相对较小。同时,称α为记忆衰减因子可能更合适——因为α的值越大,模型对历史数据“遗忘”的就越快。从某种程度来说,指数平滑法就像是拥有无限记忆(平滑窗口足够大)且权值呈指数级递减的移动平均法。一次指数平滑所得的计算结果可以在数据集及范围之外进行扩展,因此也就可以用来进行预测。预测方式为:

    xi+h=six_{i+h}=s_{i}

    sis_{i}是最后一个已经算出来的值。h等于1代表预测的下一个值。

    我们可以通过statsmodels中的时间序列模型进行指数平滑建模。官方文档地址为:
    https://www.statsmodels.org/stable/generated/statsmodels.tsa.holtwinters.SimpleExpSmoothing.html
    具体代码如下:

    #一次指数平滑
    from statsmodels.tsa.api import SimpleExpSmoothing
     
    y_hat_avg = test.copy()
    fit = SimpleExpSmoothing(np.asarray(train['Count'])).fit(smoothing_level=0.6, optimized=False)
    y_hat_avg['SES'] = fit.forecast(len(test))
    

    之后同样进行数据可视化并查看模型效果

    plt.figure(figsize=(16, 8))
    plt.plot(train['Count'], label='Train')
    plt.plot(test['Count'], label='Test')
    plt.plot(y_hat_avg['SES'], label='SES')
    plt.legend(loc='best')
    plt.show()
    

    可视化结果为:
    在这里插入图片描述
    RMSE结果为1040

    二次指数平滑

    在介绍二次指数平滑前介绍一下趋势的概念。

    趋势,或者说斜率的定义很简单:b=Δy/Δxb=Δy/Δx,其中ΔxΔx为两点在x坐标轴的变化值,所以对于一个序列而言,相邻两个点的Δx=1Δx=1,因此b=Δy=y(x)y(x1)b=Δy=y(x)-y(x-1)。 除了用点的增长量表示,也可以用二者的比值表示趋势。比如可以说一个物品比另一个贵20块钱,等价地也可以说贵了5%,前者称为可加的(addtive),后者称为可乘的(multiplicative)。在实际应用中,可乘的模型预测稳定性更佳,但是为了便于理解,我们在这以可加的模型为例进行推导。
    指数平滑考虑的是数据的baseline,二次指数平滑在此基础上将趋势作为一个额外考量,保留了趋势的详细信息。即我们保留并更新两个量的状态:平滑后的信号和平滑后的趋势。公式如下:
    基准等式
    si=αxi+(1α)(si1+ti1)s_{i}=\alpha x_{i}+(1-\alpha)(s_{i-1}+t_{i-1})
    趋势等式
    ti=β(sisi1)+(1β)ti1t_{i}=\beta (s_{i}-s_{i-1})+(1-\beta)t_{i-1}

    第二个等式描述了平滑后的趋势。当前趋势的未平滑“值”( tit_{i} )是当前平滑值( sis_{i} )和上一个平滑值(si1s_{i-1})的差;也就是说,当前趋势告诉我们在上一个时间步长里平滑信号改变了多少。要想使趋势平滑,我们用一次指数平滑法对趋势进行处理,并使用参数 β\beta (理解:对 tit_{i} 的处理类似于一次平滑指数法中的 sis_{i} ,即对趋势也需要做一个平滑,临近的趋势权重大)。

    为获得平滑信号,我们像上次那样进行一次混合,但要同时考虑到上一个平滑信号及趋势。假设单个步长时间内保持着上一个趋势,那么第一个等式的最后那项就可以对当前平滑信号进行估计。

    若要利用该计算结果进行预测,就取最后那个平滑值,然后每增加一个时间步长就在该平滑值上增加一次最后那个平滑趋势:

    xi+h=si+htix_{i+h}=s_{i}+ht_{i}

    在这里插入图片描述
    之后使用二次指数平滑进行预测:

    from statsmodels.tsa.api import Holt
     
    y_hat_avg = test.copy()
     
    fit = Holt(np.asarray(train['Count'])).fit(smoothing_level=0.3, smoothing_slope=0.1)
    y_hat_avg['Holt_linear'] = fit.forecast(len(test))
    

    结果如图:
    在这里插入图片描述
    得到对应的RMSE为1033

    三次指数平滑

    在应用这种算法前,我们先介绍一个新术语。假如有家酒店坐落在半山腰上,夏季的时候生意很好,顾客很多,但每年其余时间顾客很少。因此,每年夏季的收入会远高于其它季节,而且每年都是这样,那么这种重复现象叫做“季节性”(Seasonality)。如果数据集在一定时间段内的固定区间内呈现相似的模式,那么该数据集就具有季节性。
    在这里插入图片描述
    二次指数平滑考虑了序列的基数和趋势,三次就是在此基础上增加了一个季节分量。类似于趋势分量,对季节分量也要做指数平滑。比如预测下一个季节第3个点的季节分量时,需要指数平滑地考虑当前季节第3个点的季节分量、上个季节第3个点的季节分量…等等。详细的有下述公式(累加法):

    si=α(xipik)+(1α)(si1+ti1)ti=β(sisi1)+(1β)ti1pi=γ(xisi)+(1γ)pik\begin{aligned} s_{i}&=\alpha (x_{i}-p_{i-k})+(1-\alpha)(s_{i-1}+t_{i-1}) \\ t_{i} &=\beta (s_{i}-s_{i-1})+(1-\beta)t_{i-1}\\ p_{i}&=\gamma (x_{i}-s_{i})+(1-\gamma)p_{i-k} \end{aligned}

    其中, pip_{i} 是指“周期性”部分。预测公式如下:

    xi+h=si+hti+pik+hx_{i+h}=s_{i}+ht_{i}+p_{i-k+h}

    k 是这个周期的长度。

    在使用二次平滑模型与三次平滑模型前,我们可以使用sm.tsa.seasonal_decompose分解时间序列,可以得到以下分解图形——从上到下依次是原始数据、趋势数据、周期性数据、随机变量(残差值)

    在这里插入图片描述
    根据分析图形和数据可以确定对应的季节参数

    具体代码为:

    #三次指数平滑
    from statsmodels.tsa.api import ExponentialSmoothing
     
    y_hat_avg = test.copy()
    fit1 = ExponentialSmoothing(np.asarray(train['Count']), seasonal_periods=7, trend='add', seasonal='add', ).fit()
    y_hat_avg['Holt_Winter'] = fit1.forecast(len(test))
    

    在这里插入图片描述
    得到的RMSE为575。我们可以看到趋势和季节性的预测准确度都很高。你可以试着调整参数来优化这个模型。

    AR模型

    AR(Auto Regressive Model)自回归模型是线性时间序列分析模型中最简单的模型。通过自身前面部分的数据与后面部分的数据之间的相关关系(自相关)来建立回归方程,从而可以进行预测或者分析。服从p阶的自回归方程表达式如下:

    xt=ϕ1xt1+ϕ2xt2++ϕpxtp+μtx_{t}=\phi_{1}x_{t-1}+\phi_{2}x_{t-2}+\cdots+\phi_{p}x_{t-p}+\mu_{t}

    表示为AR(p)AR(p),。其中,μt\mu_{t}表示白噪声,是时间序列中的数值的随机波动,但是这些波动会相互抵消,最终是0。ϕ\phi表示自回归系数。

    所以当只有一个时间记录点时,称为一阶自回归过程,即AR(1)。其表达式为:
    xt=ϕ1xt1+μtx_{t}=\phi_{1}x_{t-1}+\mu_{t}

    利用Python建立AR模型一般会用到我们之后会说到的ARIMA模型(AR模型中的p是ARIMA模型中的参数之一,只要将其他的参数设置为0即为AR模型)。您可以先阅读后续ARIMA模型的内容并参考文件中的代码查看具体的内容

    MA模型

    MA(Moving Average Model)移动平均模型通过将一段时间序列中白噪声(误差)进行加权和,可以得到移动平均方程。如下模型为q阶移动平均过程,表示为MA(q)。

    xt=μ+μt+θ1μt1+θ2μt2++θqμtqx_{t}=\mu+\mu_{t}+\theta_{1}\mu_{t-1}+\theta_{2}\mu_{t-2}+\cdots+\theta_{q}\mu_{t-q}

    其中xtx_{t}表示t期的值,当期的值由前q期的误差值来决定,μμ值是常数项,相当于普通回归中的截距项,μt\mu_{t}是当期的随机误差。MA模型的核心思想是每一期的随机误差都会影响当期值,把前q期的所有误差加起来就是对t期值的影响。

    同样,利用Python建立MA模型一般会用到我们之后会说到的ARIMA模型,您可以先阅读后续ARIMA模型的内容并参考文件中的代码查看具体的内容

    ARMA模型

    ARMA(Auto Regressive and Moving Average Model)自回归移动平均模型是与自回归和移动平均模型两部分组成。所以可以表示为ARMA(p, q)。p是自回归阶数,q是移动平均阶数。

    xt=ϕ1xt1+ϕ2xt2++ϕpxtp+μt+θ1μt1+θ2μt2++θqμtqx_{t}=\phi_{1}x_{t-1}+\phi_{2}x_{t-2}+\cdots+\phi_{p}x_{t-p}+\mu_{t}+\theta_{1}\mu_{t-1}+\theta_{2}\mu_{t-2}+\cdots+\theta_{q}\mu_{t-q}

    从式子中就可以看出,自回归模型结合了两个模型的特点,其中,AR可以解决当前数据与后期数据之间的关系,MA则可以解决随机变动也就是噪声的问题。

    ARIMA模型

    ARIMA(Auto Regressive Integrate Moving Average Model)差分自回归移动平均模型是在ARMA模型的基础上进行改造的,ARMA模型是针对t期值进行建模的,而ARIMA是针对t期与t-d期之间差值进行建模,我们把这种不同期之间做差称为差分,这里的d是几就是几阶差分。ARIMA模型也是基于平稳的时间序列的或者差分化后是稳定的,另外前面的几种模型都可以看作ARIMA的某种特殊形式。表示为ARIMA(p, d, q)。p为自回归阶数,q为移动平均阶数,d为时间成为平稳时所做的差分次数,也就是Integrate单词的在这里的意思。

    具体步骤如下:

    xt=ϕ1wt1+ϕ2wt2++ϕpwtp+μt+θ1μt1+θ2μt2++θqμtqx_{t}=\phi_{1}w_{t-1}+\phi_{2}w_{t-2}+\cdots+\phi_{p}w_{t-p}+\mu_{t}+\theta_{1}\mu_{t-1}+\theta_{2}\mu_{t-2}+\cdots+\theta_{q}\mu_{t-q}

    上面公式中的wtw_{t}表示t期经过d阶差分以后的结果。我们可以看到ARIMA模型的形式基本与ARMA的形式是一致的,只不过把XX换成了ww

    使用ARIMA进行预测代码如下:

    from statsmodels.tsa.arima_model import ARIMA
     
    ts_ARIMA= train['Count'].astype(float)
    fit1 = ARIMA(ts_ARIMA, order=(7, 1, 4)).fit()
    y_hat_ARIMA = fit1.predict(start="2013-11-1", end="2013-12-31", dynamic=True)
    

    并画出预测值与实际值图形:

    plt.figure(figsize=(16, 8))
    plt.plot(train['Count'], label='Train')
    plt.plot(test['Count'], label='Test')
    plt.plot(y_hat_ARIMA, label='ARIMA')
    plt.legend(loc='best')
    plt.show()
    

    在这里插入图片描述
    并计算RMSE:

    from sklearn.metrics import mean_squared_error
    from math import sqrt
      
    rmse = sqrt(mean_squared_error(test['Count'],y_hat_ARIMA.to_frame()))
    print(rmse)
    

    得到对应的RMSE为3723

    SARIMA模型

    SARIMA季节性自回归移动平均模型模型在ARIMA模型的基础上添加了季节性的影响,结构参数有七个:SARIMA(p,d,q)(P,D,Q,s)
    其中p,d,q分别为之前ARIMA模型中我们所说的p:趋势的自回归阶数。d:趋势差分阶数。q:趋势的移动平均阶数。
    P:季节性自回归阶数。
    D:季节性差分阶数。
    Q:季节性移动平均阶数。
    s:单个季节性周期的时间步长数。

    import statsmodels.api as sm
    y_hat_avg = test.copy()
    fit1 = sm.tsa.statespace.SARIMAX(train.Count, order=(2, 1, 4), seasonal_order=(0, 1, 1, 7)).fit()
    y_hat_avg['SARIMA'] = fit1.predict(start="2013-11-1", end="2013-12-31", dynamic=True)
    

    得到实际值与预测值如下:

    plt.figure(figsize=(16, 8))
    plt.plot(train['Count'], label='Train')
    plt.plot(test['Count'], label='Test')
    plt.plot(y_hat_avg['SARIMA'], label='SARIMA')
    plt.legend(loc='best')
    plt.show()
    

    在这里插入图片描述
    并计算RMSE:

    from sklearn.metrics import mean_squared_error
    from math import sqrt
    rmse = sqrt(mean_squared_error(test['Count'], y_hat_avg['SARIMA']))
    print(rmse)
    

    结果为933

    其他时间序列预测的模型还有SARIMAX模型(在ARIMA模型上加了季节性的因素),Prophet模型,ARCH模型,LSTM神经网络模型等。限于篇幅,感兴趣的同学可以自行查看相关模型资料

    在后续的文章中我们将讲解如何确定数据的平稳性与数据预处理,为后续时间序列的建模做准备

    参考文章:
    https://www.analyticsvidhya.com/blog/2018/02/time-series-forecasting-methods/
    https://blog.csdn.net/anshuai_aw1/article/details/82499095

    相关代码与数据可关注公众号并回复:时间序列获取
    在这里插入图片描述

    展开全文
  • ARX_model 该存储库包含用于时间序列预测模型ARX的python程序。 AX.py和csv_read.py是两个Python文件,用于使用csv文件作为输入来测试AR模型。 ARX_test是用于测试所提出的ARX模型的性能的程序。
  • 我最近读了一篇非常有趣的论文,叫做 Deep Transformer Models for Time Series Forecasting: The...预测流感流行病例:时间序列预测的深度变形模型:流感流行病例 能源生产预测:能源消耗预测使用堆叠非参数贝叶斯方法 天
  • 时间序列预测步骤I am a strong believer in “learning by doing” philosophy. 我坚信“做中学”的哲学。 Data science is an applied field, so you need to get your feet wet to learn something. One can ...
  • 运用混沌理论加权一阶局域预测方法,建立了混沌时间序列瓦斯异常涌出预测模型;并利用平煤十矿己15-24080掘进工作面31d的瓦斯实际浓度数据对该模型进行了预测效果检验。结果表明:时间序列的最大Lyapunov指数大于零,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,185
精华内容 1,674
关键字:

时间序列预测模型