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,
[sampel, waktu, langkah, fitur]
dan,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.
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?
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/
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.):
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
Ternyata model.tambahkan(TimeDistributed(Padat(vocab_len)))
adalah apa yang saya cari. Berikut ini sebuah contoh: https://github.com/sachinruk/ShakespeareBot
Saya telah diringkas kebanyakan dari pemahaman saya tentang LSTMs berikut:
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
.
Sebagai pelengkap jawaban yang diterima, jawaban ini menunjukkan keras perilaku dan cara untuk mencapai masing-masing gambar.
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:
(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]],
]
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 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)
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
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:
stateful=True
untuk berulang mengambil output dari satu langkah dan melayani sebagai masukan langkah berikutnya (kebutuhan output_features == input_features
) 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)
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:
stateful=False
, batch kedua berisi seluruh urutan baru, independen dari batch pertama stateful=True
, batch kedua berlanjut batch pertama, memperpanjang urutan yang sama.
It's seperti membagi urutan di windows juga, dengan dua perbedaan utama: 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()
). 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)
.
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()
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:
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:
Dalam semua contoh di atas, saya menunjukkan perilaku "satu lapisan". Anda dapat, tentu saja, tumpukan berlapis-lapis di atas satu sama lain, tidak necessarly semua mengikuti pola yang sama, dan menciptakan model sendiri. Salah satu contoh menarik yang telah muncul adalah "autoencoder" yang "banyak ke satu encoder" diikuti dengan "untuk" decoder: 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)
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)
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
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))