ทำความเข้าใจกับ Keras LSTMs


311

ฉันพยายามที่จะกระทบยอดความเข้าใจของฉันเกี่ยวกับ LSTM และชี้ให้เห็นที่นี่ในโพสต์นี้โดย Christopher Olahนำมาใช้ใน Keras ฉันกำลังติดตามบล็อกที่เขียนโดย Jason Brownleeสำหรับบทช่วยสอนของ Keras สิ่งที่ฉันสับสนเป็นหลักคือ

  1. การปรับแต่งชุดข้อมูลใหม่เข้า[samples, time steps, features]และ
  2. LSTM stateful

ให้ความสนใจกับคำถามสองข้อข้างต้นโดยอ้างอิงจากรหัสที่วางไว้ด้านล่าง:

# reshape into X=t and Y=t+1
look_back = 3
trainX, trainY = create_dataset(train, look_back)
testX, testY = create_dataset(test, look_back)

# reshape input to be [samples, time steps, features]
trainX = numpy.reshape(trainX, (trainX.shape[0], look_back, 1))
testX = numpy.reshape(testX, (testX.shape[0], look_back, 1))
########################
# The IMPORTANT BIT
##########################
# create and fit the LSTM network
batch_size = 1
model = Sequential()
model.add(LSTM(4, batch_input_shape=(batch_size, look_back, 1), stateful=True))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')
for i in range(100):
    model.fit(trainX, trainY, nb_epoch=1, batch_size=batch_size, verbose=2, shuffle=False)
    model.reset_states()

หมายเหตุ: create_dataset รับลำดับความยาว N และส่งกลับN-look_backอาร์เรย์ซึ่งแต่ละองค์ประกอบเป็นlook_backลำดับความยาว

ขั้นตอนเวลาและคุณสมบัติคืออะไร

ดังจะเห็นได้ว่า TrainX เป็นอาร์เรย์สามมิติที่มี Time_steps และฟีเจอร์เป็นสองมิติสุดท้ายตามลำดับ (3 และ 1 ในรหัสเฉพาะนี้) จากภาพด้านล่างนี่หมายความว่าเรากำลังพิจารณาmany to oneกรณีที่จำนวนกล่องสีชมพูเป็น 3 หรือไม่? หรือมันหมายถึงความยาวโซ่คือ 3 (เช่นพิจารณาเพียงแค่กล่องสีเขียว 3 กล่อง)ป้อนคำอธิบายรูปภาพที่นี่

อาร์กิวเมนต์ของคุณสมบัติเกี่ยวข้องกันเมื่อเราพิจารณาซีรี่ส์หลายตัวแปรหรือไม่? เช่นการสร้างแบบจำลองสองหุ้นทางการเงินพร้อมกัน?

LSTM ของรัฐ

LSTM ที่ไม่หยุดทำงานหมายความว่าเราบันทึกค่าหน่วยความจำของเซลล์ระหว่างการทำงานเป็นกลุ่มหรือไม่? หากเป็นกรณีนี้batch_sizeคือหนึ่งและหน่วยความจำจะถูกรีเซ็ตระหว่างการฝึกอบรมทำงานดังนั้นสิ่งที่เป็นจุดที่บอกว่ามันเป็น stateful ฉันเดาว่าสิ่งนี้เกี่ยวข้องกับความจริงที่ว่าข้อมูลการฝึกอบรมไม่ได้ถูกสับ แต่ฉันไม่แน่ใจว่าจะทำอย่างไร

ความคิดใด ๆ การอ้างอิงภาพ: http://karpathy.github.io/2015/05/21/rnn-effectiveness/

แก้ไข 1:

ความสับสนเล็กน้อยเกี่ยวกับความคิดเห็นของ @ van เกี่ยวกับกล่องสีแดงและสีเขียวเท่ากัน ดังนั้นเพื่อยืนยันการเรียก API ต่อไปนี้สอดคล้องกับไดอะแกรมที่ไม่ได้ควบคุม? โดยเฉพาะการสังเกตแผนภาพที่สอง ( batch_sizeถูกเลือกโดยพลการ): ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่

แก้ไข 2:

สำหรับผู้ที่ทำหลักสูตรการเรียนรู้อย่างหนักของ Udacity และยังสับสนเกี่ยวกับอาร์กิวเมนต์ time_step ให้ดูที่การอภิปรายต่อไปนี้: https://discussions.udacity.com/t/rnn-lstm-use-implementation/163169

ปรับปรุง:

ปรากฎmodel.add(TimeDistributed(Dense(vocab_len)))ว่าเป็นสิ่งที่ฉันกำลังมองหา นี่คือตัวอย่าง: https://github.com/sachinruk/ShakespeareBot

Update2:

ฉันได้สรุปความเข้าใจส่วนใหญ่เกี่ยวกับ LSTM ที่นี่: https://www.youtube.com/watch?v=ywinX5wgdEU


7
ภาพถ่ายแรกควรเป็น (batch_size, 5, 1); ภาพถ่ายที่สองควรเป็น (batch_size, 4, 3) (หากไม่มีลำดับดังต่อไปนี้) และทำไมเอาต์พุตยังคงเป็น "X" ควรเป็น "Y" หรือไม่
รถตู้

1
ที่นี่ฉันถือว่า X_1, X_2 ... X_6 เป็นตัวเลขเดียว และสามจำนวน (X_1, X_2, X_3) ทำให้เวกเตอร์ของรูปร่าง (3,) หมายเลขหนึ่ง (X_1) สร้างเวกเตอร์ที่มีรูปร่าง (1,)
Van

2
@ Van, สมมติฐานของคุณถูกต้อง นั่นเป็นเรื่องที่น่าสนใจดังนั้นโดยพื้นฐานแล้วโมเดลไม่ได้เรียนรู้รูปแบบเกินจำนวนเวลา _steps ดังนั้นถ้าฉันมีอนุกรมเวลาความยาว 1,000 และสามารถมองเห็นลวดลายได้ทุก ๆ 100 วันฉันควรสร้างพารามิเตอร์ time_steps อย่างน้อย 100 นี่เป็นการสังเกตที่ถูกต้องหรือไม่?
sachinruk

3
ใช่. และถ้าคุณสามารถรวบรวมฟีเจอร์ที่เกี่ยวข้องได้ 3 รายการต่อวันคุณสามารถกำหนดขนาดฟีเจอร์เป็น 3 ได้เช่นเดียวกับในรูปที่สอง ภายใต้สถานการณ์นั้นรูปร่างอินพุตจะเป็น (batch_size, 100, 3)
รถตู้

1
และเพื่อตอบคำถามแรกของคุณนั่นเป็นเพราะฉันกำลังถ่ายทำซีรีส์ครั้งเดียว ตัวอย่างเช่นราคาหุ้นดังนั้น X และ Y มาจากซีรี่ส์เดียวกัน
sachinruk

คำตอบ:


173

ก่อนอื่นคุณเลือกบทเรียนที่ยอดเยี่ยม ( 1 , 2 ) เพื่อเริ่มต้น

ความหมายของขั้นตอนเวลา : Time-steps==3ใน X.shape (อธิบายรูปร่างของข้อมูล) หมายถึงมีกล่องสีชมพูสามกล่อง เนื่องจากใน Keras แต่ละขั้นตอนต้องการอินพุตดังนั้นจำนวนของกล่องสีเขียวควรจะเท่ากับจำนวนของกล่องสีแดง ถ้าคุณไม่แฮ็คโครงสร้าง

อีกมากมายที่จะเทียบกับหลายอย่างใดอย่างหนึ่ง : ใน keras มีreturn_sequencesพารามิเตอร์เมื่อ Initializing ของคุณLSTMหรือหรือGRU SimpleRNNเมื่อreturn_sequencesใดที่False(ตามค่าเริ่มต้น) จะมีหลายค่าตามที่แสดงในภาพ รูปร่างที่ส่งคืนคือ(batch_size, hidden_unit_length)ซึ่งแสดงถึงสถานะสุดท้าย เมื่อreturn_sequencesเป็นTrueเช่นนั้นมันเป็นจำนวนมากหลายครั้ง รูปร่างกลับมาของมันคือ(batch_size, time_step, hidden_unit_length)

อาร์กิวเมนต์ของคุณสมบัติเกี่ยวข้องหรือไม่ : อาร์กิวเมนต์ของคุณสมบัติหมายถึง"กล่องสีแดงของคุณมีขนาดใหญ่แค่ไหน"หรือมิติข้อมูลเข้าแต่ละขั้นตอนคืออะไร หากคุณต้องการทำนายจากข้อมูลตลาด 8 ชนิดจากนั้นคุณสามารถสร้างข้อมูลของคุณfeature==8ได้

Stateful : คุณสามารถค้นหาซอร์สโค้ดได้ เมื่อเริ่มต้นสถานะถ้าสถานะstateful==Trueนั้นจากการฝึกครั้งสุดท้ายจะถูกใช้เป็นสถานะเริ่มต้นมิฉะนั้นจะสร้างสถานะใหม่ ฉันยังไม่เปิดstatefulเครื่อง แต่ผมไม่เห็นด้วยกับที่batch_sizeสามารถเป็น 1 stateful==Trueเมื่อ

ขณะนี้คุณสร้างข้อมูลด้วยข้อมูลที่รวบรวม ภาพข้อมูลสต็อคของคุณกำลังมาเป็นสตรีมแทนที่จะรอให้วันรวบรวมลำดับทั้งหมดคุณต้องการสร้างข้อมูลอินพุตออนไลน์ขณะฝึกอบรม / คาดการณ์กับเครือข่าย หากคุณมี 400 หุ้นที่แชร์เครือข่ายเดียวกันคุณสามารถตั้งค่าbatch_size==400ได้


สับสนเล็กน้อยเกี่ยวกับสาเหตุที่กล่องสีแดงและสีเขียวต้องเหมือนกัน คุณช่วยดูการแก้ไขที่ฉันทำ (ภาพใหม่เป็นหลัก) และแสดงความคิดเห็นได้หรือไม่?
sachinruk

1
จริง ตรวจสอบเอกสาร:stateful: Boolean (default False). If True, the last state for each sample at index i in a batch will be used as initial state for the sample of index i in the following batch.
Van

1
@Van หากฉันมีอนุกรมเวลาหลายตัวแปรฉันยังควรใช้lookback = 1หรือไม่
innm

1
ทำไมขนาด LSTM ของพื้นที่ส่งออก (32) จึงแตกต่างจากจำนวนของเซลล์ประสาท (เซลล์ LSTM)
เหนียว

1
นอกจากนี้stateful=True: ขนาดชุดสามารถเป็นอะไรก็ได้ที่คุณชอบ แต่คุณต้องติดกับมัน ถ้าคุณสร้างแบบจำลองของคุณด้วยชุดขนาด 5 แล้วทั้งหมดfit(), predict()และวิธีการที่เกี่ยวข้องจะต้องมีชุดของ 5. หมายเหตุ แต่ที่รัฐนี้จะไม่ถูกบันทึกด้วยmodel.save()ซึ่งอาจจะดูเหมือนไม่พึงประสงค์ อย่างไรก็ตามคุณสามารถเพิ่มสถานะลงในไฟล์ hdf5 ได้ด้วยตนเองหากคุณต้องการ แต่สิ่งนี้มีประสิทธิภาพช่วยให้คุณสามารถเปลี่ยนขนาดแบทช์เพียงแค่บันทึกและโหลดโมเดลใหม่
jlh

191

ในฐานะที่เป็นส่วนเติมเต็มให้กับคำตอบที่ได้รับการยอมรับคำตอบนี้จะแสดงพฤติกรรมของ keras และวิธีการบรรลุแต่ละภาพ

พฤติกรรมทั่วไปของ Keras

การประมวลผลภายใน keras มาตรฐานมักจะมากตามที่แสดงในรูปภาพต่อไปนี้ (ที่ฉันใช้features=2ความดันและอุณหภูมิเหมือนตัวอย่าง):

ManyToMany

ในภาพนี้ฉันเพิ่มจำนวนขั้นตอนเป็น 5 เพื่อหลีกเลี่ยงความสับสนกับส่วนข้อมูลอื่น

สำหรับตัวอย่างนี้:

  • เรามีถังน้ำมัน N แห่ง
  • เราใช้เวลา 5 ชั่วโมงในการวัดรายชั่วโมง (ขั้นตอนเวลา)
  • เราวัดคุณสมบัติสองประการ:
    • ความดัน P
    • อุณหภูมิต

อาเรย์อินพุตของเรานั้นควรเป็นรูปทรง(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]],
  ....
        ]

โปรดสังเกตว่าในกรณีนี้คุณมีเพียงหนึ่งลำดับเริ่มต้นเท่านั้น แต่คุณแบ่งมันเป็นหลายลำดับเพื่อสร้างหน้าต่าง

แนวคิดของ "ลำดับคืออะไร" เป็นนามธรรม ส่วนที่สำคัญคือ:

  • คุณสามารถมีแบทช์ที่มีลำดับของแต่ละบุคคลจำนวนมาก
  • สิ่งที่ทำให้ลำดับเป็นลำดับคือพวกมันมีวิวัฒนาการเป็นขั้นตอน

บรรลุแต่ละกรณีด้วย "ชั้นเดียว"

บรรลุมาตรฐานหลายต่อหลายคน:

StandardManyToMany

คุณสามารถประสบความสำเร็จได้มากมายด้วยเลเยอร์ LSTM แบบง่าย ๆ โดยใช้return_sequences=True:

outputs = LSTM(units, return_sequences=True)(inputs)

#output_shape -> (batch_size, steps, units)

ประสบความสำเร็จหลายต่อหลาย:

การใช้เลเยอร์เดียวกันที่แน่นอน keras จะทำการประมวลผลล่วงหน้าภายในที่แน่นอน แต่เมื่อคุณใช้return_sequences=False(หรือไม่สนใจอาร์กิวเมนต์นี้) keras จะละทิ้งขั้นตอนก่อนหน้านี้โดยอัตโนมัติ:

ManyToOne

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 เราต้องการอินพุตเป็นขั้นตอนดังนั้นเราเพียงแค่ป้อนข้อมูลซ้ำตามความยาวที่เราต้องการ:

OneToManyRepeat

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คือสิ่งที่ "อนุญาต" ให้เราหยุดลำดับจัดการสิ่งที่เราต้องการและดำเนินการต่อจากที่ที่เราหยุด

OneToManyStateful

สุจริตวิธีการทำซ้ำอาจเป็นตัวเลือกที่ดีกว่าสำหรับกรณีนี้ แต่เนื่องจากเรากำลังตรวจสอบอยู่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

ตอนนี้ที่นี่เราได้รับแอปพลิเคชั่นที่ดีมาก: กำหนดลำดับการป้อนข้อมูลพยายามทำนายขั้นตอนที่ไม่ทราบอนาคต

เราใช้วิธีการเดียวกับใน "หนึ่งถึงมาก" ข้างต้นด้วยความแตกต่างที่:

  • เราจะใช้ลำดับตัวเองเป็นข้อมูลเป้าหมายหนึ่งขั้นล่วงหน้า
  • เรารู้ส่วนหนึ่งของลำดับ (ดังนั้นเราจึงยกเลิกส่วนนี้ของผลลัพธ์)

ManyToManyStateful

เลเยอร์ (เหมือนด้านบน):

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กรณีข้างต้นคุณสามารถอ่านเพิ่มเติมได้ในคำตอบนี้: ข้อสงสัยเกี่ยวกับ


1
การใช้ stateful ที่น่าสนใจมากกับการใช้เอาต์พุตเป็นอินพุต วิธีอื่นในการทำเช่นนี้คือการใช้ฟังก์ชัน Keras API (เหมือนที่คุณทำที่นี่ถึงแม้ว่าฉันเชื่อว่าคุณสามารถใช้ลำดับต่อมาได้) และใช้เซลล์ LSTM เดียวกันทุกครั้ง ในขณะที่ผ่านทั้งสถานะผลลัพธ์และผลลัพธ์จากเซลล์ไปยังตัวเอง คือmy_cell = LSTM(num_output_features_per_timestep, return_state=True)ตามด้วยลูปของa, _, c = my_cell(output_of_previous_time_step, initial_states=[a, c])
Jacob R

1
เซลล์และความยาวเป็นค่าที่เป็นอิสระอย่างสมบูรณ์ ไม่มีภาพใดแสดงถึงจำนวน "เซลล์" พวกเขาทั้งหมดสำหรับ "ความยาว"
Daniel Möller

1
@ DanielMöllerฉันรู้ว่าสายไปหน่อย แต่คำตอบของคุณดึงดูดความสนใจของฉันจริงๆ จุดหนึ่งของคุณแตกสลายทุกอย่างเกี่ยวกับความเข้าใจของฉันในสิ่งที่ชุดสำหรับ LSTM คือ คุณให้ตัวอย่างด้วยรถถัง N ห้าขั้นตอนและคุณสมบัติสองอย่าง ฉันเชื่อว่าถ้าแบตช์เป็นตัวอย่างที่สองนั่นหมายความว่าตัวอย่างสองตัวอย่าง (รถถังที่มีคุณสมบัติ 5 ขั้นตอน 2) จะถูกป้อนเข้าสู่เครือข่ายและหลังจากนั้นจะมีการปรับน้ำหนัก แต่ถ้าฉันเข้าใจถูกต้องคุณระบุว่าชุดที่ 2 หมายความว่าการจับเวลาของตัวอย่างจะถูกแบ่งออกเป็น 2 และครึ่งแรกของตัวอย่างทั้งหมดจะถูกป้อนเข้าสู่ LSTM-> การปรับปรุงน้ำหนักและมากกว่าวินาที
viceriel

1
ใช่. บน stateful = True แบตช์ 1 = กลุ่มตัวอย่างอัปเดต จากนั้น batch 2 = ขั้นตอนเพิ่มเติมสำหรับกลุ่มตัวอย่างเดียวกันให้อัปเดต
Daniel Möller

2
ฉันหวังว่าฉันจะสามารถลงคะแนน 100 ครั้งนี้ คำตอบที่มีประโยชน์สุด ๆ
adamconkey

4

เมื่อคุณมี return_sequences ในเลเยอร์สุดท้ายของ RNN คุณจะไม่สามารถใช้เลเยอร์หนาแน่นแบบธรรมดาแทนการใช้ TimeDistributed

นี่คือตัวอย่างรหัสซึ่งอาจช่วยผู้อื่นได้

word = keras.layers.Input (batch_shape = (ไม่มี, self.maxSequenceLength), ชื่อ = "อินพุต")

    # Build a matrix of size vocabularySize x EmbeddingDimension 
    # where each row corresponds to a "word embedding" vector.
    # This layer will convert replace each word-id with a word-vector of size Embedding Dimension.
    embeddings = keras.layers.embeddings.Embedding(self.vocabularySize, self.EmbeddingDimension,
        name = "embeddings")(words)
    # Pass the word-vectors to the LSTM layer.
    # We are setting the hidden-state size to 512.
    # The output will be batchSize x maxSequenceLength x hiddenStateSize
    hiddenStates = keras.layers.GRU(512, return_sequences = True, 
                                        input_shape=(self.maxSequenceLength,
                                        self.EmbeddingDimension),
                                        name = "rnn")(embeddings)
    hiddenStates2 = keras.layers.GRU(128, return_sequences = True, 
                                        input_shape=(self.maxSequenceLength, self.EmbeddingDimension),
                                        name = "rnn2")(hiddenStates)

    denseOutput = TimeDistributed(keras.layers.Dense(self.vocabularySize), 
        name = "linear")(hiddenStates2)
    predictions = TimeDistributed(keras.layers.Activation("softmax"), 
        name = "softmax")(denseOutput)  

    # Build the computational graph by specifying the input, and output of the network.
    model = keras.models.Model(input = words, output = predictions)
    # model.compile(loss='kullback_leibler_divergence', \
    model.compile(loss='sparse_categorical_crossentropy', \
        optimizer = keras.optimizers.Adam(lr=0.009, \
            beta_1=0.9,\
            beta_2=0.999, \
            epsilon=None, \
            decay=0.01, \
            amsgrad=False))
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.