Zrozumienie Keras LSTMs
Staram się pogodzić moje zrozumienie LSTMs i wskazał tutaj w ten post przez Christopher Olah zaimplementowane w Keras. Jestem po blog napisany przez Jason Brownlee dla keras tutorial. To, co mnie głównie myli, to:
- przekształcanie serii danych na
[samples, time steps, features]
i, - stateful LSTMs
Skupmy się na dwóch powyższych pytaniach z odniesieniem do kodu wklejonego poniżej:
# 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()
Uwaga: create_dataset przyjmuje sekwencję długości n i zwraca tablicę N-look_back
, której każdy element jest sekwencją długości look_back
.
Czym są kroki i funkcje czasu?
Jak widać TrainX jest tablicą 3-D z Time_steps i Feature będącymi odpowiednio dwoma ostatnimi wymiarami (3 i 1 w tym kodzie). Czy w odniesieniu do poniższego obrazka oznacza to, że rozważamy przypadek many to one
, w którym liczba różowych pudełek wynosi 3? A może dosłownie oznacza to, że długość łańcucha wynosi 3 (tj. uwzględniono tylko 3 zielone pola).
Czy argument funkcji staje się istotny, gdy rozważamy szereg wielowymiarowy? np. modelowanie dwóch akcji finansowych jednocześnie?
Stateful LSTMs
Czy stateful LSTMs oznacza, że zapisujemy wartości pamięci komórki między seriami? Jeśli tak jest, batch_size
jest jeden, a pamięć jest resetowana między treningami, więc po co mówić, że jest stanowa. Zgaduję, że to ma związek do tego, że dane treningowe nie są tasowane, ale nie jestem pewien, jak.
Edit 1:
Trochę zmieszany komentarz @ van o tym, że czerwone i zielone pola są równe. Czy poniższe wywołania API odpowiadają rozwiniętym diagramom? Szczególnie zauważając, że drugi diagram (batch_size
był arbitralnie wybrany.):
Edit 2:
Dla osób, które ukończyły kurs głębokiego uczenia Udacity i nadal są zdezorientowane co do argumentu time_step, spójrz na następującą dyskusję: https://discussions.udacity.com/t/rnn-lstm-use-implementation/163169
Aktualizacja:
Okazało się, że właśnie tego szukałem. Oto przykład: https://github.com/sachinruk/ShakespeareBotUpdate2:
Mam podsumowałem większość mojego zrozumienia LSTMs tutaj: https://www.youtube.com/watch?v=ywinX5wgdEU
3 answers
Po pierwsze, wybierasz świetne tutoriale(1,2) na początek.
Co oznacza etap czasowy: Time-steps==3
w X. kształt (opisujący kształt danych) oznacza, że są trzy różowe pola. Ponieważ w Keras każdy krok wymaga wprowadzenia, dlatego liczba zielonych pól powinna być zwykle równa liczbie czerwonych pól. Chyba, że zhakujesz strukturę.
Many to many vs. many to one: W keras istnieje parametr return_sequences
podczas inicjalizacji LSTM
lub GRU
lub SimpleRNN
. Jeśli return_sequences
jest False
(Domyślnie), to jest wiele do jednego, Jak pokazano na rysunku. Jego return shape to (batch_size, hidden_unit_length)
, które reprezentują ostatni stan. Gdy return_sequences
jest True
, to jest wiele do wielu . Jego zwrotny kształt to (batch_size, time_step, hidden_unit_length)
Czy argument feature staje się istotny : argument Feature oznacza "jak duże jest twoje czerwone pole" lub jaki jest wymiar wejściowy każdego kroku. Jeśli chcesz przewidzieć na podstawie, powiedzmy, 8 rodzajów informacji rynkowych, to możesz wygenerować swoje dane za pomocą feature==8
.
Stateful : możesz wyszukać kod źródłowy. Podczas inicjalizacji stanu, if stateful==True
, stan z ostatniego treningu zostanie użyty jako stan początkowy, w przeciwnym razie wygeneruje on nowy stan. Jeszcze nie włączyłem stateful
. Nie zgadzam się jednak z tym, że {[14] } Może być tylko 1, gdy stateful==True
.
Obecnie generujesz swoje dane za pomocą zebranych danych. Obraz Twoje informacje giełdowe przychodzą jako strumień, a nie czekając na dzień, aby zebrać wszystkie sekwencyjne, chciałbyś wygenerować dane wejściowe online podczas treningu / Przewidywania z siecią. Jeśli masz 400 akcji współdzielących tę samą sieć, możesz ustawić batch_size==400
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-03 08:09:59
Jako uzupełnienie zaakceptowanej odpowiedzi, ta odpowiedź pokazuje zachowania kerasa i jak osiągnąć każdy obraz.
Ogólne zachowanie Kerasa
Keras jest jedną z najbardziej rozpoznawalnych i najbardziej rozpoznawalnych postaci keras w historii keras.]}Na tym obrazku zwiększyłem liczbę kroków do 5, aby uniknąć pomylenia z innymi wymiarami.
Do tego przykład:
- mamy zbiorniki na olej N
- spędziliśmy 5 godzin podejmując działania co godzinę (kroki czasowe)
- zmierzyliśmy dwie cechy:
- Ciśnienie P
- Temperatura T
Nasza tablica wejściowa powinna mieć kształt (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]],
]
Wejścia do okien przesuwnych
Często warstwy LSTM mają przetwarzać całe sekwencje. Dzielenie okien może nie być najlepszym pomysłem. Warstwa ma wewnętrzne mówi o tym, jak Sekwencja ewoluuje w miarę postępów. Okna eliminują możliwość uczenia się długich sekwencji, ograniczając wszystkie sekwencje do rozmiaru okna.
W systemie Windows każde okno jest częścią długiej oryginalnej sekwencji, ale przez Kerasa będą one postrzegane jako niezależna Sekwencja.]} [ 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]],
....
]
Zauważ, że w tym przypadku masz początkowo tylko jedną sekwencję, ale dzielisz ją na wiele sekwencji, aby utworzyć System windows.
Pojęcie " co jest sekwencja " jest abstrakcyjna. Ważne części to:
- możesz mieć partie z wieloma pojedynczymi sekwencjami
- to, co sprawia, że sekwencje są sekwencjami, to to, że ewoluują w krokach (Zwykle krokach czasowych)
Osiągnięcie każdego przypadku z "pojedynczymi warstwami"
Osiągnięcie standardu many to many:
Możesz osiągnąć wiele do wielu za pomocą prostej warstwy LSTM, używającreturn_sequences=True
:
outputs = LSTM(units, return_sequences=True)(inputs)
#output_shape -> (batch_size, steps, units)
Osiągnięcie wielu do jeden:
Keras używa dokładnie tej samej warstwy, ale kiedy użyjeszreturn_sequences=False
(lub po prostu zignorujesz ten argument), keras automatycznie odrzuci kroki poprzednie do ostatniego:
outputs = LSTM(units)(inputs)
#output_shape -> (batch_size, units) --> steps were discarded, only the last was returned
Osiągnięcie jednego do wielu
Teraz nie jest to obsługiwane przez same warstwy keras LSTM. Będziesz musiał stworzyć własną strategię, aby pomnożyć kroki. Istnieją dwa dobre podejścia:
- Create a stałe wejście wielostopniowe przez powtórzenie tensora W tym celu należy wykonać następujące czynności, aby wykonać jeden krok i podać go jako dane wejściowe następnego kroku (needs
output_features == input_features
)
Jeden do wielu z wektorem powtórzeń
Aby dopasować się do standardowego zachowania keras, potrzebujemy wejść w krokach, więc po prostu powtarzamy wejścia dla żądanej długości:]}outputs = RepeatVector(steps)(inputs) #where inputs is (batch,features)
outputs = LSTM(units,return_sequences=True)(outputs)
#output_shape -> (batch_size, steps, units)
Understanding stateful = True
Teraz przychodzi jeden z możliwych w przeciwieństwie do innych komputerów, które nie są w stanie zmieścić się w pamięci komputera]}
Stateful pozwala nam wprowadzać" części " sekwencji etapami. Różnica wynosi:
- W
stateful=False
druga partia zawiera zupełnie nowe sekwencje, niezależne od pierwszej partii - W
stateful=True
druga partia kontynuuje pierwszą partię, rozszerzając te same sekwencje.
To jak dzielenie sekwencji również w windows, z tymi dwoma głównymi różnice:
- te okna nie nakładają się!!
-
stateful=True
będzie widzieć te okna połączone jako jedną długą sekwencję
W stateful=True
każda nowa partia będzie interpretowana jako kontynuacja poprzedniej partii(dopóki nie wywołasz model.reset_states()
).
- Sekwencja 1 w partii 2 będzie kontynuowana Sekwencja 1 w partii 1.
- Sekwencja 2 w partii 2 będzie kontynuowana Sekwencja 2 w partii 1.
- Sekwencja n w partii 2 będzie kontynuowana Sekwencja n w Seria 1.
Przykład wejść, partia 1 zawiera kroki 1 i 2, partia 2 zawiera kroki 3 do 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]],
] ]
Zauważ wyrównanie czołgów w partii 1 i partii 2! Dlatego potrzebujemy shuffle=False
(o ile oczywiście nie używamy tylko jednej sekwencji).
Możesz mieć dowolną liczbę partii, w nieskończoność. (Aby mieć zmienne długości w każdej partii, użyj input_shape=(None,features)
.
Jeden do wielu z stateful = True
W naszym przypadku użyjemy tylko 1 kroku na batch, ponieważ chcemy uzyskać jeden krok wyjściowy i uczynić go wejściowym.
Proszę zauważyć, że zachowanie na zdjęciu nie jest "spowodowane" stateful=True
. Wymusimy to zachowanie w poniższej pętli ręcznej. W tym przykładzie stateful=True
jest tym, co "pozwala" nam zatrzymać sekwencję, manipulować tym, co chcemy i kontynuować od miejsca, w którym się zatrzymaliśmy.
stateful=True
, to dobry przykład. Najlepszym sposobem wykorzystania tego jest następny przypadek "wiele do wielu".
Warstwa:
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)
Teraz będziemy potrzebować pętli ręcznej do przewidywania:
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()
Many to many with stateful = True
Teraz, tutaj, mamy bardzo ładne zastosowanie: biorąc pod uwagę sekwencję wejściową, spróbuj przewidzieć jego przyszłe nieznane kroki.
Używamy tej samej metody jak w "jeden do wielu" powyżej, z tą różnicą, że:]}- użyjemy sekwencji sam w sobie być dane docelowe, o krok do przodu
- znamy część sekwencji (więc odrzucamy tę część wyników).
Warstwa (taka sama jak wyżej):
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)
Szkolenie:
Będziemy trenować nasz model, aby przewidzieć następny krok sekwencji:]}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)
Przewidywanie:
[33]}pierwszy etap naszego przewidywania polega na "ustawieniu Stanów". Dlatego zamierzamy przewidzieć cała sekwencja ponownie, nawet jeśli znamy już tę jej część: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
Teraz przechodzimy do pętli jak w przypadku jeden do wielu. Ale nie Resetuj Stanów tutaj!. Chcemy, aby model wiedział, w którym kroku sekwencji jest (i wie, że jest to pierwszy nowy krok ze względu na prognozę, którą przed chwilą wykonaliśmy)
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()
To podejście zostało użyte w tych odpowiedziach i pliku:
- Przewidywanie wielokrotnego kroku do przodu szeregów czasowych za pomocą LSTM
- jak wykorzystać model Keras do prognozowania przyszłych dat lub wydarzeń?
- https://github.com/danmoller/TestRepo/blob/master/TestBookLSTM.ipynb
Osiąganie złożonych konfiguracji
We wszystkich powyższych przykładach pokazałem zachowanie "jednej warstwy".
Można oczywiście układać wiele warstw jeden na drugim, niekoniecznie Wszystkie według tego samego wzoru, i tworzyć własne modele.
Jeden ciekawy przykład, który pojawił się jest "autoencoder", który ma koder "wiele do jednego", a następnie dekoder "Jeden do wielu": {]}
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)
Dekoder:
Używając metody "powtórz";
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)
Pociąg z fit(X,X)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-24 13:32:41
Gdy masz return_sequences w ostatniej warstwie RNN nie możesz użyć prostej gęstej warstwy zamiast tego użyj TimeDistributed.
Oto przykładowy fragment kodu, który może pomóc innym.
Słowa = keras.warstwy.Input (batch_shape=(None, self.maxSequenceLength), name = "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))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-25 09:05:36