Cet article est une traduction du grand Dieu [PhD Jason Brownlee] Bowen, l'adresse originale ici .
Après avoir lu cet article, vous saurez:
如何为序列预测问题开发朴素的LSTM网络。
如何使用LSTM网络通过批处理和功能仔细管理状态。
如何在LSTM网络中手动管理状态以进行状态预测。
在我的新书中,用几行代码,通过18个循序渐进的教程和9个项目,探索如何为一系列预测建模问题开发深度学习模型。
Description du problème: alphabet d'apprentissage
Dans ce tutoriel, nous allons développer et comparer plusieurs différents modèles de réseau de neurones récurrent de LSTM.
Ces contexte comparatif serait un problème de prévision des séries simples d'apprentissage des lettres. Ainsi, compte tenu d'une lettre, de prédire la prochaine lettre de l'alphabet. Ceci est un simple problème de prévision de la série, une fois compris, peuvent être étendus à d'autres problèmes de prévision de la série, comme la prévision des séries chronologiques et la classification de séquence. Utilisons un code python peut être réutilisé entre des exemples pour préparer des questions. Tout d'abord, nous allons importer toutes les classes et les fonctions que nous prévoyons d'utiliser dans ce tutoriel.
import numpy
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from keras.utils import np_utils
Ensuite, nous pouvons fournir des semences pour le générateur de nombres aléatoires pour veiller à ce que le code est exécuté à chaque fois que les résultats sont les mêmes.
# fix random seed for reproducibility
numpy.random.seed(7)
Maintenant, nous pouvons définir un ensemble de données cette lettre. Pour faciliter la lecture, nous définirons les lettres en majuscules. la modélisation des réseaux de neurones numériques, nous avons donc besoin de cartographier les lettres est un entier. Nous pouvons créer un index par lettre aux caractères du dictionnaire (carte) pour accomplir facilement ce. Nous pouvons également créer une recherche inversée à reconvertir en prévision de caractères pour une utilisation ultérieure.
# define the raw dataset
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
# create mapping of characters to integers (0-25) and the reverse
char_to_int = dict((c, i) for i, c in enumerate(alphabet))
int_to_char = dict((i, c) for i, c in enumerate(alphabet))
Maintenant, nous devons créer des entrées et sorties, sur lequel pour former notre réseau de neurones. Nous pouvons définir la longueur de la séquence d'entrée, puis lire dans l'ordre de la séquence de lettres d'entrée pour le faire. Par exemple, nous utilisons une longueur d'entrée. Dès le début des données d'entrée d'origine, on peut lire la première lettre « A » comme la prédiction et la prochaine lettre « B ». Nous prédisons le mouvement et répéter jusqu'à ce que le « Z » le long d'un caractère.
# prepare the dataset of input to output pairs encoded as integers
seq_length = 1
dataX = []
dataY = []
for i in range(0, len(alphabet) - seq_length, 1):
seq_in = alphabet[i:i + seq_length]
seq_out = alphabet[i + seq_length]
dataX.append([char_to_int[char] for char in seq_in])
dataY.append(char_to_int[seq_out])
print(seq_in, '->', seq_out)
Nous imprimons également entrée pour le contrôle d'intégrité. Ce sera capable de code pour générer la sortie suivante, un résumé de la longueur de la séquence d'entrée et délivre en sortie un caractère unique.
A -> B
B -> C
C -> D
D -> E
E -> F
F -> G
G -> H
H -> I
I -> J
J -> K
K -> L
L -> M
M -> N
N -> O
O -> P
P -> Q
Q -> R
R -> S
S -> T
T -> U
U -> V
V -> W
W -> X
X -> Y
Y -> Z
Nous avons besoin de tableau numpy remodelage format désiré réseau LSTM, à savoir: [ les échantillons, pas de temps, Caractéristiques ].
# reshape X to be [samples, time steps, features]
X = numpy.reshape(dataX, (len(dataX), seq_length, 1))
Après mise en forme, on peut entrer un nombre entier normalisée à la gamme de 0 à 1, à savoir l'utilisation du réseau en forme de S-LSTM gamme de fonctions d'activation.
# normalize
X = X / float(len(alphabet))
Enfin, nous pouvons utiliser cette question comme une tâche de classification de séquence, où chaque lettre représente 26 lettres dans une autre classe. Ainsi, nous pouvons utiliser la sortie Keras to_categorical () fonction intégrée (y) est converti en un encodage à chaud.
# one hot encode the output variable
y = np_utils.to_categorical(dataY)
Pour un caractère d'apprendre une LSTM simple mappage de caractères
Le design Let simple LSTM de départ pour apprendre à prédire le caractère suivant dans l'alphabet dans le contexte donné un caractère. Nous publierons construit en une seule lettre à un ensemble aléatoire d'entrée d'une sortie une seule lettre. Comme nous le verrons, cela est difficile apprentissage LSTM. Nous définissons un réseau LSTM 32 unités et une couche de sortie ayant une fonction d'activation softmax doit être prédite. Parce que c'est un problème de classification multi-classe, donc nous pouvons utiliser une fonction logarithmique de la perte (appelée « categorical_crossentropy » dans Keras in), et en utilisant la fonction d'optimisation ADAM pour optimiser le réseau. Le modèle de 500 ère, la taille du lot est 1.
# create and fit the model
model = Sequential()
model.add(LSTM(32, input_shape=(X.shape[1], X.shape[2])))
model.add(Dense(y.shape[1], activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(X, y, epochs=500, batch_size=1, verbose=2)
Après l'ajustement du modèle, nous pouvons évaluer et résumer la performance de l'ensemble des données de formation.
# summarize performance of the model
scores = model.evaluate(X, y, verbose=0)
print("Model Accuracy: %.2f%%" % (scores[1]*100))
Ensuite, nous pouvons exécuter à nouveau les données de formation du réseau et produit les prévisions, l'entrée et la sortie de caractères sont de retour converti en son format d'origine pour comprendre intuitivement l'étendue du réseau pour comprendre le problème.
# demonstrate some model predictions
for pattern in dataX:
x = numpy.reshape(pattern, (1, len(pattern), 1))
x = x / float(len(alphabet))
prediction = model.predict(x, verbose=0)
index = numpy.argmax(prediction)
result = int_to_char[index]
seq_in = [int_to_char[value] for value in pattern]
print(seq_in, "->", result)
La mise en œuvre de code complet est le suivant:
# Naive LSTM to learn one-char to one-char mapping
import numpy
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from keras.utils import np_utils
# fix random seed for reproducibility
numpy.random.seed(7)
# define the raw dataset
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
# create mapping of characters to integers (0-25) and the reverse
char_to_int = dict((c, i) for i, c in enumerate(alphabet))
int_to_char = dict((i, c) for i, c in enumerate(alphabet))
# prepare the dataset of input to output pairs encoded as integers
seq_length = 1
dataX = []
dataY = []
for i in range(0, len(alphabet) - seq_length, 1):
seq_in = alphabet[i:i + seq_length]
seq_out = alphabet[i + seq_length]
dataX.append([char_to_int[char] for char in seq_in])
dataY.append(char_to_int[seq_out])
print(seq_in, '->', seq_out)
# reshape X to be [samples, time steps, features]
X = numpy.reshape(dataX, (len(dataX), seq_length, 1))
# normalize
X = X / float(len(alphabet))
# one hot encode the output variable
y = np_utils.to_categorical(dataY)
# create and fit the model
model = Sequential()
model.add(LSTM(32, input_shape=(X.shape[1], X.shape[2])))
model.add(Dense(y.shape[1], activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(X, y, epochs=500, batch_size=1, verbose=2)
# summarize performance of the model
scores = model.evaluate(X, y, verbose=0)
print("Model Accuracy: %.2f%%" % (scores[1]*100))
# demonstrate some model predictions
for pattern in dataX:
x = numpy.reshape(pattern, (1, len(pattern), 1))
x = x / float(len(alphabet))
prediction = model.predict(x, verbose=0)
index = numpy.argmax(prediction)
result = int_to_char[index]
seq_in = [int_to_char[value] for value in pattern]
print(seq_in, "->", result)
Effectue les résultats de sortie sont les suivantes:
Model Accuracy: 84.00%
['A'] -> B
['B'] -> C
['C'] -> D
['D'] -> E
['E'] -> F
['F'] -> G
['G'] -> H
['H'] -> I
['I'] -> J
['J'] -> K
['K'] -> L
['L'] -> M
['M'] -> N
['N'] -> O
['O'] -> P
['P'] -> Q
['Q'] -> R
['R'] -> S
['S'] -> T
['T'] -> U
['U'] -> W
['V'] -> Y
['W'] -> Z
['X'] -> Z
['Y'] -> Z
Nous pouvons voir que le réseau est en effet difficile de résoudre ce problème. La raison en est qu'il n'y a aucun moyen inférieur contexte LSTM peut être utilisé. Chaque entrée - mode de sortie sont affichés dans un ordre aléatoire sur le réseau, et dans chaque mode (dans chaque mode de traitement par lots, chaque lot comprenant: a) réinitialiser l'état du réseau. Ceci est un abus de l'architecture de réseau LSTM, il est traité comme Standard Multilayer Perceptron même. Ensuite, nous allons essayer de définir le problème différemment, afin de fournir pour plus d'apprentissage pour le réseau.
LSTM simple fenêtre de fonction de trois caractères à un mappage de caractères
Ajouter plus de contexte pour l'empilement des données perceptron méthode populaire est d'utiliser une méthode de fenêtre. Ceci est la séquence où l'étape précédente comme une autre fonction d'entrée fournie par le réseau. Nous pouvons essayer d'utiliser la même technique pour fournir plus de contexte pour le réseau LSTM. Ici, la longueur de la séquence sera de 1 à 3, par exemple:
# prepare the dataset of input to output pairs encoded as integers
seq_length = 3
Exemples de données de formation sont les suivantes:
ABC -> D
BCD -> E
CDE -> F
Ensuite, chaque élément de la séquence en tant que nouvelle fonction à l'entrée du réseau. Cela nécessite la modification de la séquence d'entrée d'une manière remodelage des étapes de préparation de données:
# reshape X to be [samples, time steps, features]
X = numpy.reshape(dataX, (len(dataX), 1, seq_length))
Il doit également être modifiée afin de prouver que, à l'heure prévue à partir du modèle de la façon de remodeler modèle échantillon.
x = numpy.reshape(pattern, (1, 1, len(pattern)))
Complète la mise en œuvre du code est le suivant:
# Naive LSTM to learn three-char window to one-char mapping
import numpy
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from keras.utils import np_utils
# fix random seed for reproducibility
numpy.random.seed(7)
# define the raw dataset
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
# create mapping of characters to integers (0-25) and the reverse
char_to_int = dict((c, i) for i, c in enumerate(alphabet))
int_to_char = dict((i, c) for i, c in enumerate(alphabet))
# prepare the dataset of input to output pairs encoded as integers
seq_length = 3
dataX = []
dataY = []
for i in range(0, len(alphabet) - seq_length, 1):
seq_in = alphabet[i:i + seq_length]
seq_out = alphabet[i + seq_length]
dataX.append([char_to_int[char] for char in seq_in])
dataY.append(char_to_int[seq_out])
print(seq_in, '->', seq_out)
# reshape X to be [samples, time steps, features]
X = numpy.reshape(dataX, (len(dataX), 1, seq_length))
# normalize
X = X / float(len(alphabet))
# one hot encode the output variable
y = np_utils.to_categorical(dataY)
# create and fit the model
model = Sequential()
model.add(LSTM(32, input_shape=(X.shape[1], X.shape[2])))
model.add(Dense(y.shape[1], activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(X, y, epochs=500, batch_size=1, verbose=2)
# summarize performance of the model
scores = model.evaluate(X, y, verbose=0)
print("Model Accuracy: %.2f%%" % (scores[1]*100))
# demonstrate some model predictions
for pattern in dataX:
x = numpy.reshape(pattern, (1, 1, len(pattern)))
x = x / float(len(alphabet))
prediction = model.predict(x, verbose=0)
index = numpy.argmax(prediction)
result = int_to_char[index]
seq_in = [int_to_char[value] for value in pattern]
print(seq_in, "->", result)
Effectue les résultats de sortie sont les suivantes:
Model Accuracy: 86.96%
['A', 'B', 'C'] -> D
['B', 'C', 'D'] -> E
['C', 'D', 'E'] -> F
['D', 'E', 'F'] -> G
['E', 'F', 'G'] -> H
['F', 'G', 'H'] -> I
['G', 'H', 'I'] -> J
['H', 'I', 'J'] -> K
['I', 'J', 'K'] -> L
['J', 'K', 'L'] -> M
['K', 'L', 'M'] -> N
['L', 'M', 'N'] -> O
['M', 'N', 'O'] -> P
['N', 'O', 'P'] -> Q
['O', 'P', 'Q'] -> R
['P', 'Q', 'R'] -> S
['Q', 'R', 'S'] -> T
['R', 'S', 'T'] -> U
['S', 'T', 'U'] -> V
['T', 'U', 'V'] -> Y
['U', 'V', 'W'] -> Z
['V', 'W', 'X'] -> Z
['W', 'X', 'Y'] -> Z
Nous pouvons voir que, pour améliorer le taux d'exécution ne peuvent, ou non. Ceci est une question simple, même avec la méthode de la fenêtre, nous ne pouvons toujours pas apprendre par LSTM. Encore une fois, cela est un cadre pauvre sur la question de l'abus de réseau LSTM. En fait, la séquence de lettres est une étape de temps caractéristique, plutôt que d'une des caractéristiques de longueur de pas de temps unique. Nous fournissons plus de contexte pour le réseau, mais pas comme il y a plus d'ordre comme prévu.
Dans la section suivante, nous serons sous la forme de pas de temps pour fournir plus d'informations de base pour le réseau.
étapes simples LSMC pour une fenêtre de temps de trois caractères à un mappage de caractères
En Keras dans, LSTM usage prévu est sous la forme de pas de temps fournir un contexte, plutôt que sur les autres réseaux offrent le même type de fonction fenêtre. Nous pouvons donner un premier exemple, la longueur de la séquence simplement changé de 1 à 3.
seq_length = 3
输入-输出样例如下所示:
ABC -> D
BCD -> E
CDE -> F
DEF -> G
Sauf que le remodelage de la séquence de données d'entrée comme une série temporelle d'une étape de caractéristique, plutôt que d'un pas de temps unique de la pluralité d'éléments.
# reshape X to be [samples, time steps, features]
X = numpy.reshape(dataX, (len(dataX), seq_length, 1))
Complète la mise en œuvre du code est le suivant:
# Naive LSTM to learn three-char time steps to one-char mapping
import numpy
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from keras.utils import np_utils
# fix random seed for reproducibility
numpy.random.seed(7)
# define the raw dataset
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
# create mapping of characters to integers (0-25) and the reverse
char_to_int = dict((c, i) for i, c in enumerate(alphabet))
int_to_char = dict((i, c) for i, c in enumerate(alphabet))
# prepare the dataset of input to output pairs encoded as integers
seq_length = 3
dataX = []
dataY = []
for i in range(0, len(alphabet) - seq_length, 1):
seq_in = alphabet[i:i + seq_length]
seq_out = alphabet[i + seq_length]
dataX.append([char_to_int[char] for char in seq_in])
dataY.append(char_to_int[seq_out])
print(seq_in, '->', seq_out)
# reshape X to be [samples, time steps, features]
X = numpy.reshape(dataX, (len(dataX), seq_length, 1))
# normalize
X = X / float(len(alphabet))
# one hot encode the output variable
y = np_utils.to_categorical(dataY)
# create and fit the model
model = Sequential()
model.add(LSTM(32, input_shape=(X.shape[1], X.shape[2])))
model.add(Dense(y.shape[1], activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(X, y, epochs=500, batch_size=1, verbose=2)
# summarize performance of the model
scores = model.evaluate(X, y, verbose=0)
print("Model Accuracy: %.2f%%" % (scores[1]*100))
# demonstrate some model predictions
for pattern in dataX:
x = numpy.reshape(pattern, (1, len(pattern), 1))
x = x / float(len(alphabet))
prediction = model.predict(x, verbose=0)
index = numpy.argmax(prediction)
result = int_to_char[index]
seq_in = [int_to_char[value] for value in pattern]
print(seq_in, "->", result)
Effectue les résultats de sortie sont les suivantes:
Model Accuracy: 100.00%
['A', 'B', 'C'] -> D
['B', 'C', 'D'] -> E
['C', 'D', 'E'] -> F
['D', 'E', 'F'] -> G
['E', 'F', 'G'] -> H
['F', 'G', 'H'] -> I
['G', 'H', 'I'] -> J
['H', 'I', 'J'] -> K
['I', 'J', 'K'] -> L
['J', 'K', 'L'] -> M
['K', 'L', 'M'] -> N
['L', 'M', 'N'] -> O
['M', 'N', 'O'] -> P
['N', 'O', 'P'] -> Q
['O', 'P', 'Q'] -> R
['P', 'Q', 'R'] -> S
['Q', 'R', 'S'] -> T
['R', 'S', 'T'] -> U
['S', 'T', 'U'] -> V
['T', 'U', 'V'] -> W
['U', 'V', 'W'] -> X
['V', 'W', 'X'] -> Y
['W', 'X', 'Y'] -> Z
On peut voir un exemple d'évaluation du modèle et de prévision prouve que le modèle peut parfaitement les problèmes d'apprentissage. Mais il a appris une question plus simple. Plus précisément, on a appris que la séquence prédite à partir de l'alphabet de trois lettres de la lettre suivante. Alphabet peut être affiché dans une séquence aléatoire de trois lettres, et de prévoir la lettre suivante. En fait, il ne peut pas être des lettres énumérées. J'espère avoir une fenêtre assez grand réseau Multilayer Perceptron peut utiliser la même méthode pour apprendre la carte. réseau LSTM est stateful. Ils devraient être en mesure d'apprendre toute la séquence de lettres, mais par défaut, la réalisation Keras réinitialisent l'état du réseau après chaque formation par lots.
état LSTM du lot
Après chaque lot du lot, LSTM de réalisation Keras réinitialisera l'état du réseau. Cela montre que si l'on taille des lots suffisante pour tous les modes d'entrée, et tous les modes d'entrée sont classés dans l'ordre, vous pouvez utiliser la séquence de lots de LSTM de contexte pour mieux apprendre la séquence. Le premier exemple de l'apprentissage par un changement de cartographie et de la taille des lots augmentation de la taille d'un ensemble de données de formation, nous pouvons facilement le prouver. De plus, Keras sera sur l'ensemble des données de formation avant chaque époque brassé de formation. Afin d'assurer le mode de données de formation pour maintenir l'ordre, nous pouvons désactiver la lecture aléatoire.
model.fit(X, y, epochs=5000, batch_size=len(dataX), verbose=2, shuffle=False)
La cartographie du réseau utilisera la séquence d'apprentissage par lots de caractères, mais au cours de la prédiction, le contexte ne sera pas disponible au réseau. Nous pouvons évaluer la capacité du réseau à prédire aléatoire et séquentielle.
la mise en œuvre du code global est le suivant:
# Naive LSTM to learn one-char to one-char mapping with all data in each batch
import numpy
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from keras.utils import np_utils
from keras.preprocessing.sequence import pad_sequences
# fix random seed for reproducibility
numpy.random.seed(7)
# define the raw dataset
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
# create mapping of characters to integers (0-25) and the reverse
char_to_int = dict((c, i) for i, c in enumerate(alphabet))
int_to_char = dict((i, c) for i, c in enumerate(alphabet))
# prepare the dataset of input to output pairs encoded as integers
seq_length = 1
dataX = []
dataY = []
for i in range(0, len(alphabet) - seq_length, 1):
seq_in = alphabet[i:i + seq_length]
seq_out = alphabet[i + seq_length]
dataX.append([char_to_int[char] for char in seq_in])
dataY.append(char_to_int[seq_out])
print(seq_in, '->', seq_out)
# convert list of lists to array and pad sequences if needed
X = pad_sequences(dataX, maxlen=seq_length, dtype='float32')
# reshape X to be [samples, time steps, features]
X = numpy.reshape(dataX, (X.shape[0], seq_length, 1))
# normalize
X = X / float(len(alphabet))
# one hot encode the output variable
y = np_utils.to_categorical(dataY)
# create and fit the model
model = Sequential()
model.add(LSTM(16, input_shape=(X.shape[1], X.shape[2])))
model.add(Dense(y.shape[1], activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(X, y, epochs=5000, batch_size=len(dataX), verbose=2, shuffle=False)
# summarize performance of the model
scores = model.evaluate(X, y, verbose=0)
print("Model Accuracy: %.2f%%" % (scores[1]*100))
# demonstrate some model predictions
for pattern in dataX:
x = numpy.reshape(pattern, (1, len(pattern), 1))
x = x / float(len(alphabet))
prediction = model.predict(x, verbose=0)
index = numpy.argmax(prediction)
result = int_to_char[index]
seq_in = [int_to_char[value] for value in pattern]
print(seq_in, "->", result)
# demonstrate predicting random patterns
print("Test a Random Pattern:")
for i in range(0,20):
pattern_index = numpy.random.randint(len(dataX))
pattern = dataX[pattern_index]
x = numpy.reshape(pattern, (1, len(pattern), 1))
x = x / float(len(alphabet))
prediction = model.predict(x, verbose=0)
index = numpy.argmax(prediction)
result = int_to_char[index]
seq_in = [int_to_char[value] for value in pattern]
print(seq_in, "->", result)
Effectue les résultats de sortie sont les suivantes:
Model Accuracy: 100.00%
['A'] -> B
['B'] -> C
['C'] -> D
['D'] -> E
['E'] -> F
['F'] -> G
['G'] -> H
['H'] -> I
['I'] -> J
['J'] -> K
['K'] -> L
['L'] -> M
['M'] -> N
['N'] -> O
['O'] -> P
['P'] -> Q
['Q'] -> R
['R'] -> S
['S'] -> T
['T'] -> U
['U'] -> V
['V'] -> W
['W'] -> X
['X'] -> Y
['Y'] -> Z
Test a Random Pattern:
['T'] -> U
['V'] -> W
['M'] -> N
['Q'] -> R
['D'] -> E
['V'] -> W
['T'] -> U
['U'] -> V
['J'] -> K
['F'] -> G
['N'] -> O
['B'] -> C
['M'] -> N
['F'] -> G
['F'] -> G
['P'] -> Q
['A'] -> B
['K'] -> L
['W'] -> X
['E'] -> F
Comme prévu, le réseau peut être utilisé dans le cadre de la séquence d'apprentissage de lettres, de manière à atteindre une précision de 100% sur les données de formation. Fait important, le réseau peut prédire avec précision la prochaine lettre de l'alphabet caractère choisi au hasard. Très impressionnant.
Stateful LSTM, pour le mappage d'un caractère à caractère 1
Nous avons vu que nous pouvons être les données brutes en une séquence de taille fixe, et LSTM peut apprendre cette représentation, mais ne peut apprendre trois caractères aléatoires pour mapper un caractère. Nous voyons aussi que nous pouvons faire la métamorphose de la taille des lots, afin de fournir plus série pour le réseau, mais seulement pendant la formation. Idéalement, nous voulons exposer le réseau à toute la séquence, et le laisser apprendre l'interdépendance, plutôt que de définir explicitement les dépendances dans le cadre des questions. Nous pouvons le faire en Keras de cette façon est de faire état se couche LSTM, et la fin de la période (qui est, la fin de la séquence de formation) pour réinitialiser manuellement l'état du réseau.
Cela va vraiment façon LSTM d'utiliser le réseau. Nous avons d'abord besoin de couche LSTM est définie comme un état. Ce faisant, il faut spécifier explicitement la taille de la taille du lot comme la forme d'entrée. Cela a également signifie que lorsque nous évaluons le réseau ou faire des prédictions, nous devons aussi établir et se conformer à la même taille du lot. Maintenant, ce n'est pas un problème, parce que nous utilisons la taille du lot est 1. Cela peut être la taille du lot difficile de prédire quand le cas 1 n'est pas, en raison de la nécessité de prévoir et de l'ordre dans les lots.
batch_size = 1
model.add(LSTM(50, batch_input_shape=(batch_size, X.shape[1], X.shape[2]), stateful=True))
Il y a une différence importante entre le statut de formation LSTM, nous manuellement une fois par période de formation, et l'état remis à zéro après chaque période. Nous pouvons le faire dans une boucle. Encore une fois, nous ne pas SHUFFLE entrée, mais pour garder l'ordre créé des données de formation d'entrée.
for i in range(300):
model.fit(X, y, epochs=1, batch_size=batch_size, verbose=2, shuffle=False)
model.reset_states()
Comme décrit ci-dessus, la taille du lot spécifié nous évaluons les performances du réseau sur l'ensemble des données de formation ensemble.
# summarize performance of the model
scores = model.evaluate(X, y, batch_size=batch_size, verbose=0)
model.reset_states()
print("Model Accuracy: %.2f%%" % (scores[1]*100))
Enfin, nous pouvons prouver que le réseau vraiment appris l'alphabet. Nous pouvons utiliser la première lettre « A » comme une graine, une demande de prévision, la prédiction est renvoyée comme entrée, jusqu'à ce que l'ensemble de « Z » processus est répété.
# demonstrate some model predictions
seed = [char_to_int[alphabet[0]]]
for i in range(0, len(alphabet)-1):
x = numpy.reshape(seed, (1, len(seed), 1))
x = x / float(len(alphabet))
prediction = model.predict(x, verbose=0)
index = numpy.argmax(prediction)
print(int_to_char[seed[0]], "->", int_to_char[index])
seed = [index]
model.reset_states()
Nous pouvons également voir si le réseau peut être prédite à partir du début d'une lettre.
# demonstrate a random starting point
letter = "K"
seed = [char_to_int[letter]]
print("New start: ", letter)
for i in range(0, 5):
x = numpy.reshape(seed, (1, len(seed), 1))
x = x / float(len(alphabet))
prediction = model.predict(x, verbose=0)
index = numpy.argmax(prediction)
print(int_to_char[seed[0]], "->", int_to_char[index])
seed = [index]
model.reset_states()
Complète la mise en œuvre du code est le suivant:
# Stateful LSTM to learn one-char to one-char mapping
import numpy
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from keras.utils import np_utils
# fix random seed for reproducibility
numpy.random.seed(7)
# define the raw dataset
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
# create mapping of characters to integers (0-25) and the reverse
char_to_int = dict((c, i) for i, c in enumerate(alphabet))
int_to_char = dict((i, c) for i, c in enumerate(alphabet))
# prepare the dataset of input to output pairs encoded as integers
seq_length = 1
dataX = []
dataY = []
for i in range(0, len(alphabet) - seq_length, 1):
seq_in = alphabet[i:i + seq_length]
seq_out = alphabet[i + seq_length]
dataX.append([char_to_int[char] for char in seq_in])
dataY.append(char_to_int[seq_out])
print(seq_in, '->', seq_out)
# reshape X to be [samples, time steps, features]
X = numpy.reshape(dataX, (len(dataX), seq_length, 1))
# normalize
X = X / float(len(alphabet))
# one hot encode the output variable
y = np_utils.to_categorical(dataY)
# create and fit the model
batch_size = 1
model = Sequential()
model.add(LSTM(50, batch_input_shape=(batch_size, X.shape[1], X.shape[2]), stateful=True))
model.add(Dense(y.shape[1], activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
for i in range(300):
model.fit(X, y, epochs=1, batch_size=batch_size, verbose=2, shuffle=False)
model.reset_states()
# summarize performance of the model
scores = model.evaluate(X, y, batch_size=batch_size, verbose=0)
model.reset_states()
print("Model Accuracy: %.2f%%" % (scores[1]*100))
# demonstrate some model predictions
seed = [char_to_int[alphabet[0]]]
for i in range(0, len(alphabet)-1):
x = numpy.reshape(seed, (1, len(seed), 1))
x = x / float(len(alphabet))
prediction = model.predict(x, verbose=0)
index = numpy.argmax(prediction)
print(int_to_char[seed[0]], "->", int_to_char[index])
seed = [index]
model.reset_states()
# demonstrate a random starting point
letter = "K"
seed = [char_to_int[letter]]
print("New start: ", letter)
for i in range(0, 5):
x = numpy.reshape(seed, (1, len(seed), 1))
x = x / float(len(alphabet))
prediction = model.predict(x, verbose=0)
index = numpy.argmax(prediction)
print(int_to_char[seed[0]], "->", int_to_char[index])
seed = [index]
model.reset_states()
Effectue les résultats de sortie sont les suivantes:
Model Accuracy: 100.00%
A -> B
B -> C
C -> D
D -> E
E -> F
F -> G
G -> H
H -> I
I -> J
J -> K
K -> L
L -> M
M -> N
N -> O
O -> P
P -> Q
Q -> R
R -> S
S -> T
T -> U
U -> V
V -> W
W -> X
X -> Y
Y -> Z
New start: K
K -> B
B -> C
C -> D
D -> E
E -> F
On peut voir le réseau se souvient parfaitement l'alphabet entier. Il utilise le contexte de l'échantillon lui-même, et comprendre toutes les dépendances prédisent la prochaine séquence de caractères requis. Nous pouvons également voir, si nous utilisons la première lettre du réseau comme une graine, il peut mettre de côté le chaos correctement du reste de l'alphabet. Nous pouvons aussi voir qu'il n'a appris que la séquence complète des lettres, et est un populaire depuis le début de l'apprentissage. Lorsque vous avez demandé de prédire la prochaine lettre « K », il prédira le « B » et revenir à l'alphabet entier. Afin de prédire le vrai « K », il faut un état de réseau itératif préalablement chauffé à partir de « A » à « J » représente une lettre. Cela nous indique que, grâce à des données de formation suivantes, nous pouvons utiliser le LSTM de « apatride » obtenir le même effet:
---a -> b
--ab -> c
-abc -> d
abcd -> e
25 est fixée à la séquence d'entrée (à partir de y à z un de prédiction) et zéro mode de préfixe de remplissage. Enfin, soulèvent des questions au titre de séquence d'entrée de longueur variable pour prédire un caractère à former réseau LSTM.
Entrée à une sortie de caractères de longueur variable LSTM
Dans la section précédente, nous avons trouvé Keras « stateful » avant LSTM est vraiment juste une séquence de raccourci n replay, mais ne nous aide pas vraiment apprendre les lettres de modèle général.
Dans cette section, nous explorons le « apatride » LSTM une variante, la séquence aléatoire variantes apprentissage de l'alphabet, et nous nous efforçons de construire un modèle d'une lettre ou des séquences peut être donné et prévoir l'alphabet suivant lettres. Tout d'abord, nous sommes cadre pour le changement. Par souci de simplicité, nous allons définir la longueur maximale de la séquence d'entrée et est fixée à une faible valeur de 5 ou similaires, afin d'accélérer la formation. Ceci définit la longueur maximale des séquences de lettres à former. Dans le prolongement, si nous permettons reboucle au début de la séquence, vous pouvez le mettre à l'alphabet (26) ou plus. Nous devons également définir le nombre de séquences aléatoires à créer, dans ce cas 1000. Cela peut être plus ou moins. Je veux réellement besoin en mode moins.
# prepare the dataset of input to output pairs encoded as integers
num_inputs = 1000
max_len = 5
dataX = []
dataY = []
for i in range(num_inputs):
start = numpy.random.randint(len(alphabet)-2)
end = numpy.random.randint(start, min(start+max_len,len(alphabet)-1))
sequence_in = alphabet[start:end+1]
sequence_out = alphabet[end + 1]
dataX.append([char_to_int[char] for char in sequence_in])
dataY.append(char_to_int[sequence_out])
print(sequence_in, '->', sequence_out)
échantillon d'entrée comme suit:
PQRST -> U
W -> X
O -> P
OPQ -> R
IJKLM -> N
QRSTU -> V
ABCD -> E
X -> Y
GHIJ -> K
La longueur de la séquence d'entrée varie entre 1 à max_len, rembourrage zéro est nécessaire. Ici, nous utilisons la fonction pad_sequences construit () sur le côté gauche de Keras (préfixe) est rempli.
X = pad_sequences(dataX, maxlen=max_len, dtype='float32')
L'évaluation du modèle formé sur le mode d'entrée sélectionné au hasard. Il est aussi facile que d'une nouvelle séquence de caractères générée aléatoirement. Je pense également que cela peut également être une séquence linéaire à « A » en tant que germe, en tant que fes de sortie unique d'entrée de caractères de retour.
Complète la mise en œuvre du code est le suivant:
# LSTM with Variable Length Input Sequences to One Character Output
import numpy
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from keras.utils import np_utils
from keras.preprocessing.sequence import pad_sequences
from theano.tensor.shared_randomstreams import RandomStreams
# fix random seed for reproducibility
numpy.random.seed(7)
# define the raw dataset
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
# create mapping of characters to integers (0-25) and the reverse
char_to_int = dict((c, i) for i, c in enumerate(alphabet))
int_to_char = dict((i, c) for i, c in enumerate(alphabet))
# prepare the dataset of input to output pairs encoded as integers
num_inputs = 1000
max_len = 5
dataX = []
dataY = []
for i in range(num_inputs):
start = numpy.random.randint(len(alphabet)-2)
end = numpy.random.randint(start, min(start+max_len,len(alphabet)-1))
sequence_in = alphabet[start:end+1]
sequence_out = alphabet[end + 1]
dataX.append([char_to_int[char] for char in sequence_in])
dataY.append(char_to_int[sequence_out])
print(sequence_in, '->', sequence_out)
# convert list of lists to array and pad sequences if needed
X = pad_sequences(dataX, maxlen=max_len, dtype='float32')
# reshape X to be [samples, time steps, features]
X = numpy.reshape(X, (X.shape[0], max_len, 1))
# normalize
X = X / float(len(alphabet))
# one hot encode the output variable
y = np_utils.to_categorical(dataY)
# create and fit the model
batch_size = 1
model = Sequential()
model.add(LSTM(32, input_shape=(X.shape[1], 1)))
model.add(Dense(y.shape[1], activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(X, y, epochs=500, batch_size=batch_size, verbose=2)
# summarize performance of the model
scores = model.evaluate(X, y, verbose=0)
print("Model Accuracy: %.2f%%" % (scores[1]*100))
# demonstrate some model predictions
for i in range(20):
pattern_index = numpy.random.randint(len(dataX))
pattern = dataX[pattern_index]
x = pad_sequences([pattern], maxlen=max_len, dtype='float32')
x = numpy.reshape(x, (1, max_len, 1))
x = x / float(len(alphabet))
prediction = model.predict(x, verbose=0)
index = numpy.argmax(prediction)
result = int_to_char[index]
seq_in = [int_to_char[value] for value in pattern]
print(seq_in, "->", result)
La sortie des résultats est la suivante:
Model Accuracy: 98.90%
['Q', 'R'] -> S
['W', 'X'] -> Y
['W', 'X'] -> Y
['C', 'D'] -> E
['E'] -> F
['S', 'T', 'U'] -> V
['G', 'H', 'I', 'J', 'K'] -> L
['O', 'P', 'Q', 'R', 'S'] -> T
['C', 'D'] -> E
['O'] -> P
['N', 'O', 'P'] -> Q
['D', 'E', 'F', 'G', 'H'] -> I
['X'] -> Y
['K'] -> L
['M'] -> N
['R'] -> T
['K'] -> L
['E', 'F', 'G'] -> H
['Q'] -> R
['Q', 'R', 'S'] -> T
On peut constater que, bien que le modèle ne soit pas parfaitement appris l'alphabet à partir de séquences générées au hasard dans, mais il est un très bon effet. Le modèle n'a pas été ajusté, peut avoir besoin de plus de formation ou de plus grands réseaux, ou les deux (un exercice pour le lecteur). Ceci est au-dessus de l'apprentissage « tout dans l'exemple d'entrée par lots de l'ordre de » bonne extension naturelle des modèles de lettres, car il peut traiter des requêtes ad hoc, mais cela est la longueur de la séquence arbitraire (longueur maximale).
résumé
Dans cet article, vous trouverez dans Keras LSTM récurrents des réseaux de neurones et la façon dont ils gèrent l'état. Plus précisément, vous apprendrez:
如何为单个字符到一个字符的预测开发幼稚的LSTM网络。
如何配置朴素的LSTM以学习样本中各个时间步长的序列。
如何配置LSTM以通过手动管理状态来学习样本之间的序列。