Le but de cet article est d'extraire des pondérations du modèle LSTM appris dans Keras et d'implémenter la partie feedforward dans numpy. Pour mon objectif personnel, je voulais jouer avec Keras.
Pour les données, j'ai utilisé les données de prédiction d'onde sinusoïdale utilisant RNN dans la bibliothèque d'apprentissage en profondeur Keras telles quelles. Cet article semble être basé sur j'ai essayé de prédire en laissant RNN apprendre les ondes de péché, donc je leur suis reconnaissant à tous les deux.
import pandas as pd
import math
import numpy as np
np.random.seed(0)
#Coefficient aléatoire
random_factor = 0.05
#Nombre d'étapes par cycle
steps_per_cycle = 80
#Nombre de cycles à générer
number_of_cycles = 50
df = pd.DataFrame(np.arange(steps_per_cycle * number_of_cycles + 1), columns=["t"])
df["sin_t"] = df.t.apply(lambda x: math.sin(x * (2 * math.pi / steps_per_cycle)+ np.random.uniform(-1.0, +1.0) * random_factor))
def _load_data(data, n_prev = 100):
"""
data should be pd.DataFrame()
"""
docX, docY = [], []
for i in range(len(data)-n_prev):
docX.append(data.iloc[i:i+n_prev].as_matrix())
docY.append(data.iloc[i+n_prev].as_matrix())
alsX = np.array(docX)
alsY = np.array(docY)
return alsX, alsY
def train_test_split(df, test_size=0.1, n_prev = 100):
"""
This just splits data to training and testing parts
"""
ntrn = round(len(df) * (1 - test_size))
ntrn = int(ntrn)
X_train, y_train = _load_data(df.iloc[0:ntrn], n_prev)
X_test, y_test = _load_data(df.iloc[ntrn:], n_prev)
return (X_train, y_train), (X_test, y_test)
length_of_sequences = 5
(X_train, y_train), (X_test, y_test) = train_test_split(df[["sin_t"]], n_prev =length_of_sequences)
Comme vous pouvez le voir dans la documentation Keras, reportez-vous à ici pour le moment. Cela semble bon. Le modèle sans $ V_o $ dans la partie Notre modèle ci-dessous a été implémenté dans Keras.
Alors, faisons un modèle comme suit, puis faisons une prédiction.
from keras.models import Sequential
from keras.layers.core import Dense, Activation
from keras.layers.recurrent import LSTM
in_out_neurons = 1
h_num = 100
model = Sequential()
model.add(LSTM(h_num, activation="tanh", recurrent_activation="sigmoid", batch_input_shape=(None, length_of_sequences, in_out_neurons), return_sequences=False))
model.add(Dense(in_out_neurons))
model.add(Activation("linear"))
model.compile(loss="mean_squared_error", optimizer="rmsprop")
model.fit(X_train, y_train, batch_size=600, epochs=15, validation_split=0.05)
y_hat_keras = model.predict(X_test)
Obtenez les paramètres du modèle que vous avez appris plus tôt. Cela semble possible avec la méthode get_weights () ''. Cette méthode a été trouvée à la fois dans l'objet
keras.models.Sequential '' et dans l'objet keras.layers '', donc avec
model.get_weights () '' comme suit: Vous pouvez l'obtenir, ou vous pouvez l'obtenir avec
model.layers [0] .get_weights ()
``.
model.get_weights()Quel paramètre est quel? Donc, pour le moment, modèle.Après avoir vérifié les couches, etc., modélisez.get_weights()Je pense qu'il vaut mieux l'obtenir avec.
```python
weights = model.get_weights()
W, U, b, W_out, b_out = model.get_weights()
print("W.shape : ", W.shape)
print("U.shape : ", U.shape)
print("b.shape : ", b.shape)
print("W_out.shape : ", W_out.shape)
print("b_out.shape : ", b_out.shape)
Wi = W[:,0:h_num]
Wf = W[:,h_num:2*h_num]
Wc = W[:,2*h_num:3*h_num]
Wo = W[:,3*h_num:]
print("Wi : ",Wi.shape)
print("Wf : ",Wf.shape)
print("Wc : ",Wc.shape)
print("Wo : ",Wo.shape)
Ui = U[:,0:h_num]
Uf = U[:,h_num:2*h_num]
Uc = U[:,2*h_num:3*h_num]
Uo = U[:,3*h_num:]
print("Ui : ",Ui.shape)
print("Uf : ",Uf.shape)
print("Uc : ",Uc.shape)
print("Uo : ",Uo.shape)
bi = b[0:h_num]
bf = b[h_num:2*h_num]
bc = b[2*h_num:3*h_num]
bo = b[3*h_num:]
print("bi : ",bi.shape)
print("bf : ",bf.shape)
print("bc : ",bc.shape)
print("bo : ",bo.shape)
En regardant le code original, vous pouvez voir cette entrée, oubliez, cellule de mémoire, dans un tableau. Puisque les poids sont stockés dans l'ordre de sortie, ils sont découpés comme ci-dessus.
La partie formule du document original ne décrivait pas le nombre de dimensions de la matrice, et c'était un peu difficile à lire, alors j'ai soigneusement commenté ce côté. (J'ai l'impression que le code est devenu assez difficile à lire)
def sigmoid(x):
return 1.0 / (1.0 + np.exp(-x))
x = X_test
n = x.shape[0]
#initial
ht_1 = np.zeros(n*h_num).reshape(n,h_num) #h_{t-1}Veux dire.
Ct_1 = np.zeros(n*h_num).reshape(n,h_num) ##C_{t-1}Veux dire.
ht_list = []
for t in np.arange(x.shape[1]):
xt = np.array(x[:,t,:])
#it :porte d'entrée t-term
it = sigmoid(np.dot(xt, Wi) + np.dot(ht_1, Ui) + bi)
# it : (390, 100)
# xt : (390, 1), Wi : (1, 100)
# ht_1 : (390, 100), Ui : (100, 100)
# bi : (100,)
# Ct_tilda :Candidat pour la t-ième période de la cellule mémoire
Ct_tilda = np.tanh(np.dot(xt, Wc) + np.dot(ht_1, Uc) + bc)
# Ct_tilda : (390, 100)
# xt : (390, 1), Wc : (1, 100)
# ht_1 : (390, 100), Uc : (100, 100)
# bc : (100,)
# ft :porte oublier le terme t
ft = sigmoid(np.dot(xt, Wf) + np.dot(ht_1, Uf) + bf)
# ft : (390, 100)
# xt : (390, 1), Wf : (1, 100)
# ht_1 : (390, 100), Uf : (100, 100)
# bf : (100,)
#cellule de mémoire t-term
Ct = it * Ct_tilda + ft * Ct_1
# ot :porte de sortie t-term
ot = sigmoid( np.dot(xt, Wo) + np.dot(ht_1, Uo) + bo)
# ht :La couche cachée de la période t
ht = ot * np.tanh(Ct)
ht_list.append(ht)
ht_1 = ht
Ct_1 = Ct
my_y_hat = np.dot(ht, W_out) + b_out
En regardant la documentation Keras, je ne pouvais pas tout à fait comprendre la différence entre les arguments activation
et
recurrent_activation, mais en regardant le code à l'intérieur, l'activité liée à la cellule mémoire (Ct, Ct_tilde) La fonction d'activation était
activation, et la fonction d'activation pour chaque porte (it, ft, ot) était `` `` recurrent_activation
.
En d'autres termes, dans mon feed-back, la partie qui utilise tanh est activation
, et la partie qui utilise sigmoïde est
recurrent_activation```.
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(y_test,label="true", color="blue")
ax.plot(y_hat_keras, label="keras y_hat", color="red")
ax.plot(my_y_hat, label="my y_hat", linestyle="dashed", color="green")
ax.legend(loc="upper right")
ax.set_ylabel("y")
ax.set_xlabel("x")
fig.savefig("./predict1.png ")
N'est-ce pas un bon sentiment?
import matplotlib.cm as cm
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(y_test, color="red")
for i in np.arange(len(ht_list)):
y_hat_iter = np.dot(ht_list[i], W_out) + b_out
ax.plot(y_hat_iter, color=cm.cool(i/len(ht_list)))
ax.set_ylabel("y")
ax.set_xlabel("x")
fig.savefig("./predict2.png ")
plt.close("all")
À mesure que t augmente, le bleu clair devient violet. Vous pouvez voir que lorsque t augmente, il s'approche de la valeur réelle.
Je voudrais essayer même les signaux non stationnaires. Keras est facile à lire car le code d'origine est également en python. De plus, la lecture du code original est une expérience très enrichissante.
Recommended Posts