Để bổ sung cho câu trả lời được chấp nhận, câu trả lời này cho thấy các hành vi của máy ảnh và cách đạt được từng hình ảnh.
Hành vi chung của Keras
Quá trình xử lý nội bộ của máy ảnh tiêu chuẩn luôn có nhiều đến nhiều như trong hình sau (nơi tôi đã sử dụng features=2
, áp suất và nhiệt độ, như một ví dụ):
Trong hình ảnh này, tôi đã tăng số bước lên 5, để tránh nhầm lẫn với các kích thước khác.
Ví dụ này:
- Chúng tôi có N thùng dầu
- Chúng tôi đã dành 5 giờ để thực hiện các biện pháp hàng giờ (các bước thời gian)
- Chúng tôi đã đo hai tính năng:
Mảng đầu vào của chúng ta nên có hình dạng như (N,5,2)
sau:
[ 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]],
]
Đầu vào cho cửa sổ trượt
Thông thường, các lớp LSTM được cho là xử lý toàn bộ chuỗi. Cửa sổ phân chia có thể không phải là ý tưởng tốt nhất. Lớp này có các trạng thái bên trong về cách một chuỗi đang phát triển khi nó bước về phía trước. Windows loại bỏ khả năng học các chuỗi dài, giới hạn tất cả các chuỗi theo kích thước cửa sổ.
Trong các cửa sổ, mỗi cửa sổ là một phần của chuỗi gốc dài, nhưng bởi Keras, chúng sẽ được xem mỗi chuỗi là một chuỗi độc lập:
[ 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]],
....
]
Lưu ý rằng trong trường hợp này, ban đầu bạn chỉ có một chuỗi, nhưng bạn chia nó thành nhiều chuỗi để tạo các cửa sổ.
Khái niệm "chuỗi là gì" là trừu tượng. Các phần quan trọng là:
- bạn có thể có các đợt với nhiều chuỗi riêng lẻ
- Điều làm cho các chuỗi là các chuỗi là chúng phát triển theo các bước (thường là các bước thời gian)
Đạt được từng trường hợp với "lớp đơn"
Đạt tiêu chuẩn nhiều đến nhiều:
Bạn có thể đạt được nhiều đến nhiều với một lớp LSTM đơn giản, sử dụng return_sequences=True
:
outputs = LSTM(units, return_sequences=True)(inputs)
#output_shape -> (batch_size, steps, units)
Đạt được nhiều thành một:
Sử dụng cùng một lớp chính xác, các máy ảnh sẽ thực hiện chính xác quá trình tiền xử lý nội bộ, nhưng khi bạn sử dụng return_sequences=False
(hoặc đơn giản bỏ qua đối số này), máy ảnh sẽ tự động loại bỏ các bước trước đó đến cuối cùng:
outputs = LSTM(units)(inputs)
#output_shape -> (batch_size, units) --> steps were discarded, only the last was returned
Đạt được một đến nhiều
Bây giờ, điều này không được hỗ trợ bởi các lớp LSTM của máy ảnh. Bạn sẽ phải tạo chiến lược của riêng mình để nhân các bước. Có hai cách tiếp cận tốt:
- Tạo đầu vào nhiều bước không đổi bằng cách lặp lại một tenxơ
- Sử dụng a
stateful=True
để thường xuyên lấy đầu ra của một bước và phục vụ nó làm đầu vào của bước tiếp theo (nhu cầu output_features == input_features
)
Một đến nhiều với vector lặp lại
Để phù hợp với hành vi tiêu chuẩn của máy ảnh, chúng tôi cần các đầu vào theo các bước, vì vậy, chúng tôi chỉ cần lặp lại các đầu vào cho độ dài mà chúng tôi muốn:
outputs = RepeatVector(steps)(inputs) #where inputs is (batch,features)
outputs = LSTM(units,return_sequences=True)(outputs)
#output_shape -> (batch_size, steps, units)
Hiểu trạng thái = Đúng
Bây giờ đến một trong những cách sử dụng có thể stateful=True
(bên cạnh việc tránh tải dữ liệu không thể vừa với bộ nhớ máy tính của bạn)
Stateful cho phép chúng ta nhập "các phần" của chuỗi trong các giai đoạn. Sự khác biệt là:
- Trong
stateful=False
, lô thứ hai chứa toàn bộ chuỗi mới, độc lập với lô đầu tiên
- Trong
stateful=True
, đợt thứ hai tiếp tục đợt đầu tiên, mở rộng các chuỗi tương tự.
Nó cũng giống như phân chia các chuỗi trong các cửa sổ, với hai điểm khác biệt chính sau:
- những cửa sổ này không chồng chất !!
stateful=True
sẽ thấy các cửa sổ này được kết nối dưới dạng một chuỗi dài
Trong stateful=True
, mỗi đợt mới sẽ được hiểu là tiếp tục đợt trước (cho đến khi bạn gọi model.reset_states()
).
- Trình tự 1 trong lô 2 sẽ tiếp tục trình tự 1 trong lô 1.
- Trình tự 2 trong lô 2 sẽ tiếp tục trình tự 2 trong lô 1.
- Trình tự n trong lô 2 sẽ tiếp tục chuỗi n trong lô 1.
Ví dụ về đầu vào, lô 1 chứa các bước 1 và 2, lô 2 chứa các bước từ 3 đến 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]],
] ]
Chú ý sự liên kết của các xe tăng trong đợt 1 và đợt 2! Đó là lý do tại sao chúng ta cần shuffle=False
(tất nhiên trừ khi chúng ta chỉ sử dụng một chuỗi).
Bạn có thể có bất kỳ số lượng lô, vô thời hạn. (Để có độ dài thay đổi trong mỗi lô, hãy sử dụng input_shape=(None,features)
.
Một đến nhiều với trạng thái = True
Đối với trường hợp của chúng tôi ở đây, chúng tôi sẽ chỉ sử dụng 1 bước cho mỗi đợt, vì chúng tôi muốn có một bước đầu ra và biến nó thành đầu vào.
Xin lưu ý rằng hành vi trong ảnh không phải là "gây ra bởi" stateful=True
. Chúng tôi sẽ buộc hành vi đó trong một vòng lặp thủ công dưới đây. Trong ví dụ này, stateful=True
là những gì "cho phép" chúng ta dừng chuỗi, thao túng những gì chúng ta muốn và tiếp tục từ nơi chúng ta dừng lại.
Thành thật mà nói, cách tiếp cận lặp lại có lẽ là một lựa chọn tốt hơn cho trường hợp này. Nhưng vì chúng tôi đang xem xét stateful=True
, đây là một ví dụ tốt. Cách tốt nhất để sử dụng điều này là trường hợp "nhiều đến nhiều" tiếp theo.
Lớp:
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)
Bây giờ, chúng ta sẽ cần một vòng lặp thủ công để dự đoán:
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()
Nhiều đến nhiều với trạng thái = Đúng
Bây giờ, ở đây, chúng tôi nhận được một ứng dụng rất hay: đưa ra một chuỗi đầu vào, cố gắng dự đoán các bước chưa biết trong tương lai của nó.
Chúng tôi đang sử dụng cùng một phương pháp như trong "một đến nhiều" ở trên, với sự khác biệt là:
- chúng tôi sẽ sử dụng chính chuỗi đó là dữ liệu đích, đi trước một bước
- chúng tôi biết một phần của chuỗi (vì vậy chúng tôi loại bỏ phần kết quả này).
Lớp (giống như trên):
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)
Đào tạo:
Chúng tôi sẽ đào tạo mô hình của chúng tôi để dự đoán bước tiếp theo của chuỗi:
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)
Dự đoán:
Giai đoạn đầu tiên của dự đoán của chúng tôi liên quan đến "điều chỉnh các quốc gia". Đó là lý do tại sao chúng ta sẽ dự đoán lại toàn bộ chuỗi, ngay cả khi chúng ta đã biết phần này của nó:
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
Bây giờ chúng ta đi đến vòng lặp như trong một đến nhiều trường hợp. Nhưng đừng thiết lập lại trạng thái ở đây! . Chúng tôi muốn mô hình biết bước nào của chuỗi đó (và nó biết nó ở bước mới đầu tiên vì dự đoán chúng tôi vừa thực hiện ở trên)
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()
Cách tiếp cận này đã được sử dụng trong các câu trả lời và tập tin này:
Đạt được cấu hình phức tạp
Trong tất cả các ví dụ trên, tôi đã chỉ ra hành vi của "một lớp".
Tất nhiên, bạn có thể xếp chồng nhiều lớp lên nhau, không nhất thiết phải theo cùng một mẫu và tạo các mô hình của riêng bạn.
Một ví dụ thú vị đã xuất hiện là "bộ mã hóa tự động" có "bộ mã hóa nhiều thành một", theo sau là bộ giải mã "một đến nhiều":
Mã hoá:
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)
Bộ giải mã:
Sử dụng phương pháp "lặp lại";
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)
Bộ giải mã tự động:
inputs = Input((steps,features))
outputs = encoder(inputs)
outputs = decoder(outputs)
autoencoder = Model(inputs,outputs)
Đào tạo với fit(X,X)
Giải thích thêm
Nếu bạn muốn biết chi tiết về cách các bước được tính trong LSTM hoặc chi tiết về các stateful=True
trường hợp ở trên, bạn có thể đọc thêm trong câu trả lời này: Nghi ngờ về `Hiểu về máy ảnh LSTMs`