マシン_(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()
について言及しました。
これらはシーケンス内のシーケンスであるため、データを別の形式で使用する必要があります。
_(machines, days, 360)
_のようにして、360を機能として扱うこともできますが(ある程度までは機能する可能性があります)、堅牢なモデル(おそらく速度の問題がある)の場合は、両方を次のように扱う必要があります。シーケンス。
次に、_(machines, days, 360, 1)
_のようなデータと2つのレベルの反復を使用します。
モデル_input_shape
_は_(None, 360, 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)
_
日中のシーケンスの複雑さに応じて、これで十分に予測できますが、複雑な方法で進化する場合は、次のモデルが少し良くなります。
より多くのレイヤーを作成し、このモデルの機能を向上させるためにさまざまなことを検討できることを常に覚えておいてください。これはほんの小さな例です
データ形状:_(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つのステップを与えます。
上記のモデルは、このアプローチに適しています。
非常に短い入力は役に立たない場合があり、モデルが悪化する可能性があることに注意してください。 (次のステップの予測を開始するのに合理的に十分なステップ数を想像してみてください)
データを前処理し、グループに分けます。
各エポックでこれらのグループのそれぞれにフィードする手動トレーニングループが必要になります(異なる長さをすべて一緒にフィードすることはできません)。
別のアプローチは、すべてのステップを与え、モデルに次のようなシフトされたシーケンスを予測させることです。
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))
をすぐに使用する必要があります。
形状は次のとおりです。
(m, d, 360, units1)
_(m, d, 360, few_units)
_-Reshape
を調整する必要がありますdays
ディメンションは1を置き換えます。Lambda
レイヤーを使用して、バッチサイズと可変日数を考慮して形状を変更する必要がある場合があります(詳細が必要な場合は、教えてください)(今それを詳述する時間がないので申し訳ありません)
次に、言及されたアプローチ ここ および ここでも、いくつかのリンクでより完全な に従うことができます。 (出力形状に注意してください。ただし、質問では、1であっても、常に時間ステップの次元を維持しています。)
重要な点は次のとおりです。
stateful=False
_を選択した場合:fit
を使用した簡単なトレーニングを意味します(「異なる長さ」のアプローチを使用しなかった場合)。stateful=True
_を使用して新しいモデルを構築し、トレーニング済みモデルの重みをコピーする必要があることも意味します。stateful=True
_を選択した場合:train_on_batch
_を使用)。model.reset_states()
が必要であることを意味します(バッチにシーケンス全体が含まれている場合はすべてのバッチ)。