webentwicklung-frage-antwort-db.com.de

So richten Sie 1D-Convolution und LSTM in Keras ein

Ich möchte eine 1D-Conv-Schicht gefolgt von einer LSTM-Schicht verwenden, um ein 16-Kanal-400-Zeitschritt-Signal zu klassifizieren.

Die Eingabeform besteht aus:

  • X = (n_samples, n_timesteps, n_features), wobei n_samples=476, n_timesteps=400, n_features=16 die Anzahl von Abtastwerten, Zeitschritten und Merkmalen (oder Kanälen) des Signals sind.

  • y = (n_samples, n_timesteps, 1). Jeder Zeitschritt ist entweder mit 0 oder 1 gekennzeichnet (binäre Klassifizierung).

Ich benutze die 1D-Conv, um die Zeitinformationen zu extrahieren, wie in der folgenden Abbildung gezeigt. F=32 Und K=8 Sind die Filter und die Kernelgröße. 1D-MaxPooling wird nach 1D-Conv verwendet. Für die Signalklassifizierung wird LSTM mit 32 Einheiten verwendet. Das Modell sollte ein y_pred = (n_samples, n_timesteps, 1) zurückgeben.

enter image description here

Das Code-Snippet wird wie folgt angezeigt:

input_layer = Input(shape=(dataset.n_timestep, dataset.n_feature))
conv1 = Conv1D(filters=32,
               kernel_size=8,
               strides=1,
               activation='relu')(input_layer)
pool1 = MaxPooling1D(pool_size=4)(conv1)
lstm1 = LSTM(32)(pool1)
output_layer = Dense(1, activation='sigmoid')(lstm1)
model = Model(inputs=input_layer, outputs=output_layer) 

Die Modellzusammenfassung ist unten dargestellt:

enter image description here

Ich habe jedoch den folgenden Fehler erhalten:

ValueError: Error when checking target: expected dense_15 to have 2 dimensions, but got array with shape (476, 400, 1).

Ich denke, das Problem war die falsche Form. Bitte lassen Sie mich wissen, wie das Problem behoben werden kann.

Eine andere Frage ist die Anzahl der Zeitschritte. Wie können wir LSTM mitteilen, dass der Zeitschritt 400 sein muss, da input_shape In der 1D-Conv zugewiesen wurde?


Ich möchte das Modelldiagramm auf der Grundlage des Vorschlags von @today hinzufügen. In diesem Fall ist der Zeitschritt von LSTM 98. Müssen wir in diesem Fall TimeDistributed verwenden? Ich habe die Zeitverteilung in Conv1D nicht angewendet.

enter image description here

Gibt es überhaupt eine Möglichkeit, die Faltung zwischen Kanälen anstelle von Zeitschritten durchzuführen? Beispielsweise durchläuft ein Filter (2, 1) jeden Zeitschritt, wie in der folgenden Abbildung dargestellt. enter image description here

Vielen Dank.

6
Thuan N.

Wenn Sie für jeden Zeitschritt einen Wert vorhersagen möchten, fallen mir zwei leicht unterschiedliche Lösungen ein:

1) Entfernen Sie die Ebene MaxPooling1D, Fügen Sie das Argument padding='same' Zur Ebene Conv1D Hinzu, und fügen Sie das Argument return_sequence=True Zu LSTM hinzu, damit das LSTM gibt die Ausgabe jedes Zeitschritts zurück:

from keras.layers import Input, Dense, LSTM, MaxPooling1D, Conv1D
from keras.models import Model

input_layer = Input(shape=(400, 16))
conv1 = Conv1D(filters=32,
               kernel_size=8,
               strides=1,
               activation='relu',
               padding='same')(input_layer)
lstm1 = LSTM(32, return_sequences=True)(conv1)
output_layer = Dense(1, activation='sigmoid')(lstm1)
model = Model(inputs=input_layer, outputs=output_layer)

model.summary()

Die Modellzusammenfassung wäre:

Layer (type)                 Output Shape              Param #   
=================================================================
input_4 (InputLayer)         (None, 400, 16)           0         
_________________________________________________________________
conv1d_4 (Conv1D)            (None, 400, 32)           4128      
_________________________________________________________________
lstm_4 (LSTM)                (None, 400, 32)           8320      
_________________________________________________________________
dense_4 (Dense)              (None, 400, 1)            33        
=================================================================
Total params: 12,481
Trainable params: 12,481
Non-trainable params: 0
_________________________________________________________________

2) Ändern Sie einfach die Anzahl der Einheiten in der Ebene "Dichte" auf 400 und ändern Sie die Form von y in (n_samples, n_timesteps):

from keras.layers import Input, Dense, LSTM, MaxPooling1D, Conv1D
from keras.models import Model

input_layer = Input(shape=(400, 16))
conv1 = Conv1D(filters=32,
               kernel_size=8,
               strides=1,
               activation='relu')(input_layer)
pool1 = MaxPooling1D(pool_size=4)(conv1)
lstm1 = LSTM(32)(pool1)
output_layer = Dense(400, activation='sigmoid')(lstm1)
model = Model(inputs=input_layer, outputs=output_layer)

model.summary()

Die Modellzusammenfassung wäre:

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_6 (InputLayer)         (None, 400, 16)           0         
_________________________________________________________________
conv1d_6 (Conv1D)            (None, 393, 32)           4128      
_________________________________________________________________
max_pooling1d_5 (MaxPooling1 (None, 98, 32)            0         
_________________________________________________________________
lstm_6 (LSTM)                (None, 32)                8320      
_________________________________________________________________
dense_6 (Dense)              (None, 400)               13200     
=================================================================
Total params: 25,648
Trainable params: 25,648
Non-trainable params: 0
_________________________________________________________________

Vergessen Sie nicht, dass Sie in beiden Fällen 'binary_crossentropy' (Nicht 'categorical_crossentropy') Als Verlustfunktion verwenden müssen. Ich erwarte, dass diese Lösung eine geringere Genauigkeit aufweist als die Lösung Nr. 1; Sie müssen jedoch mit beiden experimentieren und versuchen, die Parameter zu ändern, da dies vollständig von dem spezifischen Problem abhängt, das Sie lösen möchten, und von der Art der Daten, die Sie haben.


pdate:

Sie haben nach einer Faltungsschicht gefragt, die nur einen Zeitschritt und k benachbarte Features abdeckt. Ja, Sie können dies mit einer Conv2D-Ebene tun:

# first add an axis to your data
X = np.expand_dims(X)   # now X has a shape of (n_samples, n_timesteps, n_feats, 1)

# adjust input layer shape ...
conv2 = Conv2D(n_filters, (1, k), ...)   # covers one timestep and k features
# adjust other layers according to the output of convolution layer...

Obwohl ich keine Ahnung habe, warum Sie dies tun, besteht eine Lösung darin, eine LSTM-Ebene zu verwenden, die in eine TimeDistributed-Ebene eingeschlossen ist, oder eine andere Lösung darin, die Ausgabe der Faltungsschicht zu verwenden (dies ist (?, n_timesteps, n_features, n_filters)) Die letzten beiden Achsen abflachen.

2
today

Die Eingabe- und Ausgabeform ist (476, 400, 16) und (476, 1) - was bedeutet, dass nur ein Wert pro vollständiger Sequenz ausgegeben wird.

Ihr LSTM speichert keine Sequenzen zurück (return_sequences = False). Aber auch wenn Sie Conv1D und MaxPooling vor dem LSTM ausführen, wird die Eingabe komprimiert. Also wird LSTM selbst eine Stichprobe von (98,32) erhalten.

Ich gehe davon aus, dass Sie für jeden Eingabeschritt einen Ausgang benötigen.

Unter der Annahme, dass Conv1D und MaxPooling für die Eingabedaten relavent sind, können Sie einen Sequenz-zu-Sequenz-Ansatz versuchen, bei dem Sie die Ausgabe der ersten N/W an ein anderes Netzwerk übergeben, um 400 Ausgaben zurückzugewinnen.

Ich empfehle, dass Sie sich einige Modelle wie Encoder Decoder Seq2SEQ-Netzwerke wie folgt ansehen

https://blog.keras.io/a-ten-minute-introduction-to-sequence-to-sequence-learning-in-keras.html

https://machinelearningmastery.com/define-encoder-decoder-sequence-sequence-model-neural-machine-translation-keras/

1
user007