ในฐานะที่เป็นส่วนเติมเต็มให้กับคำตอบที่ได้รับการยอมรับคำตอบนี้จะแสดงพฤติกรรมของ keras และวิธีการบรรลุแต่ละภาพ
พฤติกรรมทั่วไปของ Keras
การประมวลผลภายใน keras มาตรฐานมักจะมากตามที่แสดงในรูปภาพต่อไปนี้ (ที่ฉันใช้features=2
ความดันและอุณหภูมิเหมือนตัวอย่าง):
ในภาพนี้ฉันเพิ่มจำนวนขั้นตอนเป็น 5 เพื่อหลีกเลี่ยงความสับสนกับส่วนข้อมูลอื่น
สำหรับตัวอย่างนี้:
- เรามีถังน้ำมัน N แห่ง
- เราใช้เวลา 5 ชั่วโมงในการวัดรายชั่วโมง (ขั้นตอนเวลา)
- เราวัดคุณสมบัติสองประการ:
อาเรย์อินพุตของเรานั้นควรเป็นรูปทรง(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]],
]
อินพุตสำหรับหน้าต่างบานเลื่อน
บ่อยครั้งที่เลเยอร์ LSTM ควรประมวลผลลำดับทั้งหมด การแบ่งหน้าต่างอาจไม่ใช่ความคิดที่ดีที่สุด เลเยอร์มีสถานะภายในเกี่ยวกับการพัฒนาของลำดับขณะที่เดินไปข้างหน้า Windows กำจัดความเป็นไปได้ในการเรียนรู้ลำดับที่ยาวนานโดย จำกัด ลำดับทั้งหมดไว้ที่ขนาดหน้าต่าง
ใน windows แต่ละหน้าต่างเป็นส่วนหนึ่งของลำดับดั้งเดิมที่มีความยาว แต่โดย Keras พวกเขาจะถูกมองว่าเป็นลำดับอิสระ:
[ 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]],
....
]
โปรดสังเกตว่าในกรณีนี้คุณมีเพียงหนึ่งลำดับเริ่มต้นเท่านั้น แต่คุณแบ่งมันเป็นหลายลำดับเพื่อสร้างหน้าต่าง
แนวคิดของ "ลำดับคืออะไร" เป็นนามธรรม ส่วนที่สำคัญคือ:
- คุณสามารถมีแบทช์ที่มีลำดับของแต่ละบุคคลจำนวนมาก
- สิ่งที่ทำให้ลำดับเป็นลำดับคือพวกมันมีวิวัฒนาการเป็นขั้นตอน
บรรลุแต่ละกรณีด้วย "ชั้นเดียว"
บรรลุมาตรฐานหลายต่อหลายคน:
คุณสามารถประสบความสำเร็จได้มากมายด้วยเลเยอร์ LSTM แบบง่าย ๆ โดยใช้return_sequences=True
:
outputs = LSTM(units, return_sequences=True)(inputs)
#output_shape -> (batch_size, steps, units)
ประสบความสำเร็จหลายต่อหลาย:
การใช้เลเยอร์เดียวกันที่แน่นอน keras จะทำการประมวลผลล่วงหน้าภายในที่แน่นอน แต่เมื่อคุณใช้return_sequences=False
(หรือไม่สนใจอาร์กิวเมนต์นี้) keras จะละทิ้งขั้นตอนก่อนหน้านี้โดยอัตโนมัติ:
outputs = LSTM(units)(inputs)
#output_shape -> (batch_size, units) --> steps were discarded, only the last was returned
ประสบความสำเร็จแบบหนึ่งต่อหลายคน
ตอนนี้ไม่รองรับเลเยอร์ keras LSTM เพียงอย่างเดียว คุณจะต้องสร้างกลยุทธ์ของคุณเองเพื่อคูณขั้นตอน มีสองวิธีที่ดี:
- สร้างอินพุตแบบหลายขั้นตอนอย่างต่อเนื่องโดยการทำซ้ำเมตริกซ์
- ใช้ a
stateful=True
เพื่อรับเอาต์พุตในขั้นตอนเดียวซ้ำอีกครั้งและทำหน้าที่เป็นอินพุตของขั้นตอนถัดไป (ต้องการoutput_features == input_features
)
หนึ่งต่อหลายกับเวกเตอร์ซ้ำ
เพื่อให้เหมาะสมกับพฤติกรรมมาตรฐานของ keras เราต้องการอินพุตเป็นขั้นตอนดังนั้นเราเพียงแค่ป้อนข้อมูลซ้ำตามความยาวที่เราต้องการ:
outputs = RepeatVector(steps)(inputs) #where inputs is (batch,features)
outputs = LSTM(units,return_sequences=True)(outputs)
#output_shape -> (batch_size, steps, units)
การทำความเข้าใจสถานะ = True
ตอนนี้หนึ่งในประเพณีที่เป็นไปได้มา stateful=True
(นอกเหนือจากการหลีกเลี่ยงการโหลดข้อมูลที่ไม่เหมาะสมกับหน่วยความจำของคอมพิวเตอร์ของคุณพร้อมกัน)
Stateful ช่วยให้เราสามารถป้อน "ส่วน" ของลำดับในขั้นตอน ความแตกต่างคือ:
- ใน
stateful=False
ชุดที่สองประกอบด้วยลำดับใหม่ทั้งหมดเป็นอิสระจากชุดแรก
- ใน
stateful=True
ชุดที่สองยังคงเป็นชุดแรกขยายลำดับเดียวกัน
มันก็เหมือนกับการแบ่งลำดับใน windows ด้วยความแตกต่างหลักสองอย่างนี้:
- หน้าต่างเหล่านี้ไม่ทับซ้อน !!
stateful=True
จะเห็นหน้าต่างเหล่านี้เชื่อมต่อกันเป็นลำดับยาว ๆ เดียว
ในstateful=True
ทุกชุดใหม่จะถูกตีความว่าเป็นการดำเนินการต่อชุดก่อนหน้า (จนกว่าคุณจะเรียกmodel.reset_states()
)
- ลำดับที่ 1 ในชุดที่ 2 จะดำเนินการตามลำดับที่ 1 ในชุดที่ 1
- ลำดับที่ 2 ในชุดที่ 2 จะดำเนินการตามลำดับที่ 2 ในชุดที่ 1
- ลำดับ n ในชุดที่ 2 จะดำเนินการตามลำดับ n ในชุดที่ 1
ตัวอย่างอินพุต, แบทช์ 1 ประกอบด้วยขั้นตอนที่ 1 และ 2, แบทช์ 2 มีขั้นตอนที่ 3 ถึง 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]],
] ]
สังเกตการวางแนวของรถถังในชุดที่ 1 และชุดที่ 2! นั่นเป็นเหตุผลที่เราต้องการshuffle=False
(เว้นแต่เราจะใช้ลำดับเดียวเท่านั้นแน่นอน)
คุณสามารถมีแบทช์ได้ไม่ จำกัด จำนวน input_shape=(None,features)
(สำหรับการมีความยาวของตัวแปรในแต่ละชุดใช้
หนึ่งต่อหลายคนที่มี stateful = True
สำหรับกรณีของเราที่นี่เราจะใช้เพียง 1 ขั้นตอนต่อชุดเพราะเราต้องการได้หนึ่งขั้นตอนการส่งออกและทำให้มันเป็นอินพุต
กรุณาแจ้งให้ทราบว่าพฤติกรรมในภาพไม่ได้ stateful=True
"ที่เกิดจาก" เราจะบังคับพฤติกรรมนั้นในลูปด้วยตนเองด้านล่าง ในตัวอย่างนี้stateful=True
คือสิ่งที่ "อนุญาต" ให้เราหยุดลำดับจัดการสิ่งที่เราต้องการและดำเนินการต่อจากที่ที่เราหยุด
สุจริตวิธีการทำซ้ำอาจเป็นตัวเลือกที่ดีกว่าสำหรับกรณีนี้ แต่เนื่องจากเรากำลังตรวจสอบอยู่stateful=True
นี่เป็นตัวอย่างที่ดี วิธีที่ดีที่สุดในการใช้นี่คือเคส "หลายต่อหลาย" ถัดไป
ชั้น:
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)
ตอนนี้เราจะต้องวนซ้ำแบบแมนนวลสำหรับการคาดการณ์:
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()
หลายต่อหลายคนมี stateful = True
ตอนนี้ที่นี่เราได้รับแอปพลิเคชั่นที่ดีมาก: กำหนดลำดับการป้อนข้อมูลพยายามทำนายขั้นตอนที่ไม่ทราบอนาคต
เราใช้วิธีการเดียวกับใน "หนึ่งถึงมาก" ข้างต้นด้วยความแตกต่างที่:
- เราจะใช้ลำดับตัวเองเป็นข้อมูลเป้าหมายหนึ่งขั้นล่วงหน้า
- เรารู้ส่วนหนึ่งของลำดับ (ดังนั้นเราจึงยกเลิกส่วนนี้ของผลลัพธ์)
เลเยอร์ (เหมือนด้านบน):
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)
การฝึกอบรม:
เราจะฝึกโมเดลของเราเพื่อทำนายลำดับขั้นตอนต่อไป:
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)
ทำนาย:
ขั้นตอนแรกของการทำนายของเราเกี่ยวข้องกับ "การปรับสภาพรัฐ" นั่นเป็นเหตุผลที่เราจะทำนายลำดับทั้งหมดอีกครั้งแม้ว่าเราจะรู้แล้วในส่วนนี้:
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
ตอนนี้เราไปที่วงเดียวในหลายกรณี แต่อย่ารีเซ็ตสถานะที่นี่! . เราต้องการให้แบบจำลองรู้ว่าขั้นตอนใดเป็นลำดับ (และรู้ว่ามันเป็นขั้นตอนใหม่ครั้งแรกเนื่องจากการคาดการณ์ที่เราทำไว้ด้านบน)
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()
วิธีการนี้ใช้ในคำตอบและไฟล์เหล่านี้:
บรรลุการกำหนดค่าที่ซับซ้อน
ในตัวอย่างด้านบนทั้งหมดฉันแสดงพฤติกรรมของ "หนึ่งเลเยอร์"
แน่นอนคุณสามารถสแต็คเลเยอร์จำนวนมากซ้อนทับกันไม่จำเป็นต้องทำตามรูปแบบเดียวกันและสร้างโมเดลของคุณเอง
ตัวอย่างที่น่าสนใจหนึ่งที่ปรากฏขึ้นคือ "autoencoder" ที่มี "ตัวเข้ารหัสหลายตัว" ตามด้วยตัวถอดรหัส "หนึ่งต่อหลาย":
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)
ถอดรหัส:
ใช้วิธีการ "ทำซ้ำ";
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)
ฝึกด้วย fit(X,X)
คำอธิบายเพิ่มเติม
หากคุณต้องการรายละเอียดเกี่ยวกับวิธีคำนวณขั้นตอนเป็น LSTM หรือรายละเอียดเกี่ยวกับstateful=True
กรณีข้างต้นคุณสามารถอ่านเพิ่มเติมได้ในคำตอบนี้: ข้อสงสัยเกี่ยวกับ