web-dev-qa-db-ja.com

時系列予測に深層学習モデルを使用するにはどうすればよいですか?

マシン_(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, ...]]
_

さらに、_29_、_30_、_31_の日の予測が必要です。その場合、この例をどのように変更して自分のニーズに応えるかはわかりません。私が選択した方向が正しいかどうかを具体的に知りたい。もしそうなら、それを行う方法。

必要に応じて詳細をお知らせいたします。

編集:

model.summary()について言及しました。

enter image description here

7
EmJ

モデルと形状

これらはシーケンス内のシーケンスであるため、データを別の形式で使用する必要があります。

_(machines, days, 360)_のようにして、360を機能として扱うこともできますが(ある程度までは機能する可能性があります)、堅牢なモデル(おそらく速度の問題がある)の場合は、両方を次のように扱う必要があります。シーケンス。

次に、_(machines, days, 360, 1)_のようなデータと2つのレベルの反復を使用します。

モデル_input_shape_は_(None, 360, 1)_になります

モデルケース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-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)
_

これは1つの試行であり、平均的な日数を作成しましたが、_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)
_

データを探索する他の多くの方法が可能であり、これは非常に創造的な分野です。たとえば、_daily_minutes_ラムダレイヤーを除いて_inner_average_の直後に_K.mean_アプローチを使用できます。

時間窓アプローチ

あなたのアプローチはいいですね。次のステップを予測する1つのステップを与え、3番目のステップを予測する2つのステップを与え、4番目のステップを予測する3つのステップを与えます。

上記のモデルは、このアプローチに適しています。

非常に短い入力は役に立たない場合があり、モデルが悪化する可能性があることに注意してください。 (次のステップの予測を開始するのに合理的に十分なステップ数を想像してみてください)

データを前処理し、グループに分けます。

  • 長さ= 4のグループ(例)
  • 長さ= 5のグループ
  • ...
  • 長さ= 28のグループ

各エポックでこれらのグループのそれぞれにフィードする手動トレーニングループが必要になります(異なる長さをすべて一緒にフィードすることはできません)。


別のアプローチは、すべてのステップを与え、モデルに次のようなシフトされたシーケンスを予測させることです。

  • _inputs = original_inputs[:, :-1]_#最終トレーニング日を除外
  • _outputs = original_inputs[:, 1:]_#最初のトレーニング日を除外

上記のモデルをこのアプローチに適合させるには、日次元をステップとして使用するすべてのLSTMで_return_sequences=True_が必要です(_inner_seq_ではありません)。 (_inner_average_メソッドは失敗し、_daily_minutes_アプローチと_return_sequences=True_および別のPermute((2,1,3))をすぐに使用する必要があります。

形状は次のとおりです。

  • ブランチ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()が必要であることを意味します(バッチにシーケンス全体が含まれている場合はすべてのバッチ)。
    • 手動で予測するために新しいモデルを構築する必要はありませんが、手動での予測は変わりません
2
Daniel Möller