Sebagai pelengkap jawaban yang diterima, jawaban ini menunjukkan perilaku keras dan cara mencapai setiap gambar.
Perilaku keras umum
Pemrosesan internal keras standar selalu banyak ke banyak seperti pada gambar berikut (di mana saya menggunakan features=2
, tekanan dan suhu, hanya sebagai contoh):
Dalam gambar ini, saya meningkatkan jumlah langkah menjadi 5, untuk menghindari kebingungan dengan dimensi lain.
Untuk contoh ini:
- Kami memiliki N tangki minyak
- Kami menghabiskan 5 jam untuk mengambil tindakan setiap jam (langkah waktu)
- Kami mengukur dua fitur:
Array input kami kemudian harus berbentuk seperti (N,5,2)
:
[ Step1 Step2 Step3 Step4 Step5
Tank A: [[Pa1,Ta1], [Pa2,Ta2], [Pa3,Ta3], [Pa4,Ta4], [Pa5,Ta5]],
Tank B: [[Pb1,Tb1], [Pb2,Tb2], [Pb3,Tb3], [Pb4,Tb4], [Pb5,Tb5]],
....
Tank N: [[Pn1,Tn1], [Pn2,Tn2], [Pn3,Tn3], [Pn4,Tn4], [Pn5,Tn5]],
]
Input untuk jendela geser
Seringkali, lapisan LSTM seharusnya memproses seluruh urutan. Membagi windows mungkin bukan ide terbaik. Lapisan memiliki keadaan internal tentang bagaimana suatu urutan berkembang ketika ia melangkah maju. Windows menghilangkan kemungkinan mempelajari urutan panjang, membatasi semua urutan ke ukuran jendela.
Di windows, setiap jendela adalah bagian dari urutan asli yang panjang, tetapi oleh Keras mereka akan dilihat masing-masing sebagai urutan independen:
[ Step1 Step2 Step3 Step4 Step5
Window A: [[P1,T1], [P2,T2], [P3,T3], [P4,T4], [P5,T5]],
Window B: [[P2,T2], [P3,T3], [P4,T4], [P5,T5], [P6,T6]],
Window C: [[P3,T3], [P4,T4], [P5,T5], [P6,T6], [P7,T7]],
....
]
Perhatikan bahwa dalam kasus ini, Anda awalnya hanya memiliki satu urutan, tetapi Anda membaginya dalam banyak urutan untuk membuat windows.
Konsep "apa itu urutan" adalah abstrak. Bagian penting adalah:
- Anda dapat memiliki batch dengan banyak urutan individual
- apa yang membuat urutan menjadi urutan adalah bahwa mereka berevolusi dalam langkah (biasanya langkah waktu)
Mencapai setiap kasus dengan "lapisan tunggal"
Mencapai standar banyak ke banyak:
Anda dapat mencapai banyak ke banyak dengan lapisan LSTM sederhana, menggunakan return_sequences=True
:
outputs = LSTM(units, return_sequences=True)(inputs)
#output_shape -> (batch_size, steps, units)
Mencapai banyak orang menjadi satu:
Dengan menggunakan layer yang sama persis, keras akan melakukan preprocessing internal yang sama persis, tetapi ketika Anda menggunakan return_sequences=False
(atau mengabaikan argumen ini), keras akan secara otomatis membuang langkah-langkah sebelum yang terakhir:
outputs = LSTM(units)(inputs)
#output_shape -> (batch_size, units) --> steps were discarded, only the last was returned
Mencapai satu ke banyak
Sekarang, ini tidak didukung oleh lapisan LSTM yang keras saja. Anda harus membuat strategi sendiri untuk melipatgandakan langkah-langkahnya. Ada dua pendekatan yang baik:
- Buat input multi-langkah yang konstan dengan mengulang tensor
- Gunakan a
stateful=True
untuk secara berulang mengambil output dari satu langkah dan menyajikannya sebagai input dari langkah berikutnya (kebutuhan output_features == input_features
)
Satu ke banyak dengan vektor berulang
Agar sesuai dengan perilaku standar yang keras, kita membutuhkan input dalam langkah-langkah, jadi, kita cukup mengulangi input untuk panjang yang kita inginkan:
outputs = RepeatVector(steps)(inputs) #where inputs is (batch,features)
outputs = LSTM(units,return_sequences=True)(outputs)
#output_shape -> (batch_size, steps, units)
Memahami stateful = Benar
Kini hadir salah satu kemungkinan penggunaan stateful=True
(selain menghindari pemuatan data yang tidak dapat memuat memori komputer Anda sekaligus)
Stateful memungkinkan kita untuk memasukkan "bagian" dari urutan secara bertahap. Perbedaannya adalah:
- Dalam
stateful=False
, batch kedua berisi urutan baru, terlepas dari batch pertama
- Dalam
stateful=True
, batch kedua melanjutkan batch pertama, memperpanjang urutan yang sama.
Ini seperti membagi urutan di windows juga, dengan dua perbedaan utama ini:
- windows ini tidak menempatkan !!
stateful=True
akan melihat jendela-jendela ini terhubung sebagai satu urutan panjang
Dalam stateful=True
, setiap batch baru akan ditafsirkan sebagai melanjutkan batch sebelumnya (sampai Anda menelepon model.reset_states()
).
- Urutan 1 dalam batch 2 akan melanjutkan urutan 1 dalam batch 1.
- Urutan 2 dalam batch 2 akan melanjutkan urutan 2 dalam batch 1.
- Urutan n dalam batch 2 akan melanjutkan urutan n dalam batch 1.
Contoh input, batch 1 berisi langkah 1 dan 2, batch 2 berisi langkah 3 hingga 5:
BATCH 1 BATCH 2
[ Step1 Step2 | [ Step3 Step4 Step5
Tank A: [[Pa1,Ta1], [Pa2,Ta2], | [Pa3,Ta3], [Pa4,Ta4], [Pa5,Ta5]],
Tank B: [[Pb1,Tb1], [Pb2,Tb2], | [Pb3,Tb3], [Pb4,Tb4], [Pb5,Tb5]],
.... |
Tank N: [[Pn1,Tn1], [Pn2,Tn2], | [Pn3,Tn3], [Pn4,Tn4], [Pn5,Tn5]],
] ]
Perhatikan keselarasan tangki dalam kelompok 1 dan kelompok 2! Itu sebabnya kita perlu shuffle=False
(kecuali kita hanya menggunakan satu urutan, tentu saja).
Anda dapat memiliki sejumlah batch, tanpa batas. (Untuk memiliki panjang variabel dalam setiap batch, gunakan input_shape=(None,features)
.
Satu ke banyak dengan stateful = Benar
Untuk kasus kami di sini, kami hanya akan menggunakan 1 langkah per batch, karena kami ingin mendapatkan satu langkah output dan menjadikannya sebagai input.
Harap perhatikan bahwa perilaku dalam gambar ini bukan "disebabkan oleh" stateful=True
. Kami akan memaksakan perilaku itu dalam loop manual di bawah ini. Dalam contoh ini, stateful=True
adalah apa yang "memungkinkan" kita untuk menghentikan urutan, memanipulasi apa yang kita inginkan, dan melanjutkan dari tempat kita berhenti.
Sejujurnya, pendekatan berulang mungkin merupakan pilihan yang lebih baik untuk kasus ini. Tapi karena kita melihat ke dalam stateful=True
, ini adalah contoh yang bagus. Cara terbaik untuk menggunakan ini adalah kasus "banyak ke banyak" berikutnya.
Lapisan:
outputs = LSTM(units=features,
stateful=True,
return_sequences=True, #just to keep a nice output shape even with length 1
input_shape=(None,features))(inputs)
#units = features because we want to use the outputs as inputs
#None because we want variable length
#output_shape -> (batch_size, steps, units)
Sekarang, kita akan memerlukan loop manual untuk prediksi:
input_data = someDataWithShape((batch, 1, features))
#important, we're starting new sequences, not continuing old ones:
model.reset_states()
output_sequence = []
last_step = input_data
for i in steps_to_predict:
new_step = model.predict(last_step)
output_sequence.append(new_step)
last_step = new_step
#end of the sequences
model.reset_states()
Banyak ke banyak dengan stateful = Benar
Sekarang, di sini, kita mendapatkan aplikasi yang sangat bagus: diberi urutan input, cobalah untuk memprediksi langkah-langkah yang tidak diketahui di masa depan.
Kami menggunakan metode yang sama seperti pada "satu ke banyak" di atas, dengan perbedaan bahwa:
- kami akan menggunakan urutan itu sendiri untuk menjadi data target, selangkah lebih maju
- kami tahu bagian dari urutan (jadi kami membuang bagian dari hasil ini).
Layer (sama seperti di atas):
outputs = LSTM(units=features,
stateful=True,
return_sequences=True,
input_shape=(None,features))(inputs)
#units = features because we want to use the outputs as inputs
#None because we want variable length
#output_shape -> (batch_size, steps, units)
Latihan:
Kami akan melatih model kami untuk memprediksi langkah selanjutnya dari urutan:
totalSequences = someSequencesShaped((batch, steps, features))
#batch size is usually 1 in these cases (often you have only one Tank in the example)
X = totalSequences[:,:-1] #the entire known sequence, except the last step
Y = totalSequences[:,1:] #one step ahead of X
#loop for resetting states at the start/end of the sequences:
for epoch in range(epochs):
model.reset_states()
model.train_on_batch(X,Y)
Memprediksi:
Tahap pertama dari prediksi kami melibatkan "membenarkan negara". Itu sebabnya kita akan memprediksi seluruh urutan lagi, bahkan jika kita sudah tahu bagiannya:
model.reset_states() #starting a new sequence
predicted = model.predict(totalSequences)
firstNewStep = predicted[:,-1:] #the last step of the predictions is the first future step
Sekarang kita pergi ke loop seperti pada kasus satu ke banyak. Tapi jangan setel ulang status di sini! . Kami ingin model mengetahui di mana urutan urutannya (dan ia tahu itu pada langkah baru pertama karena prediksi yang baru saja kami buat di atas)
output_sequence = [firstNewStep]
last_step = firstNewStep
for i in steps_to_predict:
new_step = model.predict(last_step)
output_sequence.append(new_step)
last_step = new_step
#end of the sequences
model.reset_states()
Pendekatan ini digunakan dalam jawaban dan file ini:
Mencapai konfigurasi yang kompleks
Dalam semua contoh di atas, saya menunjukkan perilaku "satu lapisan".
Anda dapat, tentu saja, menumpuk banyak lapisan di atas satu sama lain, tidak semua harus mengikuti pola yang sama, dan membuat model Anda sendiri.
Salah satu contoh menarik yang telah muncul adalah "autoencoder" yang memiliki "banyak ke satu encoder" diikuti oleh decoder "satu ke banyak":
Encoder:
inputs = Input((steps,features))
#a few many to many layers:
outputs = LSTM(hidden1,return_sequences=True)(inputs)
outputs = LSTM(hidden2,return_sequences=True)(outputs)
#many to one layer:
outputs = LSTM(hidden3)(outputs)
encoder = Model(inputs,outputs)
Dekoder:
Menggunakan metode "repeat";
inputs = Input((hidden3,))
#repeat to make one to many:
outputs = RepeatVector(steps)(inputs)
#a few many to many layers:
outputs = LSTM(hidden4,return_sequences=True)(outputs)
#last layer
outputs = LSTM(features,return_sequences=True)(outputs)
decoder = Model(inputs,outputs)
Autoencoder:
inputs = Input((steps,features))
outputs = encoder(inputs)
outputs = decoder(outputs)
autoencoder = Model(inputs,outputs)
Berlatih dengan fit(X,X)
Penjelasan tambahan
Jika Anda ingin detail tentang bagaimana langkah-langkah dihitung dalam LSTMs, atau detail tentang stateful=True
kasus - kasus di atas, Anda dapat membaca lebih lanjut dalam jawaban ini: Keraguan mengenai `Memahami Keras LSTMs`