wake-up-neo.com

Stateful LSTM- und Stream-Vorhersagen

Ich habe ein LSTM-Modell (mit Keras und TF erstellt) auf mehrere Stapel von 7 Mustern mit jeweils 3 Merkmalen trainiert, wobei die Form wie unten dargestellt aussieht (Zahlen unten sind nur Platzhalter zum Zwecke der Erklärung), wobei jeder Stapel mit 0 gekennzeichnet ist oder 1:

Daten:

[
   [[1,2,3],[1,2,3],[1,2,3],[1,2,3],[1,2,3],[1,2,3],[1,2,3]]
   [[1,2,3],[1,2,3],[1,2,3],[1,2,3],[1,2,3],[1,2,3],[1,2,3]]
   [[1,2,3],[1,2,3],[1,2,3],[1,2,3],[1,2,3],[1,2,3],[1,2,3]]
   ...
]

d.h. Stapel von m Sequenzen mit jeweils Länge 7, deren Elemente dreidimensionale Vektoren sind (der Stapel hat also eine Form (m * 7 * 3))

Ziel:

[
   [1]
   [0]
   [1]
   ...
]

In meiner Produktionsumgebung befinden sich Daten aus Proben mit 3 Funktionen ([1,2,3],[1,2,3]...). Ich würde gerne jedes Sample streamen, wenn es bei meinem Modell ankommt, und die Zwischenwahrscheinlichkeit erhalten, ohne auf den gesamten Stapel warten zu müssen (7) - siehe Animation unten.

 enter image description here

Eine meiner Gedanken war, den Stapel mit 0 für die fehlenden Proben aufzufüllen, [[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[1,2,3]], aber das scheint ineffizient zu sein.

Ich freue mich über jede Hilfe, die mich in die richtige Richtung lenken kann, sowohl um den LSTM-Zwischenzustand dauerhaft zu speichern, während auf die nächste Probe gewartet wird, als auch auf ein Modell, das mit einer bestimmten Stapelgröße mit Teildaten trainiert wird, vorherzusagen.


Update, einschließlich Modellcode:

opt = optimizers.Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=10e-8, decay=0.001)
model = Sequential()

num_features = data.shape[2]
num_samples = data.shape[1]

first_lstm = LSTM(32, batch_input_shape=(None, num_samples, num_features), return_sequences=True, activation='tanh')
model.add(
    first_lstm)
model.add(LeakyReLU())
model.add(Dropout(0.2))
model.add(LSTM(16, return_sequences=True, activation='tanh'))
model.add(Dropout(0.2))
model.add(LeakyReLU())
model.add(Flatten())
model.add(Dense(1, activation='sigmoid'))

model.compile(loss='binary_crossentropy', optimizer=opt,
              metrics=['accuracy', keras_metrics.precision(), keras_metrics.recall(), f1])

Modellzusammenfassung:

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
lstm_1 (LSTM)                (None, 100, 32)           6272      
_________________________________________________________________
leaky_re_lu_1 (LeakyReLU)    (None, 100, 32)           0         
_________________________________________________________________
dropout_1 (Dropout)          (None, 100, 32)           0         
_________________________________________________________________
lstm_2 (LSTM)                (None, 100, 16)           3136      
_________________________________________________________________
dropout_2 (Dropout)          (None, 100, 16)           0         
_________________________________________________________________
leaky_re_lu_2 (LeakyReLU)    (None, 100, 16)           0         
_________________________________________________________________
flatten_1 (Flatten)          (None, 1600)              0         
_________________________________________________________________
dense_1 (Dense)              (None, 1)                 1601      
=================================================================
Total params: 11,009
Trainable params: 11,009
Non-trainable params: 0
_________________________________________________________________
12
Shlomi Schwartz

Ich denke, es könnte eine einfachere Lösung geben.

Wenn Ihr Modell keine Faltungsebenen oder andere Ebenen hat, die sich auf die Länge/Schritt-Dimension auswirken, können Sie es einfach als stateful=True Markieren.

Achtung: Ihr Modell hat Ebenen, die sich auf die Längenabmessung auswirken !!

Der Layer Flatten wandelt die Längenbemaßung in eine Feature-Bemaßung um. Dies wird Sie vollständig daran hindern, Ihr Ziel zu erreichen. Wenn die Ebene Flatten 7 Schritte erwartet, benötigen Sie immer 7 Schritte.

Bevor Sie meine Antwort unten anwenden, korrigieren Sie Ihr Modell so, dass die Ebene Flatten nicht verwendet wird. Stattdessen kann einfach der return_sequences=True Für die letzte LSTM-Ebene entfernt werden.

Der folgende Code hat das behoben und bereitet auch einige Dinge vor, die mit der folgenden Antwort verwendet werden sollen:

def createModel(forTraining):

    #model for training, stateful=False, any batch size   
    if forTraining == True:
        batchSize = None
        stateful = False

    #model for predicting, stateful=True, fixed batch size
    else:
        batchSize = 1
        stateful = True

    model = Sequential()

    first_lstm = LSTM(32, 
        batch_input_shape=(batchSize, num_samples, num_features), 
        return_sequences=True, activation='tanh', 
        stateful=stateful)   

    model.add(first_lstm)
    model.add(LeakyReLU())
    model.add(Dropout(0.2))

    #this is the last LSTM layer, use return_sequences=False
    model.add(LSTM(16, return_sequences=False, stateful=stateful,  activation='tanh'))

    model.add(Dropout(0.2))
    model.add(LeakyReLU())

    #don't add a Flatten!!!
    #model.add(Flatten())

    model.add(Dense(1, activation='sigmoid'))

    if forTraining == True:
        compileThisModel(model)

Auf diese Weise können Sie mit 7 Schritten trainieren und mit einem Schritt vorhersagen. Sonst wird es nicht möglich sein.

Die Verwendung eines Stateful-Modells als Lösung für Ihre Frage

Trainieren Sie zuerst dieses neue Modell erneut, da es keine Ebene "Abflachen" hat:

trainingModel = createModel(forTraining=True)
trainThisModel(trainingModel)

Mit diesem trainierten Modell können Sie nun einfach ein neues Modell genauso wie mit dem trainierten Modell erstellen, aber stateful=True In allen LSTM-Ebenen markieren. Und wir sollten die Gewichte aus dem trainierten Modell kopieren.

Da diese neuen Layer eine feste Stapelgröße benötigen (Keras-Regeln), habe ich angenommen, dass sie 1 ist (ein einzelner Stream kommt, nicht m Streams), und habe sie zur obigen Modellerstellung hinzugefügt.

predictingModel = createModel(forTraining=False)
predictingModel.set_weights(trainingModel.get_weights())

Und voilà. Prognostizieren Sie die Ergebnisse des Modells einfach mit einem einzigen Schritt:

pseudo for loop as samples arrive to your model:
    prob = predictingModel.predict_on_batch(sample)

    #where sample.shape == (1, 1, 3)

Wenn Sie feststellen, dass Sie das Ende einer fortlaufenden Sequenz erreicht haben, rufen Sie predictingModel.reset_states() auf, damit Sie eine neue Sequenz sicher starten können, ohne dass das Modell denkt, sie sollte am Ende der vorherigen repariert werden.


Speicher- und Ladezustände

Einfach holen und einstellen, mit h5py sparen:

def saveStates(model, saveName):

    f = h5py.File(saveName,'w')

    for l, lay in enumerate(model.layers):
        #if you have nested models, 
            #consider making this recurrent testing for layers in layers
        if isinstance(lay,RNN):
            for s, stat in enumerate(lay.states):
                f.create_dataset('states_' + str(l) + '_' + str(s),
                                 data=K.eval(stat), 
                                 dtype=K.dtype(stat))

    f.close()


def loadStates(model, saveName):

    f = h5py.File(saveName, 'r')
    allStates = list(f.keys())

    for stateKey in allStates:
        name, layer, state = stateKey.split('_')
        layer = int(layer)
        state = int(state)

        K.set_value(model.layers[layer].states[state], f.get(stateKey))

    f.close()

Arbeitstest zum Speichern/Laden von Zuständen

import h5py, numpy as np
from keras.layers import RNN, LSTM, Dense, Input
from keras.models import Model
import keras.backend as K




def createModel():
    inp = Input(batch_shape=(1,None,3))
    out = LSTM(5,return_sequences=True, stateful=True)(inp)
    out = LSTM(2, stateful=True)(out)
    out = Dense(1)(out)
    model = Model(inp,out)
    return model


def saveStates(model, saveName):

    f = h5py.File(saveName,'w')

    for l, lay in enumerate(model.layers):
        #if you have nested models, consider making this recurrent testing for layers in layers
        if isinstance(lay,RNN):
            for s, stat in enumerate(lay.states):
                f.create_dataset('states_' + str(l) + '_' + str(s), data=K.eval(stat), dtype=K.dtype(stat))

    f.close()


def loadStates(model, saveName):

    f = h5py.File(saveName, 'r')
    allStates = list(f.keys())

    for stateKey in allStates:
        name, layer, state = stateKey.split('_')
        layer = int(layer)
        state = int(state)

        K.set_value(model.layers[layer].states[state], f.get(stateKey))

    f.close()

def printStates(model):

    for l in model.layers:
        #if you have nested models, consider making this recurrent testing for layers in layers
        if isinstance(l,RNN):
            for s in l.states:
                print(K.eval(s))   

model1 = createModel()
model2 = createModel()
model1.predict_on_batch(np.ones((1,5,3))) #changes model 1 states

print('model1')
printStates(model1)
print('model2')
printStates(model2)

saveStates(model1,'testStates5')
loadStates(model2,'testStates5')

print('model1')
printStates(model1)
print('model2')
printStates(model2)

Überlegungen zu den Aspekten der Daten

In Ihrem ersten Modell (wenn es stateful=False Ist) wird davon ausgegangen, dass jede Sequenz in m individuell und nicht mit den anderen verbunden ist. Es wird auch berücksichtigt, dass jeder Stapel eindeutige Sequenzen enthält.

Ist dies nicht der Fall, sollten Sie stattdessen das Stateful-Modell trainieren (unter Berücksichtigung, dass jede Sequenz tatsächlich mit der vorherigen Sequenz verbunden ist). Und dann bräuchten Sie m Chargen von 1 Sequenz. -> m x (1, 7 or None, 3).

4
Daniel Möller

Wenn ich es richtig verstanden habe, haben Sie Stapel von m-Sequenzen mit jeweils Länge 7, deren Elemente aus 3-dimensionalen Vektoren bestehen (der Stapel hat also Form (m*7*3)). In jedem Keras RNN können Sie die return_sequences flag auf True, um die Zwischenzustände zu werden, dh für jeden Stapel erhalten Sie anstelle der endgültigen Vorhersage die entsprechenden 7 Ausgänge, wobei die Ausgabe i die Vorhersage in der Stufe i darstellt, wenn alle Eingänge von 0 bis i angegeben sind.

Aber Sie würden am Ende alles auf einmal bekommen. Soweit ich weiß, bietet Keras keine direkte Schnittstelle zum Abrufen des Durchsatzes, während der Stapel verarbeitet wird. Dies kann noch eingeschränkter sein, wenn Sie eine der CUDNN-optimierten Varianten verwenden. Was Sie tun können, ist im Grunde, Ihre Charge als 7 aufeinanderfolgende Chargen von Shape (m*1*3) zu betrachten und sie schrittweise Ihrem LSTM zuzuführen, wobei der verborgene Zustand und die Vorhersage bei jedem Schritt aufgezeichnet werden. Dazu können Sie entweder return_state auf True setzen und dies manuell tun oder einfach stateful auf True setzen und das Objekt den Überblick behalten.


Das folgende Python2 + Keras-Beispiel sollte genau das darstellen, was Sie möchten. Speziell:

  • so können Sie den gesamten LSTM-Zwischenzustand dauerhaft speichern
  • während Sie auf die nächste Probe warten
  • und Vorhersagen auf einem Modell, das mit einer bestimmten Stapelgröße trainiert wurde, die willkürlich und unbekannt sein kann.

Dazu enthält es ein Beispiel für stateful=True für das einfachste Training und return_state=True für die genaueste Inferenz, sodass Sie beide Ansätze kennenlernen können. Es wird auch davon ausgegangen, dass Sie ein Modell erhalten, das serialisiert wurde und von dem Sie nicht viel wissen. Die Struktur ist eng mit der in Andrew Ngs Kurs verwandt, der definitiv autoritärer ist als ich im Thema. Da Sie nicht angeben, wie das Modell trainiert wurde, nahm ich an, dass das Training viel zu eins ist. Dies kann jedoch leicht angepasst werden.

from __future__ import print_function
from keras.layers import Input, LSTM, Dense
from keras.models import Model, load_model
from keras.optimizers import Adam
import numpy as np

# globals
SEQ_LEN = 7
HID_DIMS = 32
OUTPUT_DIMS = 3 # outputs are assumed to be scalars


##############################################################################
# define the model to be trained on a fixed batch size:
# assume many-to-one training setup (otherwise set return_sequences=True)
TRAIN_BATCH_SIZE = 20

x_in = Input(batch_shape=[TRAIN_BATCH_SIZE, SEQ_LEN, 3])
lstm = LSTM(HID_DIMS, activation="tanh", return_sequences=False, stateful=True)
dense = Dense(OUTPUT_DIMS, activation='linear')
m_train = Model(inputs=x_in, outputs=dense(lstm(x_in)))
m_train.summary()

# a dummy batch of training data of shape (TRAIN_BATCH_SIZE, SEQ_LEN, 3), with targets of shape (TRAIN_BATCH_SIZE, 3):
batch123 = np.repeat([[1, 2, 3]], SEQ_LEN, axis=0).reshape(1, SEQ_LEN, 3).repeat(TRAIN_BATCH_SIZE, axis=0)
targets = np.repeat([[123,234,345]], TRAIN_BATCH_SIZE, axis=0) # dummy [[1,2,3],,,]-> [123,234,345] mapping to be learned


# train the model on a fixed batch size and save it
print(">> INFERECE BEFORE TRAINING MODEL:", m_train.predict(batch123, batch_size=TRAIN_BATCH_SIZE, verbose=0))
m_train.compile(optimizer=Adam(lr=0.5), loss='mean_squared_error', metrics=['mae'])
m_train.fit(batch123, targets, epochs=100, batch_size=TRAIN_BATCH_SIZE)
m_train.save("trained_lstm.h5")
print(">> INFERECE AFTER TRAINING MODEL:", m_train.predict(batch123, batch_size=TRAIN_BATCH_SIZE, verbose=0))


##############################################################################
# Now, although we aren't training anymore, we want to do step-wise predictions
# that do alter the inner state of the model, and keep track of that.


m_trained = load_model("trained_lstm.h5")
print(">> INFERECE AFTER RELOADING TRAINED MODEL:", m_trained.predict(batch123, batch_size=TRAIN_BATCH_SIZE, verbose=0))

# now define an analogous model that allows a flexible batch size for inference:
x_in = Input(shape=[SEQ_LEN, 3])
h_in = Input(shape=[HID_DIMS])
c_in = Input(shape=[HID_DIMS])
pred_lstm = LSTM(HID_DIMS, activation="tanh", return_sequences=False, return_state=True, name="lstm_infer")
h, cc, c = pred_lstm(x_in, initial_state=[h_in, c_in])
prediction = Dense(OUTPUT_DIMS, activation='linear', name="dense_infer")(h)
m_inference = Model(inputs=[x_in, h_in, c_in], outputs=[prediction, h,cc,c])

#  Let's confirm that this model is able to load the trained parameters:
# first, check that the performance from scratch is not good:
print(">> INFERENCE BEFORE SWAPPING MODEL:")
predictions, hs, zs, cs = m_inference.predict([batch123,
                                               np.zeros((TRAIN_BATCH_SIZE, HID_DIMS)),
                                               np.zeros((TRAIN_BATCH_SIZE, HID_DIMS))],
                                              batch_size=1)
print(predictions)


# import state from the trained model state and check that it works:
print(">> INFERENCE AFTER SWAPPING MODEL:")
for layer in m_trained.layers:
    if "lstm" in layer.name:
        m_inference.get_layer("lstm_infer").set_weights(layer.get_weights())
    Elif "dense" in layer.name:
        m_inference.get_layer("dense_infer").set_weights(layer.get_weights())

predictions, _, _, _ = m_inference.predict([batch123,
                                            np.zeros((TRAIN_BATCH_SIZE, HID_DIMS)),
                                            np.zeros((TRAIN_BATCH_SIZE, HID_DIMS))],
                                           batch_size=1)
print(predictions)


# finally perform granular predictions while keeping the recurrent activations. Starting the sequence with zeros is a common practice, but depending on how you trained, you might have an <END_OF_SEQUENCE> character that you might want to propagate instead:
h, c = np.zeros((TRAIN_BATCH_SIZE, HID_DIMS)), np.zeros((TRAIN_BATCH_SIZE, HID_DIMS))
for i in range(len(batch123)):
    # about output shape: https://keras.io/layers/recurrent/#rnn
    # h,z,c hold the network's throughput: h is the proper LSTM output, c is the accumulator and cc is (probably) the candidate
    current_input = batch123[i:i+1] # the length of this feed is arbitrary, doesn't have to be 1
    pred, h, cc, c = m_inference.predict([current_input, h, c])
    print("input:", current_input)
    print("output:", pred)
    print(h.shape, cc.shape, c.shape)
    raw_input("do something with your prediction and hidden state and press any key to continue")

Zusätzliche Information:

Da gibt es zwei Formen der staatlichen Persistenz:
1. Die gespeicherten/trainierten Parameter des Modells sind für jede Sequenz gleich
2. Die Variablen a, c, die sich durch die Sequenzen entwickeln und möglicherweise "neu gestartet" werden.

Es ist interessant, einen Blick auf die Eingeweide des LSTM-Objekts zu werfen. In dem von mir angegebenen Python-Beispiel werden die Gewichte a und c explizit behandelt, die trainierten Parameter jedoch nicht, und es ist möglicherweise nicht offensichtlich, wie sie intern implementiert werden oder was sie bedeuten. Sie können wie folgt geprüft werden:

for w in lstm.weights:
    print(w.name, w.shape)

In unserem Fall (32 versteckte Zustände) wird Folgendes zurückgegeben:

lstm_1/kernel:0 (3, 128)
lstm_1/recurrent_kernel:0 (32, 128)
lstm_1/bias:0 (128,)

Wir beobachten eine Dimensionalität von 128. Warum ist das so? dieser Link beschreibt die Keras LSTM-Implementierung folgendermaßen:

 enter image description here

Das g ist die wiederkehrende Aktivierung, p ist die Aktivierung, Ws sind die Kernel, Us sind die wiederkehrenden Kernel, h ist die verborgene Variable, die auch die Ausgabe ist, und die Notation * ist eine elementweise Multiplikation.

Was erklärt, dass 128=32*4 die Parameter für die affine Transformation sind, die in jedem der 4 Gates stattfinden, verkettet:

  • Die Matrix der Form (3, 128) (mit dem Namen kernel) verarbeitet die Eingabe für ein bestimmtes Sequenzelement 
  • Die Matrix der Form (32, 128) (mit dem Namen recurrent_kernel) verarbeitet die Eingabe für den letzten wiederkehrenden Zustand h.
  • Der Vektor der Form (128,) (mit dem Namen bias), wie in jedem anderen NN-Setup üblich.
4
fr_andres

Hinweis: Diese Antwort setzt voraus, dass Ihr Modell in der Trainingsphase nicht stateful ist. Sie müssen verstehen, was eine stateful RNN-Schicht ist, und sicherstellen, dass die Trainingsdaten die entsprechenden Eigenschaften von statefulness haben. Kurz gesagt bedeutet dies, dass zwischen den Sequenzen eine Abhängigkeit besteht, d. H. Eine Sequenz ist das Follow-up einer anderen Sequenz, die Sie in Ihrem Modell berücksichtigen möchten. Wenn Ihre Modell- und Trainingsdaten zustandsbehaftet sind, sind andere Antworten, bei denen stateful=True für die RNN-Schichten von Anfang an festgelegt wird, einfacher.

Update: Unabhängig davon, ob das Trainingsmodell stateful ist oder nicht, Sie können seine Gewichte immer in das Inferenzmodell kopieren und Statefulness aktivieren. Ich denke, dass Lösungen, die auf der Einstellung von stateful=True basieren, kürzer und besser als meine sind. Ihr einziger Nachteil ist, dass die Losgröße in diesen Lösungen festgelegt werden muss.


Beachten Sie, dass die Ausgabe einer LSTM-Schicht über eine einzelne Sequenz durch ihre feststehenden Gewichtungsmatrizen und ihre internen Zustände bestimmt wird, die vom vorherigen verarbeiteten Zeitschritt abhängen. Um nun die Ausgabe der LSTM-Schicht für eine einzelne Sequenz der Länge m zu erhalten, ist es eine naheliegende Möglichkeit, die gesamte Sequenz in einem Zug der LSTM-Schicht zuzuführen. Wie bereits erwähnt, können wir diese Tatsache jedoch nutzen, da die internen Zustände von dem vorherigen Zeitschritt abhängen. Diese einzelnen Sequenzblöcke werden von Block zu Block verarbeitet, indem der Status der LSTM-Schicht am Ende der Verarbeitung eines Blocks abgerufen und an das LSTM übergeben wird Schicht für die Verarbeitung des nächsten Blocks. Um es klarer zu machen, sei angenommen, dass die Sequenzlänge 7 ist (d. H. Sie hat 7 Zeitschritte von Merkmalsvektoren mit fester Länge). Als Beispiel ist es möglich, diese Sequenz wie folgt zu verarbeiten:

  1. Führen Sie die Zeitschritte 1 und 2 in die LSTM-Ebene ein. Holen Sie sich den Endzustand (nennen Sie es C1).
  2. Vergeben Sie die Zeitschritte 3, 4 und 5 und geben Sie C1 als Anfangszustand an die LSTM-Schicht an. Holen Sie sich den Endzustand (nennen Sie es C2).
  3. Vergeben Sie die Zeitschritte 6 und 7 und geben Sie C2 als Anfangszustand an die LSTM-Schicht an. Holen Sie sich die endgültige Ausgabe.

Diese endgültige Ausgabe entspricht der Ausgabe, die von der LSTM-Schicht erzeugt wird, wenn wir die gesamten 7 Zeitschritte auf einmal zuführen würden.

Um dies in Keras zu realisieren, können Sie das Argument return_state des LSTM-Layers auf True setzen, um den Zwischenstatus zu erhalten. Geben Sie außerdem keine feste Zeitschrittlänge an, wenn Sie die Eingabeebene definieren. Verwenden Sie stattdessen None, um das Modell mit Sequenzen beliebiger Länge speisen zu können, die es uns ermöglichen, jede Sequenz progressiv zu verarbeiten (es ist in Ordnung, wenn Ihre Eingabedaten in der Trainingszeit Sequenzen fester Länge sind). 

Da Sie diese Fähigkeit zur Bearbeitung von Spannfuttern in der Inferenzzeit benötigen, müssen Sie ein neues Modell definieren, das die im Trainingsmodell verwendete LSTM-Schicht verwendet und die Anfangszustände als Eingabe abrufen kann und die resultierenden Zustände auch als Ausgabe liefert. Das Folgende ist eine allgemeine Skizze, die ausgeführt werden könnte (beachten Sie, dass der zurückgegebene Status der LSTM-Schicht beim Trainieren des Modells nicht verwendet wird, wir benötigen ihn nur zur Testzeit):

# define training model
train_input = Input(shape=(None, n_feats))   # note that the number of timesteps is None
lstm_layer = LSTM(n_units, return_state=True)
lstm_output, _, _ =  lstm_layer(train_input) # note that we ignore the returned states
classifier = Dense(1, activation='sigmoid')
train_output = classifier(lstm_output)

train_model = Model(train_input, train_output)

# compile and fit the model on training data ...

# ==================================================

# define inference model
inf_input = Input(shape=(None, n_feats))
state_h_input = Input(shape=(n_units,))
state_c_input = Input(shape=(n_units,))

# we use the layers of previous model
lstm_output, state_h, state_c = lstm_layer(inf_input,
                                           initial_state=[state_h_input, state_c_input])
output = classifier(lstm_output)

inf_model = Model([inf_input, state_h_input, state_c_input],
                  [output, state_h, state_c])  # note that we return the states as output

Jetzt können Sie den inf_model so lange füttern, wie die Zeitschritte einer Sequenz jetzt verfügbar sind. Beachten Sie jedoch, dass Sie zunächst die Zustände mit Vektoren aller Nullen füttern müssen (dies ist der voreingestellte Anfangswert der Zustände). Wenn die Sequenzlänge beispielsweise 7 ist, wird wie folgt beschrieben, was passiert, wenn ein neuer Datenstrom verfügbar ist:

state_h = np.zeros((1, n_units,))
state_c = np.zeros((1, n_units))

# three new timesteps are available
outputs = inf_model.predict([timesteps, state_h, state_c])

out = output[0,0]  # you may ignore this output since the entire sequence has not been processed yet
state_h = outputs[0,1]
state_c = outputs[0,2]

# after some time another four new timesteps are available
outputs = inf_model.predict([timesteps, state_h, state_c])

# we have processed 7 timesteps, so the output is valid
out = output[0,0]  # store it, pass it to another thread or do whatever you want to do with it

# reinitialize the state to make them ready for the next sequence chunk
state_h = np.zeros((1, n_units))
state_c = np.zeros((1, n_units))

# to be continued...

Natürlich müssen Sie dies in einer Art Schleife tun oder eine Kontrollflussstruktur implementieren, um den Datenstrom zu verarbeiten, aber ich denke, Sie wissen, wie die allgemeine Idee aussieht.

Obwohl Ihr spezielles Beispiel kein Sequenz-zu-Sequenz-Modell ist, empfehle ich dringend, das offizielles Keras seq2seq-Tutorial zu lesen, von dem ich denke, dass man daraus eine Menge Ideen lernen kann.

2
today

Soweit ich weiß, gibt es aufgrund des statischen Diagramms in Tensorflow keine effiziente Möglichkeit, Eingaben mit unterschiedlicher Länge von der Trainingseingangslänge zuzuführen. 

Polsterung ist die offizielle Methode, um damit umzugehen, ist jedoch weniger effizient und speicherintensiv. Ich schlage vor, Sie schauen in Pytorch nach, was für die Behebung Ihres Problems trivial sein wird. 

Es gibt viele großartige Beiträge , um Lstm mit Pytorch zu erstellen, und Sie werden den Vorteil des dynamischen Graphen verstehen, sobald Sie ihn sehen. 

0
Shawn