簡體   English   中英

如何使用深度學習模型進行時間序列預測?

[英]How to use deep learning models for time-series forecasting?

我從機器(m1, m2, so on)了 28 天的信號。 (注意:每天的每個信號長度為 360)。

machine_num, day1, day2, ..., day28
m1, [12, 10, 5, 6, ...], [78, 85, 32, 12, ...], ..., [12, 12, 12, 12, ...]
m2, [2, 0, 5, 6, ...], [8, 5, 32, 12, ...], ..., [1, 1, 12, 12, ...]
...
m2000, [1, 1, 5, 6, ...], [79, 86, 3, 1, ...], ..., [1, 1, 12, 12, ...]

我想預測未來3天每台機器的信號序列。 即在第day29 、第day30 、第day31 但是,我沒有第29天、第30天和第31天的值。 所以,我的計划如下使用LSTM模型。

第一步是獲取day 1信號並要求預測day 2信號,然后在下一步獲取第days 1, 2信號並要求預測day 3信號等,因此當我到達day 28,網絡擁有最多 28 個信號,並被要求預測第day 29的信號,等等。

我嘗試做一個單變量 LSTM 模型,如下所示。

# univariate lstm example
from numpy import array
from keras.models import Sequential
from keras.layers import LSTM
from keras.layers import Dense
# define dataset
X = array([[10, 20, 30], [20, 30, 40], [30, 40, 50], [40, 50, 60]])
y = array([40, 50, 60, 70])
# reshape from [samples, timesteps] into [samples, timesteps, features]
X = X.reshape((X.shape[0], X.shape[1], 1))
# define model
model = Sequential()
model.add(LSTM(50, activation='relu', input_shape=(3, 1)))
model.add(Dense(1))
model.compile(optimizer='adam', loss='mse')
# fit model
model.fit(X, y, epochs=1000, verbose=0)
# demonstrate prediction
x_input = array([50, 60, 70])
x_input = x_input.reshape((1, 3, 1))
yhat = model.predict(x_input, verbose=0)
print(yhat)

然而,這個例子非常簡單,因為它沒有像我這樣的長序列。 例如,我的m1數據如下所示。

m1 = [[12, 10, 5, 6, ...], [78, 85, 32, 12, ...], ..., [12, 12, 12, 12, ...]]

此外,我需要第293031天的預測。 在這種情況下,我不確定如何更改此示例以滿足我的需要。 我想特別知道我選擇的方向是否正確。 如果是這樣,該怎么做。

如果需要,我很樂意提供更多詳細信息。

編輯:

我已經提到了model.summary()

在此處輸入圖片說明

我認為你要往好的方向發展,要增加每天的時間步數,你需要在你的數據中添加一個pad,這個例子可以幫助你: https : //github.com/keras-team/keras /blob/master/examples/imdb_lstm.py#L46

但是,我也會嘗試另一種方法,例如固定時間步數,例如 3 天、4 天、5 天……然后,評估您的火車,您可以選擇最適合您的模型的時間步數。

也許你最初增加天數的方法會更好,但在這類問題中,找到 LSTM 中的最佳時間步數非常重要。

模型和形狀

由於這些是序列中的序列,您需要以不同的格式使用您的數據。

盡管您可以像(machines, days, 360)簡單地將 360 視為特征(在某些情況下可以工作),但對於一個健壯的模型(然后可能存在速度問題),您需要同時處理事物作為序列。

然后我會使用像(machines, days, 360, 1)和兩個級別的重復數據。

我們的模型input_shape將是(None, 360, 1)

模型案例 1 - 僅按日返還

數據形狀:( (machines, days, 360)
對數據應用一些標准化。

這是一個示例,但模型可以很靈活,因為您可以添加更多層、嘗試卷積等:

inputs = Input((None, 360)) #(m, d, 360)
outs = LSTM(some_units, return_sequences=False, 
            stateful=depends_on_training_approach)(inputs)  #(m, some_units)
outs = Dense(360, activation=depends_on_your_normalization)(outs) #(m, 360)
outs = Reshape((1,360)) #(m, 1, 360) 
    #this reshape is not necessary if using the "shifted" approach - see time windows below
    #it would then be (m, d, 360)

model = Model(inputs, outs)

根據日內序列的復雜性,他們可以用這個得到很好的預測,但如果他們以復雜的方式進化,那么下一個模​​型會好一點。

永遠記住,您可以創建更多層並探索事物以增加此模型的能力,這只是一個小例子

模型案例 2 - 兩級重發

數據形狀:( (machines, days, 360, 1)
對數據應用一些標准化。

有很多方法可以試驗如何做到這一點,但這里是一個簡單的方法。

inputs = Input((None, 360, 1)) #(m, d, 360, 1)

#branch 1
inner_average = TimeDistributed(
                    Bidirectional(
                        LSTM(units1, return_sequences=True, stateful=False),
                        merge_mode='ave'
                    )
                )(inputs) #(m, d, 360, units1)
inner_average = Lambda(lambda x: K.mean(x, axis=1))(inner_average) #(m, 360, units1)


#branch 2
inner_seq = TimeDistributed(
                LSTM(some_units, return_sequences=False, stateful=False)
            )(inputs) #may be Bidirectional too
            #shape (m, d, some_units)

outer_seq = LSTM(other_units, return_sequences = False, 
                 stateful=depends_on_training_approach)(inner_seq) #(m, other_units)

outer_seq = Dense(few_units * 360, activation = 'tanh')(outer_seq) #(m, few_units * 360)
    #activation = same as inner_average 


outer_seq = Reshape((360,few_units))(outer_seq) #(m, 360, few_units)


#join branches

outputs = Concatenate()([inner_average, outer_seq]) #(m, 360, units1+few_units)
outputs = LSTM(units, return_sequences=True, stateful= False)(outputs) #(m, 360,units)
outputs = Dense(1, activation=depends_on_your_normalization)(outputs) #(m, 360, 1)
outputs = Reshape((1,360))(outputs) #(m, 1, 360) for training purposes

model = Model(inputs, outputs)

這是一次嘗試,我做了平均天數,但我可以做,而不是inner_average ,像:

#branch 1
daily_minutes = Permute((2,1,3))(inputs) #(m, 360, d, 1)
daily_minutes = TimeDistributed(
                    LSTM(units1, return_sequences=False, 
                         stateful=depends_on_training_approach)
                )(daily_minutes) #(m, 360, units1)

許多其他探索數據的方式都是可能的,這是一個極具創造性的領域。 例如,您可以在不包括K.mean lambda 層的K.mean之后inner_average使用daily_minutes方法......你明白了。

時間窗口法

你的方法聽起來不錯。 一步預測下一步,兩步預測第三步,三步預測第四步。

上述模型適用於這種方法。

請記住,非常短的輸入可能是無用的,並且可能會使您的模型變得更糟。 (試着想象有多少步驟足以讓你開始預測下一個步驟)

預處理您的數據並將其分組:

  • 長度為 4 的組(例如)
  • 長度為 5 的組
  • ...
  • 長度為 28 的組

您將需要一個手動訓練循環,在每個 epoch 中,您為這些組中的每一個提供食物(您不能同時提供不同的長度)。


另一種方法是,給出所有步驟,讓模型預測一個移位的序列,如:

  • inputs = original_inputs[:, :-1] #排除最后訓練日
  • output outputs = original_inputs[:, 1:] #排除第一個訓練日

為了使上述模型適合這種方法,您需要在每個使用天維度作為步驟的 LSTM 中return_sequences=True (而不是inner_seq )。 inner_average方法將失敗,您將不得不daily_minutes使用帶有return_sequences=True和另一個Permute((2,1,3))daily_minutes方法。

形狀將是:

  • 分支 1 : (m, d, 360, units1)
  • BRANCH2: (m, d, 360, few_units) -需要調節Reshape
    • 使用 1 個時間步長的重塑將是不必要的, days維度將替換 1。
    • 考慮到批量大小和可變天數,您可能需要使用Lambda層來重塑(如果需要詳細信息,請告訴我)

訓練和預測

(抱歉現在沒有時間詳述)

然后,您也可以遵循此處此處提到的方法,通過幾個鏈接更完整 (注意輸出形狀,但是,在您的問題中,我們始終保持時間步長維度,即使它可能是 1)

要點是:

  • 如果您選擇stateful=False
    • 這意味着通過fit輕松訓練(只要您沒有使用“不同長度”的方法);
    • 這也意味着您需要使用stateful=True構建一個新模型,復制訓練模型的權重;
    • 然后你做手動一步一步的預測
  • 如果您從一開始就選擇stateful=True
    • 這必然意味着手動訓練循環(例如使用train_on_batch );
    • 這必然意味着每當您要展示一個批次的序列不是最后一批的續集時,您都需要model.reset_states() (如果您的批次包含完整序列,則為每個批次)。
    • 不需要建立新的模型來手動預測,但手動預測保持不變

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM