Pengertian Keras LSTMs

Saya mencoba untuk mendamaikan saya mengerti dari LSTMs dan menunjukkan di sini posting ini oleh Christopher Olah yang dilaksanakan di Keras. Saya mengikuti blog yang ditulis oleh Jason Brownlee untuk tutorial Keras. Apa yang saya bingung terutama tentang ini,

  1. Membentuk kembali data seri ke [sampel, waktu, langkah, fitur] dan,
  2. Yang stateful LSTMs

Mari kita berkonsentrasi pada hal di atas dua pertanyaan dengan mengacu pada kode yang disisipkan di bawah ini:

# 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()

Catatan: create_dataset mengambil urutan panjang N dan kembali N-look_back array yang setiap elemennya adalah look_back urutan panjang.

Apa Langkah Waktu dan Fitur?

Seperti dapat dilihat TrainX adalah sebuah 3-D array dengan Time_steps dan Fitur yang terakhir dua dimensi masing-masing (3 dan 1 dalam kode tertentu). Sehubungan dengan gambar di bawah ini, apakah ini berarti bahwa kita sedang mempertimbangkan `banyak ke satu kasus, di mana jumlah pink kotak adalah 3? Atau apakah itu benar-benar berarti rantai panjang adalah 3 (yaitu hanya 3 kotak hijau dianggap).

Tidak memiliki argumen menjadi relevan ketika kita mempertimbangkan multivariat seri? misalnya pemodelan dua saham keuangan secara bersamaan?

Stateful LSTMs

Tidak stateful LSTMs berarti bahwa kita menyimpan memori dan nilai-nilai antara berjalan dari batch? Jika hal ini terjadi, batch_size adalah satu, dan memori reset antara pelatihan berjalan begitu apa gunanya mengatakan bahwa itu adalah stateful. I'm menduga hal ini terkait dengan fakta bahwa pelatihan data tidak dikocok, tetapi saya'm tidak yakin bagaimana.

Setiap pikiran? Referensi gambar: http://karpathy.github.io/2015/05/21/rnn-effectiveness/

Edit 1:

Sedikit bingung tentang @van's komentar tentang kotak merah dan hijau yang sama. Jadi hanya untuk mengkonfirmasi, apakah mengikuti panggilan API sesuai untuk membuka gulungan diagram? Terutama mencatat kedua diagram (batch_size sewenang-wenang dipilih.):

Edit 2:

Bagi orang-orang yang telah melakukan Udacity's deep learning dan masih bingung tentang time_step argumen, lihat pembahasan berikut: https://discussions.udacity.com/t/rnn-lstm-use-implementation/163169

Update:

Ternyata model.tambahkan(TimeDistributed(Padat(vocab_len))) adalah apa yang saya cari. Berikut ini sebuah contoh: https://github.com/sachinruk/ShakespeareBot

Update2:

Saya telah diringkas kebanyakan dari pemahaman saya tentang LSTMs berikut: https://www.youtube.com/watch?v=ywinX5wgdEU

Mengomentari pertanyaan (9)
Larutan

Pertama-tama, anda memilih tutorial yang besar(1,2) untuk memulai.

Apa Waktu-langkah berarti: Time-langkah==3 di X. bentuk (Menggambarkan data bentuk) berarti ada tiga pink kotak-kotak. Sejak Keras di setiap langkah membutuhkan masukan, oleh karena itu jumlah kotak hijau biasanya harus sama dengan jumlah kotak merah. Kecuali anda hack struktur.

many to many vs. banyak ke satu: Di keras, ada return_sequences parameter ketika anda inisialisasi LSTM atau GRU atau SimpleRNN. Ketika return_sequences adalah Palsu (by default), maka itu adalah banyak ke satu seperti yang ditunjukkan dalam gambar. Kembali bentuk (batch_size, hidden_unit_length), yang mewakili negara terakhir. Ketika return_sequences adalah Benar, maka itu adalah banyak ke banyak. Kembali bentuk (batch_size, time_step, hidden_unit_length)

Tidak memiliki argumen menjadi relevan: Fitur argumen berarti "Seberapa besar anda kotak merah" atau apa input dimensi masing-masing langkah. Jika anda ingin memprediksi dari, katakanlah, 8 jenis informasi pasar, maka anda dapat menghasilkan data anda dengan fitur ==8.

Stateful: Anda dapat mencari source code. Ketika inisialisasi negara, jika stateful==True, maka negara dari pelatihan terakhir akan digunakan sebagai keadaan awal, jika tidak maka akan menghasilkan keadaan baru. Aku ingin't turn on stateful belum. Namun, saya tidak setuju dengan bahwa batch_size hanya dapat 1 ketika stateful==True.

Saat ini, anda menghasilkan data anda dengan data yang dikumpulkan. Gambar informasi saham anda akan datang seperti sungai, daripada menunggu untuk hari untuk mengumpulkan semua berurutan, anda ingin menghasilkan input data secara online **** sementara pelatihan/memprediksi dengan jaringan. Jika anda memiliki 400 saham berbagi jaringan yang sama, maka anda dapat mengatur batch_size==400.

Komentar (10)

Sebagai pelengkap jawaban yang diterima, jawaban ini menunjukkan keras perilaku dan cara untuk mencapai masing-masing gambar.

Umum Keras perilaku

Standar keras pemrosesan internal selalu banyak ke banyak seperti pada gambar berikut (di mana saya digunakan = = = fitur = 2, tekanan dan temperatur, hanya sebagai contoh): Dalam gambar ini, saya meningkatkan jumlah langkah ke 5, untuk menghindari kebingungan dengan dimensi lain. Untuk contoh ini:

  • Kita memiliki N tangki minyak
  • Kita menghabiskan 5 jam mengambil langkah-langkah per jam (waktu langkah-langkah)
  • Kita diukur dua fitur:
  • Tekanan P
  • Suhu T Kami input array kemudian harus menjadi sesuatu yang 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]],
        ]

Masukan untuk jendela geser

Sering, LSTM lapisan yang seharusnya untuk memproses seluruh urutan. Membagi windows mungkin bukan ide yang terbaik. Layer ini memiliki internal serikat tentang bagaimana urutan berkembang sebagai langkah maju. Windows menghilangkan kemungkinan pembelajaran jangka urutan, membatasi semua urutan untuk ukuran jendela. Di windows, masing-masing jendela merupakan bagian dari panjang asli berurutan, tetapi dengan Keras mereka akan melihat masing-masing sebagai independen urutan:

        [     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 harus awalnya hanya satu urutan, tetapi anda're membaginya dalam banyak urutan untuk membuat windows. Konsep "apa yang merupakan urutan" adalah abstrak. Bagian yang penting adalah:

  • anda dapat memiliki batch dengan banyak individu urutan
  • apa yang membuat urutan menjadi urutan adalah bahwa mereka berevolusi dalam langkah-langkah (biasanya waktu langkah-langkah)

    Mencapai masing-masing kasus dengan "satu lapisan"

    Mencapai standar banyak ke banyak:

    Anda dapat mencapai banyak ke banyak dengan sederhana LSTM lapisan, menggunakan return_sequences=True:

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

#output_shape -> (batch_size, steps, units)

Mencapai banyak ke satu:

Menggunakan cara yang sama lapisan, keras akan melakukan hal yang sama persis internal preprocessing, tetapi ketika anda menggunakan return_sequences=False (atau mengabaikan argumen ini), keras akan secara otomatis membuang langkah-langkah sebelumnya untuk yang terakhir:

outputs = LSTM(units)(inputs)

#output_shape -> (batch_size, units) --> steps were discarded, only the last was returned

Mencapai satu ke banyak

Sekarang, hal ini tidak didukung dengan keras LSTM lapisan saja. Anda akan harus membuat strategi anda sendiri untuk berlipat ganda langkah-langkah. Ada dua pendekatan:

  • Membuat konstan multi-langkah input dengan mengulangi sebuah tensor
  • Gunakan stateful=True untuk berulang mengambil output dari satu langkah dan melayani sebagai masukan langkah berikutnya (kebutuhan output_features == input_features)

    Satu ke banyak dengan mengulang vektor

    Dalam rangka untuk menyesuaikan dengan keras standar perilaku, kita perlu masukan-masukan dalam langkah-langkah, jadi, kita hanya mengulang 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)

Pengertian stateful = True

Kini hadir salah satu kemungkinan penggunaan stateful=True (selain menghindari loading data yang dapat't sesuai dengan komputer anda's memori sekaligus) Stateful memungkinkan kami untuk input "bagian" urutan secara bertahap. Perbedaannya adalah:

  • Dalam stateful=False, batch kedua berisi seluruh urutan baru, independen dari batch pertama
  • Dalam stateful=True, batch kedua berlanjut batch pertama, memperpanjang urutan yang sama. It's seperti membagi urutan di windows juga, dengan dua perbedaan utama:
  • jendela-jendela ini tidak menempatkan!!
  • stateful=True akan melihat jendela ini terhubung sebagai satu urutan panjang Di stateful=True, setiap batch baru akan ditafsirkan sebagai melanjutkan batch sebelumnya (sampai anda menelepon model.reset_states()).
  • Urutan 1 di batch 2 akan melanjutkan urutan 1 di batch 1.
  • Urutan 2 di batch 2 akan melanjutkan urutan 2 di batch 1.
  • Urutan n dalam batch 2 akan melanjutkan urutan n di batch 1. Contoh dari input, batch 1 ini berisi langkah-langkah 1 dan 2, batch 2 ini berisi langkah-langkah 3 sampai 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 tank di batch 1 dan batch 2! Yang's mengapa kita perlu shuffle=False (kecuali jika kita hanya menggunakan satu urutan, tentu saja). Anda dapat memiliki jumlah batch, tanpa batas. (Bagi yang memiliki variabel panjang di setiap batch, gunakan input_shape=(None,fitur).

Satu ke banyak dengan stateful=True

Untuk kasus kita di sini, kita akan menggunakan hanya 1 langkah per batch, karena kami ingin mendapatkan satu output langkah dan membuat itu menjadi masukan. Harap perhatikan bahwa perilaku dalam gambar tidak "yang disebabkan oleh" stateful=True. Kami akan memaksa bahwa perilaku di manual lingkaran di bawah ini. Dalam contoh ini, stateful=True adalah apa "memungkinkan" kita untuk menghentikan urutan, memanipulasi apa yang kita inginkan, dan melanjutkan dari mana kita berhenti. Jujur, ulangi pendekatan ini mungkin pilihan yang lebih baik untuk kasus ini. Tapi karena kita'kembali melihat ke stateful=True, ini adalah contoh yang baik. Cara terbaik untuk menggunakan ini adalah "banyak ke banyak" kasus ini. 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're akan membutuhkan manual loop 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=True

Sekarang, di sini, kita mendapatkan aplikasi yang sangat bagus: diberikan sebuah urutan masukan, mencoba untuk memprediksi masa depan yang tidak diketahui langkah-langkah. Kami're menggunakan metode yang sama seperti di "untuk" di atas, dengan perbedaan bahwa:

  • kita akan menggunakan urutan itu sendiri menjadi target data, satu langkah ke depan
  • kita tahu bagian dari urutan (agar kita membuang bagian hasil). Lapisan (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) 

Pelatihan: Kami akan melatih kita model untuk memprediksi langkah berikutnya 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 kami memprediksi melibatkan "ajusting negara". Yang's mengapa kita're akan memprediksi seluruh urutan lagi, bahkan jika kita sudah tahu ini bagian dari itu:

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 dalam satu ke banyak hal. Tapi don't reset serikat sini!. Kami ingin model untuk tahu di mana langkah dari urutan itu (dan ia tahu itu's pertama langkah baru karena prediksi kami hanya dibuat 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 ini dan file:

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)

Decoder: Menggunakan "ulangi" metode;

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)

Kereta dengan fit(X,X)

Penjelasan tambahan

Jika anda ingin rincian tentang bagaimana langkah-langkah yang dihitung dalam LSTMs, atau rincian tentang stateful=True kasus-kasus di atas, anda dapat membaca lebih lanjut di jawaban ini: https://stackoverflow.com/questions/53955093/doubts-regarding-understanding-keras-lstms

Komentar (21)

Bila anda memiliki return_sequences di lapisan terakhir dari RNN anda tidak dapat menggunakan sederhana lapisan Padat bukan menggunakan TimeDistributed.

Berikut adalah contoh potongan kode ini mungkin bisa membantu orang lain.

kata-kata = keras.lapisan-lapisan.Input(batch_shape=(None, mandiri.maxSequenceLength), nama = "input")

    # 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))
Komentar (0)