python français - Forme d'entrée du réseau neuronal LSTM à partir du dataframe




long short (3)

J'essaie de mettre en place un LSTM avec Keras .

Je sais que les LSTM dans Keras nécessitent un tenseur 3D avec une forme (nb_samples, timesteps, input_dim) en entrée. Cependant, je ne suis pas tout à fait sûr de savoir à quoi ressemblerait l’entrée dans mon cas, car je n’ai qu’un échantillon de T observations pour chaque entrée, pas de plusieurs échantillons (nb_samples=1, timesteps=T, input_dim=N) . Est-il préférable de diviser chacune de mes entrées en échantillons de longueur T/M ? T est environ quelques millions d'observations pour moi, alors combien de temps chaque échantillon devrait-il être dans ce cas, c'est-à-dire comment choisir M ?

Aussi, ai-je raison de dire que ce tenseur devrait ressembler à:

[[[a_11, a_12, ..., a_1M], [a_21, a_22, ..., a_2M], ..., [a_N1, a_N2, ..., a_NM]], 
 [[b_11, b_12, ..., b_1M], [b_21, b_22, ..., b_2M], ..., [b_N1, b_N2, ..., b_NM]], 
 ..., 
 [[x_11, x_12, ..., a_1M], [x_21, x_22, ..., x_2M], ..., [x_N1, x_N2, ..., x_NM]]]

où M et N définis comme avant et x correspondent au dernier échantillon que j'aurais obtenu du fractionnement comme indiqué ci-dessus?

Enfin, étant donné un cadre de données sur les pandas avec T observations T dans chaque colonne et N colonnes, une pour chaque entrée, comment puis-je créer une telle entrée pour alimenter Keras?


Answers

Forme de tensor

Vous avez raison de dire que Keras attend un tenseur 3D pour un réseau neuronal LSTM, mais je pense que la pièce manquante est que Keras s'attend à ce que chaque observation puisse avoir plusieurs dimensions .

Par exemple, dans Keras, j'ai utilisé des vecteurs de mots pour représenter des documents pour le traitement du langage naturel. Chaque mot du document est représenté par un vecteur numérique à n dimensions (donc, si n = 2 le mot «chat» serait représenté par quelque chose comme [0.31, 0.65] ). Pour représenter un document unique, les vecteurs de mots sont alignés en séquence (par exemple, «The cat sat.» = [[0.12, 0.99], [0.31, 0.65], [0.94, 0.04]] ). Un document serait un échantillon unique dans un LSTM Keras.

Ceci est analogue à vos observations de séries chronologiques. Un document est comme une série chronologique, et un mot est comme une seule observation dans votre série temporelle, mais dans votre cas, la représentation de votre observation est simplement n = 1 .

A cause de cela, je pense que votre tenseur devrait être quelque chose comme [[[a1], [a2], ... , [aT]], [[b1], [b2], ..., [bT]], ..., [[x1], [x2], ..., [xT]]] , où x correspond à nb_samples , timesteps = T et input_dim = 1 , car chacune de vos observations n'est qu'un nombre.

Taille du lot

La taille du lot doit être définie de manière à maximiser le débit sans dépasser la capacité de mémoire de votre machine, conformément à cette publication croisée . Autant que je sache, votre saisie n'a pas besoin d'être un multiple de la taille de votre lot, ni lors de la formation du modèle, ni lors de la prédiction de celui-ci.

Exemples

Si vous recherchez un exemple de code, sur le Keras Github, vous trouverez un certain nombre d'exemples d'utilisation de LSTM et d'autres types de réseaux ayant des entrées séquencées.


Vous trouverez ci-dessous un exemple de configuration de données de séries chronologiques pour former un LSTM. La sortie du modèle est absurde car je ne l'ai configurée que pour montrer comment créer le modèle.

import pandas as pd
import numpy as np
# Get some time series data
df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/timeseries.csv")
df.head()

Séries de données:

Date      A       B       C      D      E      F      G
0   2008-03-18  24.68  164.93  114.73  26.27  19.21  28.87  63.44
1   2008-03-19  24.18  164.89  114.75  26.22  19.07  27.76  59.98
2   2008-03-20  23.99  164.63  115.04  25.78  19.01  27.04  59.61
3   2008-03-25  24.14  163.92  114.85  27.41  19.61  27.84  59.41
4   2008-03-26  24.44  163.45  114.84  26.86  19.53  28.02  60.09

Vous pouvez créer des entrées de put dans un vecteur, puis utiliser la fonction pandas .cumsum() pour créer la séquence de la série chronologique:

# Put your inputs into a single list
df['single_input_vector'] = df[input_cols].apply(tuple, axis=1).apply(list)
# Double-encapsulate list so that you can sum it in the next step and keep time steps as separate elements
df['single_input_vector'] = df.single_input_vector.apply(lambda x: [list(x)])
# Use .cumsum() to include previous row vectors in the current row list of vectors
df['cumulative_input_vectors'] = df.single_input_vector.cumsum()

La sortie peut être configurée de manière similaire, mais ce sera un vecteur unique au lieu d'une séquence:

# If your output is multi-dimensional, you need to capture those dimensions in one object
# If your output is a single dimension, this step may be unnecessary
df['output_vector'] = df[output_cols].apply(tuple, axis=1).apply(list)

Les séquences d'entrée doivent avoir la même longueur pour les exécuter dans le modèle. Vous devez donc les adapter à la longueur maximale de vos vecteurs cumulatifs:

# Pad your sequences so they are the same length
from keras.preprocessing.sequence import pad_sequences

max_sequence_length = df.cumulative_input_vectors.apply(len).max()
# Save it as a list   
padded_sequences = pad_sequences(df.cumulative_input_vectors.tolist(), max_sequence_length).tolist()
df['padded_input_vectors'] = pd.Series(padded_sequences).apply(np.asarray)

Les données de formation peuvent être extraites du dataframe et placées dans des tableaux numpy. Notez que les données d'entrée qui sortent du dataframe ne feront pas de tableau 3D. Il fait un tableau de tableaux, ce qui n'est pas la même chose.

Vous pouvez utiliser hstack et remodeler pour créer un tableau d'entrée 3D.

# Extract your training data
X_train_init = np.asarray(df.padded_input_vectors)
# Use hstack to and reshape to make the inputs a 3d vector
X_train = np.hstack(X_train_init).reshape(len(df),max_sequence_length,len(input_cols))
y_train = np.hstack(np.asarray(df.output_vector)).reshape(len(df),len(output_cols))

Pour le prouver:

>>> print(X_train_init.shape)
(11,)
>>> print(X_train.shape)
(11, 11, 6)
>>> print(X_train == X_train_init)
False

Une fois que vous avez des données d'entraînement, vous pouvez définir les dimensions de votre couche d'entrée et de vos couches de sortie.

# Get your input dimensions
# Input length is the length for one input sequence (i.e. the number of rows for your sample)
# Input dim is the number of dimensions in one input vector (i.e. number of input columns)
input_length = X_train.shape[1]
input_dim = X_train.shape[2]
# Output dimensions is the shape of a single output vector
# In this case it's just 1, but it could be more
output_dim = len(y_train[0])

Construisez le modèle:

from keras.models import Model, Sequential
from keras.layers import LSTM, Dense

# Build the model
model = Sequential()

# I arbitrarily picked the output dimensions as 4
model.add(LSTM(4, input_dim = input_dim, input_length = input_length))
# The max output value is > 1 so relu is used as final activation.
model.add(Dense(output_dim, activation='relu'))

model.compile(loss='mean_squared_error',
              optimizer='sgd',
              metrics=['accuracy'])

Enfin, vous pouvez former le modèle et enregistrer le journal de formation comme historique:

# Set batch_size to 7 to show that it doesn't have to be a factor or multiple of your sample size
history = model.fit(X_train, y_train,
              batch_size=7, nb_epoch=3,
              verbose = 1)

Sortie:

Epoch 1/3
11/11 [==============================] - 0s - loss: 3498.5756 - acc: 0.0000e+00     
Epoch 2/3
11/11 [==============================] - 0s - loss: 3498.5755 - acc: 0.0000e+00     
Epoch 3/3
11/11 [==============================] - 0s - loss: 3498.5757 - acc: 0.0000e+00 

C'est tout. Utilisez model.predict(X)X est le même format (autre que le nombre d'échantillons) que X_train afin de faire des prédictions à partir du modèle.


La plupart d'entre eux ont déjà répondu à ce point. Juste comme une note supplémentaire (basée sur ma compréhension et expérimentation mais pas à partir d'une source documentée), la déclaration

== si les objets référencés par les variables sont égaux

à partir de réponses ci-dessus devrait être lu comme

== si les objets référencés par les variables sont égaux et les objets appartenant au même type / classe

. Je suis arrivé à cette conclusion basée sur le test ci-dessous:

list1 = [1,2,3,4]
tuple1 = (1,2,3,4)

print(list1)
print(tuple1)
print(id(list1))
print(id(tuple1))

print(list1 == tuple1)
print(list1 is tuple1)

Ici le contenu de la liste et du tuple est le même mais le type / classe est différent.





python pandas keras lstm