Tutoriel RNN (Recurrent Neural Network) : exemple TensorFlow

Pourquoi avons-nous besoin dโ€™un rรฉseau neuronal rรฉcurrent (RNN) ?

Le rรฉseau neuronal rรฉcurrent (RNN) vous permet de modรฉliser des unitรฉs de mรฉmoire pour conserver les donnรฉes et modรฉliser les dรฉpendances ร  court terme. Il est รฉgalement utilisรฉ dans la prรฉvision de sรฉries chronologiques pour lโ€™identification de corrรฉlations et de modรจles de donnรฉes. Il permet รฉgalement de produire des rรฉsultats prรฉdictifs pour les donnรฉes sรฉquentielles en offrant un comportement similaire ร  celui d'un cerveau humain.

La structure d'un rรฉseau de neurones artificiels est relativement simple et concerne principalement la multiplication matricielle. Au cours de la premiรจre รฉtape, les entrรฉes sont multipliรฉes par des poids initialement alรฉatoires, et le biais, transformรฉ avec une fonction d'activation, et les valeurs de sortie sont utilisรฉs pour faire une prรฉdiction. Cette รฉtape donne une idรฉe de la distance entre le rรฉseau et la rรฉalitรฉ.

La mรฉtrique appliquรฉe est la perte. Plus la fonction de perte est รฉlevรฉe, plus le modรจle est stupide. Pour amรฉliorer la connaissance du rรฉseau, une certaine optimisation est nรฉcessaire en ajustant les poids du rรฉseau. La descente de gradient stochastique est la mรฉthode utilisรฉe pour modifier les valeurs des poids dans le bon sens. Une fois lโ€™ajustement effectuรฉ, le rรฉseau peut utiliser un autre lot de donnรฉes pour tester ses nouvelles connaissances.

Heureusement, lโ€™erreur est plus faible quโ€™auparavant, mais pas assez petite. L'รฉtape d'optimisation est effectuรฉe de maniรจre itรฉrative jusqu'ร  ce que l'erreur soit minimisรฉe, c'est-ร -dire qu'aucune information supplรฉmentaire ne puisse รชtre extraite.

Le problรจme avec ce type de modรจle est quโ€™il nโ€™a pas de mรฉmoire. Cela signifie que l'entrรฉe et la sortie sont indรฉpendantes. En dโ€™autres termes, le modรจle ne se soucie pas de ce qui a prรฉcรฉdรฉ. Cela soulรจve des questions lorsque vous devez prรฉdire des sรฉries chronologiques ou des phrases, car le rรฉseau a besoin d'informations sur les donnรฉes historiques ou les mots passรฉs.

Pour pallier ce problรจme, un nouveau type d'architecture a รฉtรฉ dรฉveloppรฉ : le rรฉseau de neurones rรฉcurrents (RNN ci-aprรจs)

Qu'est-ce qu'un rรฉseau neuronal rรฉcurrent (RNN) ?

A Rรฉseau de neurones rรฉcurrents (RNN) est une classe de Rรฉseau neuronal artificiel dans lequel la connexion entre diffรฉrents nล“uds forme un graphe orientรฉ pour donner un comportement dynamique temporel. Il permet de modรฉliser des donnรฉes sรฉquentielles dรฉrivรฉes de rรฉseaux ร  rรฉaction. Il fonctionne de la mรชme maniรจre que le cerveau humain pour fournir des rรฉsultats prรฉdictifs.

Un rรฉseau neuronal rรฉcurrent ressemble beaucoup ร  un rรฉseau neuronal traditionnel, sauf qu'un รฉtat mรฉmoire est ajoutรฉ aux neurones. Le calcul pour inclure une mรฉmoire est simple.

Imaginez un modรจle simple avec un seul neurone alimentรฉ par un lot de donnรฉes. Dans un rรฉseau neuronal traditionnel, le modรจle produit la sortie en multipliant l'entrรฉe par le poids et la fonction d'activation. Avec un RNN, cette sortie est renvoyรฉe ร  elle-mรชme un certain nombre de fois. Nous appelons pas de temps la durรฉe pendant laquelle la sortie devient l'entrรฉe de la prochaine multiplication matricielle.

Par exemple, dans lโ€™image ci-dessous, vous pouvez voir que le rรฉseau est composรฉ dโ€™un neurone. Le rรฉseau calcule la multiplication matricielle entre l'entrรฉe et le poids et ajoute de la non-linรฉaritรฉ avec la fonction d'activation. Cela devient la sortie ร  t-1. Cette sortie est l'entrรฉe de la deuxiรจme multiplication matricielle.

Rรฉseau de neurones rรฉcurrents (RNN)
Rรฉseau de neurones rรฉcurrents (RNN)

Ci-dessous, nous codons un simple RNN dans TensorFlow pour comprendre l'รฉtape ainsi que la forme de la sortie.

Le rรฉseau est composรฉ de :

  • Quatre entrรฉes
  • Six neurones
  • 2 รฉtapes

Le rรฉseau fonctionnera comme le montre l'image ci-dessous.

Rรฉseau de neurones rรฉcurrents (RNN)

Le rรฉseau est dit ยซ rรฉcurrent ยป car il effectue la mรชme opรฉration dans chaque case activรฉe. Le rรฉseau a calculรฉ les poids des entrรฉes et de la sortie prรฉcรฉdente avant d'utiliser une fonction d'activation.

import numpy as np
import tensorflow as tf
n_inputs = 4
n_neurons = 6
n_timesteps = 2
The data is a sequence of a number from 0 to 9 and divided into three batches of data.
## Data 
X_batch = np.array([
        [[0, 1, 2, 5], [9, 8, 7, 4]], # Batch 1
        [[3, 4, 5, 2], [0, 0, 0, 0]], # Batch 2
        [[6, 7, 8, 5], [6, 5, 4, 2]], # Batch 3
    ])

Nous pouvons construire le rรฉseau avec un espace rรฉservรฉ pour les donnรฉes, l'รฉtape rรฉcurrente et le rรฉsultat.

  1. Dรฉfinir l'espace rรฉservรฉ pour les donnรฉes
X = tf.placeholder(tf.float32, [None, n_timesteps, n_inputs])

Ici:

  • Aucun : Inconnu et prendra la taille du lot
  • n_timesteps : nombre de fois que le rรฉseau renverra la sortie au neurone
  • n_inputs : nombre d'entrรฉes par lot
  1. Dรฉfinir le rรฉseau rรฉcurrent

Comme mentionnรฉ sur l'image ci-dessus, le rรฉseau est composรฉ de 6 neurones. Le rรฉseau calculera deux produits scalaires :

  • Donnรฉes d'entrรฉe avec le premier ensemble de poids (c'est-ร -dire 6 : รฉgal au nombre de neurones)
  • Sortie prรฉcรฉdente avec un deuxiรจme ensemble de poids (soit 6 : correspondant au nombre de sorties)

Notez que, lors du premier feedforward, les valeurs de la sortie prรฉcรฉdente sont รฉgales ร  des zรฉros car nous n'avons aucune valeur disponible.

L'objet pour construire un RNN est tf.contrib.rnn.BasicRNNCell avec l'argument num_units pour dรฉfinir le nombre d'entrรฉes

basic_cell = tf.contrib.rnn.BasicRNNCell(num_units=n_neurons)

Maintenant que le rรฉseau est dรฉfini, vous pouvez calculer les sorties et les รฉtats

outputs, states = tf.nn.dynamic_rnn(basic_cell, X, dtype=tf.float32)

Cet objet utilise une boucle interne pour multiplier les matrices le nombre de fois appropriรฉ.

Notez que le neurone rรฉcurrent est fonction de toutes les entrรฉes des pas de temps prรฉcรฉdents. C'est ainsi que le rรฉseau construit sa propre mรฉmoire. Les informations du moment prรฉcรฉdent peuvent se propager dans le futur. C'est la magie du rรฉseau neuronal rรฉcurrent

## Define the shape of the tensor
X = tf.placeholder(tf.float32, [None, n_timesteps, n_inputs])
## Define the network
basic_cell = tf.contrib.rnn.BasicRNNCell(num_units=n_neurons)
outputs, states = tf.nn.dynamic_rnn(basic_cell, X, dtype=tf.float32)
init = tf.global_variables_initializer()
init = tf.global_variables_initializer()
with tf.Session() as sess:
    init.run()
    outputs_val = outputs.eval(feed_dict={X: X_batch})
print(states.eval(feed_dict={X: X_batch}))
[[ 0.38941205 -0.9980438   0.99750966  0.7892596   0.9978241   0.9999997 ]
 [ 0.61096436  0.7255889   0.82977575 -0.88226104  0.29261455 -0.15597084]
 [ 0.62091285 -0.87023467  0.99729395 -0.58261937  0.9811445   0.99969864]]

ร€ des fins explicatives, vous imprimez les valeurs de lโ€™รฉtat prรฉcรฉdent. La sortie imprimรฉe ci-dessus montre la sortie du dernier รฉtat. Imprimez maintenant toute la sortie, vous pouvez remarquer que les รฉtats sont la sortie prรฉcรฉdente de chaque lot. Autrement dit, la sortie prรฉcรฉdente contient les informations sur la sรฉquence entiรจre.e

print(outputs_val)    
print(outputs_val.shape)    
[[[-0.75934666 -0.99537754  0.9735819  -0.9722234  -0.14234993
   -0.9984044 ]
  [ 0.99975264 -0.9983206   0.9999993  -1.         -0.9997506
   -1.        ]]

 [[ 0.97486496 -0.98773265  0.9969686  -0.99950117 -0.7092863
   -0.99998885]
  [ 0.9326837   0.2673438   0.2808514  -0.7535883  -0.43337247
    0.5700631 ]]

 [[ 0.99628735 -0.9998728   0.99999213 -0.99999976 -0.9884324
   -1.        ]
  [ 0.99962527 -0.9467421   0.9997403  -0.99999714 -0.99929446
   -0.9999795 ]]]
(3, 2, 6)

Rรฉseau de neurones rรฉcurrents (RNN)

La sortie a la forme de (3, 2, 6) :

  • 3 : Nombre de lots
  • 2 : Numรฉro du pas de temps
  • 6 : Nombre de neurones

L'optimisation d'un rรฉseau de neurones rรฉcurrent est identique ร  un rรฉseau de neurones traditionnel. Vous verrez plus en dรฉtail comment coder l'optimisation dans la prochaine partie de ce tutoriel sur les rรฉseaux de neurones rรฉcurrents.

Applications du RNN

RNN a de multiples utilisations, notamment lorsquโ€™il sโ€™agit de prรฉdire lโ€™avenir. Dans le secteur financier, RNN peut รชtre utile pour prรฉdire les cours des actions ou le signe de la direction du marchรฉ boursier (c'est-ร -dire positive ou nรฉgative).

Le RNN est utile pour une voiture autonome car il permet dโ€™รฉviter un accident de voiture en anticipant la trajectoire du vรฉhicule.

RNN est largement utilisรฉ dans lโ€™analyse de texte, le sous-titrage dโ€™images, lโ€™analyse des sentiments et la traduction automatique. Par exemple, on peut utiliser une critique de film pour comprendre le sentiment ressenti par le spectateur aprรจs avoir regardรฉ le film. L'automatisation de cette tรขche est trรจs utile lorsque la sociรฉtรฉ cinรฉmatographique ne dispose pas de suffisamment de temps pour rรฉviser, รฉtiqueter, consolider et analyser les critiques. La machine peut effectuer le travail avec un niveau de prรฉcision plus รฉlevรฉ.

Limites du RNN

En thรฉorie, RNN est censรฉ transporter les informations plusieurs fois. Cependant, il est assez difficile de propager toutes ces informations lorsque le pas de temps est trop long. Lorsquโ€™un rรฉseau comporte trop de couches profondes, il devient impossible ร  entraรฎner. Ce problรจme s'appelle : problรจme de gradient en voie de disparition. Si vous vous en souvenez, le rรฉseau neuronal met ร  jour le poids ร  l'aide de l'algorithme de descente de gradient. Les gradients diminuent ร  mesure que le rรฉseau descend vers les couches infรฉrieures.

En conclusion, les pentes restent constantes, ce qui signifie quโ€™il nโ€™y a aucune marge dโ€™amรฉlioration. Le modรจle apprend d'un changement de gradient ; ce changement affecte la production du rรฉseau. Cependant, si la diffรฉrence de gradient est trop petite (c'est-ร -dire que les poids changent un peu), le rรฉseau ne peut rien apprendre et donc la sortie. Par consรฉquent, un rรฉseau confrontรฉ ร  un problรจme de gradient nul ne peut pas converger vers une bonne solution.

Amรฉlioration LSTM

Pour surmonter le problรจme potentiel de disparition du gradient auquel est confrontรฉ le RNN, trois chercheurs, Hochreiter, Schmidhuber et Bengio, ont amรฉliorรฉ le RNN avec une architecture appelรฉe Mรฉmoire ร  long terme (LSTM). En bref, LSMT fournit au rรฉseau des informations passรฉes pertinentes sur des รฉpoques plus rรฉcentes. La machine utilise une meilleure architecture pour sรฉlectionner et transporter les informations ultรฉrieurement.

L'architecture LSTM est disponible dans TensorFlow, tf.contrib.rnn.LSTMCell. LSTM sort du cadre du didacticiel. Vous pouvez vous rรฉfรฉrer au fonctionnaire Documentation pour plus d'informations

RNN en sรฉries chronologiques

Dans ce didacticiel TensorFlow RNN, vous utiliserez un RNN avec des donnรฉes de sรฉries chronologiques. Les sรฉries chronologiques dรฉpendent du temps prรฉcรฉdent, ce qui signifie que les valeurs passรฉes incluent des informations pertinentes dont le rรฉseau peut tirer des leรงons. L'idรฉe derriรจre la prรฉvision des sรฉries chronologiques est d'estimer la valeur future d'une sรฉrie, par exemple le cours de l'action, la tempรฉrature, le PIB, etc.

La prรฉparation des donnรฉes pour Keras RNN et les sรฉries chronologiques peut รชtre un peu dรฉlicate. Tout d'abord, l'objectif est de prรฉdire la prochaine valeur de la sรฉrie, ce qui signifie que vous utiliserez les informations passรฉes pour estimer la valeur ร  t + 1. L'รฉtiquette est รฉgale ร  la sรฉquence d'entrรฉe et dรฉcalรฉe d'une pรฉriode en avant. Deuxiรจmement, le nombre d'entrรฉes est fixรฉ ร  1, c'est-ร -dire une observation par fois. Enfin, le pas de temps est รฉgal ร  la sรฉquence de la valeur numรฉrique. Par exemple, si vous dรฉfinissez le pas de temps sur 10, la sรฉquence d'entrรฉe sera renvoyรฉe dix fois consรฉcutives.

Regardez le graphique ci-dessous, nous avons reprรฉsentรฉ les donnรฉes de la sรฉrie chronologique ร  gauche et une sรฉquence d'entrรฉe fictive ร  droite. Vous crรฉez une fonction pour renvoyer un ensemble de donnรฉes avec une valeur alรฉatoire pour chaque jour de janvier 2001 ร  dรฉcembre 2016.

# To plot pretty figures
%matplotlib inline
import matplotlib
import matplotlib.pyplot as plt
import pandas as pd
def create_ts(start = '2001', n = 201, freq = 'M'):
    rng = pd.date_range(start=start, periods=n, freq=freq)
    ts = pd.Series(np.random.uniform(-18, 18, size=len(rng)), rng).cumsum()
    return ts
ts= create_ts(start = '2001', n = 192, freq = 'M')
ts.tail(5)

Sortie

2016-08-31    -93.459631
2016-09-30    -95.264791
2016-10-31    -95.551935
2016-11-30   -105.879611
2016-12-31   -123.729319
Freq: M, dtype: float64
ts = create_ts(start = '2001', n = 222)

# Left
plt.figure(figsize=(11,4))
plt.subplot(121)
plt.plot(ts.index, ts)
plt.plot(ts.index[90:100], ts[90:100], "b-", linewidth=3, label="A training instance")
plt.title("A time series (generated)", fontsize=14)

# Right
plt.subplot(122)
plt.title("A training instance", fontsize=14)
plt.plot(ts.index[90:100], ts[90:100], "b-", markersize=8, label="instance")
plt.plot(ts.index[91:101], ts[91:101], "bo", markersize=10, label="target", markerfacecolor='red')
plt.legend(loc="upper left")
plt.xlabel("Time")

plt.show()

RNN dans les sรฉries chronologiques

La partie droite du graphique montre toutes les sรฉries. Cela a commencรฉ en 2001 et se termine en 2019. Cela n'a aucun sens d'alimenter toutes les donnรฉes du rรฉseau, vous devez plutรดt crรฉer un lot de donnรฉes d'une longueur รฉgale au pas de temps. Ce lot sera la variable X. La variable Y est la mรชme que X mais dรฉcalรฉe d'une pรฉriode (c'est-ร -dire que vous souhaitez prรฉvoir t+1).

Les deux vecteurs ont la mรชme longueur. Vous pouvez le voir dans la partie droite du graphique ci-dessus. La ligne reprรฉsente les dix valeurs de l'entrรฉe X, tandis que les points rouges sont les dix valeurs de l'รฉtiquette, Y. Notez que l'รฉtiquette commence une pรฉriode avant X et se termine une pรฉriode aprรจs.

Crรฉer un RNN pour prรฉdire des sรฉries temporelles dans TensorFlow

Maintenant, dans cette formation RNN, il est temps de crรฉer votre premier RNN pour prรฉdire la sรฉrie ci-dessus. Vous devez spรฉcifier certains hyperparamรจtres (les paramรจtres du modรจle, c'est-ร -dire le nombre de neurones, etc.) pour le modรจle :

  • Nombre d'entrรฉe : 1
  • Pas de temps (fenรชtres en sรฉries temporelles) : 10
  • Nombre de neurones : 120
  • Nombre de sortie : 1

Votre rรฉseau apprendra ร  partir dโ€™une sรฉquence de 10 jours et contiendra 120 neurones rรฉcurrents. Vous alimentez le modรจle avec une seule entrรฉe, c'est-ร -dire un jour. N'hรฉsitez pas ร  modifier les valeurs pour voir si le modรจle s'est amรฉliorรฉ.

Avant de construire le modรจle, vous devez diviser l'ensemble de donnรฉes en une ensemble de trains et un ensemble de test. L'ensemble de donnรฉes complet contient 222 points de donnรฉes ; vous utiliserez les 201 premiers points pour entraรฎner le modรจle et les 21 derniers points pour tester votre modรจle.

Aprรจs avoir dรฉfini un ensemble d'entraรฎnement et de test, vous devez crรฉer un objet contenant les lots. Dans ces lots, vous avez des valeurs X et des valeurs Y. N'oubliez pas que les valeurs X sont dรฉcalรฉes d'une pรฉriode. Vous utilisez donc les 200 premiรจres observations et le pas de temps est รฉgal ร  10. L'objet X_batches doit contenir 20 lots de taille 10*1. L'objet y_batches a la mรชme forme que l'objet X_batches mais avec une pรฉriode en avance.

ร‰tape 1) Crรฉer le train et tester

Tout d'abord, vous convertissez la sรฉrie en un numpy tableau; Ensuite, vous dรฉfinissez les fenรชtres (c'est-ร -dire le nombre de fois oรน le rรฉseau apprendra), le nombre d'entrรฉes, de sorties et la taille de la rame, comme indiquรฉ dans l'exemple TensorFlow RNN ci-dessous.

series = np.array(ts)
n_windows = 20   
n_input =  1
n_output = 1
size_train = 201

Aprรจs cela, vous divisez simplement le tableau en deux ensembles de donnรฉes.

## Split data
train = series[:size_train]
test = series[size_train:]
print(train.shape, test.shape)
(201,) (21,)

ร‰tape 2) Crรฉez la fonction pour renvoyer X_batches et y_batches

Pour faciliter les choses, vous pouvez crรฉer une fonction qui renvoie deux tableaux diffรฉrents, un pour X_batches et un pour y_batches.

ร‰crivons une fonction RNN TensorFlow pour construire les lots.

A noter que les lots X sont dรฉcalรฉs d'une pรฉriode (on prend la valeur t-1). La sortie de la fonction doit avoir trois dimensions. Les premiรจres dimensions sont รฉgales au nombre de lots, la seconde ร  la taille des fenรชtres et la derniรจre au nombre d'entrรฉes.

La partie la plus dรฉlicate consiste ร  sรฉlectionner correctement les points de donnรฉes. Pour les points de donnรฉes X, vous choisissez les observations de t = 1 ร  t = 200, tandis que pour le point de donnรฉes Y, vous renvoyez les observations de t = 2 ร  201. Une fois que vous avez les points de donnรฉes corrects, il est simple de remodeler les sรฉries.

Pour construire l'objet avec les lots, vous devez diviser l'ensemble de donnรฉes en dix lots de longueur รฉgale (c'est-ร -dire 20). Vous pouvez utiliser la mรฉthode reshape et transmettre -1 pour que la sรฉrie soit similaire ร  la taille du lot. La valeur 20 est le nombre d'observations par lot et 1 est le nombre d'entrรฉes.

Vous devez faire la mรชme รฉtape mais pour lโ€™รฉtiquette.

Notez que vous devez dรฉcaler les donnรฉes du nombre de fois que vous souhaitez prรฉvoir. Par exemple, si vous souhaitez prรฉvoir une pรฉriode ร  l'avance, vous dรฉcalez la sรฉrie de 1. Si vous souhaitez prรฉvoir deux jours, dรฉcalez les donnรฉes de 2.

x_data = train[:size_train-1]: Select all the training instance minus one day
X_batches = x_data.reshape(-1, windows, input): create the right shape for the batch e.g (10, 20, 1)
def create_batches(df, windows, input, output):
    ## Create X         
        x_data = train[:size_train-1] # Select the data
        X_batches = x_data.reshape(-1, windows, input)  # Reshape the data 
    ## Create y
        y_data = train[n_output:size_train]
        y_batches = y_data.reshape(-1, windows, output)
        return X_batches, y_batches

Maintenant que la fonction est dรฉfinie, vous pouvez l'appeler pour crรฉer les lots comme indiquรฉ dans l'exemple RNN ci-dessous.

X_batches, y_batches = create_batches(df = train,
                                      windows = n_windows,
                                      input = n_input,
                                      output = n_output)

Vous pouvez imprimer la forme pour vous assurer que les dimensions sont correctes.

print(X_batches.shape, y_batches.shape)
(10, 20, 1) (10, 20, 1)

Vous devez crรฉer l'ensemble de test avec un seul lot de donnรฉes et 20 observations.

Notez que si vous prรฉvoyez jours aprรจs jours, cela signifie que la deuxiรจme valeur prรฉdite sera basรฉe sur la valeur rรฉelle du premier jour (t+1) de l'ensemble de donnรฉes de test. En fait, la vraie valeur sera connue.

Si vous souhaitez prรฉvoir t+2 (c'est-ร -dire deux jours ร  l'avance), vous devez utiliser la valeur prรฉdite t+1 ; si vous souhaitez prรฉdire t+3 (trois jours ร  l'avance), vous devez utiliser les valeurs prรฉdites t+1 et t+2. Il est logique quโ€™il soit difficile de prรฉdire avec prรฉcision t+n jours ร  lโ€™avance.

X_test, y_test = create_batches(df = test, windows = 20,input = 1, output = 1)
print(X_test.shape, y_test.shape)
(10, 20, 1) (10, 20, 1)

Trรจs bien, la taille de votre lot est prรชte, vous pouvez crรฉer l'architecture RNN. N'oubliez pas que vous disposez de 120 neurones rรฉcurrents.

ร‰tape 3) Construisez le modรจle

Pour crรฉer le modรจle, vous devez dรฉfinir trois parties :

  1. La variable avec les tenseurs
  2. Le RNN
  3. La perte et l'optimisation

ร‰tape 3.1) Variables

Vous devez spรฉcifier les variables X et y avec la forme appropriรฉe. Cette รฉtape est triviale. Le tenseur a la mรชme dimension que les objets X_batches et y_batches.

Par exemple, le tenseur X est un espace rรฉservรฉ (consultez le tutoriel sur Introduction ร  Tensorflow pour vous rafraรฎchir l'esprit sur la dรฉclaration des variables) a trois dimensions :

  • Remarque : taille du lot
  • n_windows : Longueur des fenรชtres. c'est-ร -dire le nombre de fois oรน le modรจle regarde en arriรจre
  • n_input : nombre d'entrรฉes

Le rรฉsultat est:

tf.placeholder(tf.float32, [None, n_windows, n_input])
## 1. Construct the tensors
X = tf.placeholder(tf.float32, [None, n_windows, n_input])   
y = tf.placeholder(tf.float32, [None, n_windows, n_output])

ร‰tape 3.2) Crรฉer le RNN

Dans la deuxiรจme partie de cet exemple RNN TensorFlow, vous devez dรฉfinir l'architecture du rรฉseau. Comme auparavant, vous utilisez les objets BasicRNNCell et Dynamic_rnn de l'estimateur TensorFlow.

## 2. create the model
basic_cell = tf.contrib.rnn.BasicRNNCell(num_units=r_neuron, activation=tf.nn.relu)   
rnn_output, states = tf.nn.dynamic_rnn(basic_cell, X, dtype=tf.float32)   

La partie suivante est un peu plus dรฉlicate mais permet un calcul plus rapide. Vous devez transformer la sortie de l'exรฉcution en une couche dense, puis la convertir ร  nouveau pour avoir la mรชme dimension que l'entrรฉe.

stacked_rnn_output = tf.reshape(rnn_output, [-1, r_neuron])          
stacked_outputs = tf.layers.dense(stacked_rnn_output, n_output)       
outputs = tf.reshape(stacked_outputs, [-1, n_windows, n_output])  

ร‰tape 3.3) Crรฉer la perte et l'optimisation

L'optimisation du modรจle dรฉpend de la tรขche que vous effectuez. Dans le tutoriel prรฉcรฉdent sur CNN, votre objectif รฉtait de classer les images, dans ce tutoriel RNN, l'objectif est lรฉgรจrement diffรฉrent. Il vous est demandรฉ de faire une prรฉdiction sur une variable continue par rapport ร  une classe.

Cette diffรฉrence est importante car elle va changer le problรจme d'optimisation. Le problรจme d'optimisation pour une variable continue est de minimiser l'erreur quadratique moyenne. Pour construire ces mรฉtriques dans TF, vous pouvez utiliser :

  • tf.reduce_sum(tf.square(sorties โ€“ y))

Le reste du code RNN est le mรชme quโ€™avant ; vous utilisez un optimiseur Adam pour rรฉduire la perte (c'est-ร -dire MSE) :

  • tf.train.AdamOptimizer(learning_rate=learning_rate)
  • optimiseur.minimiser (perte)

Voilร , vous pouvez tout emballer et votre modรจle est prรชt ร  s'entraรฎner.

tf.reset_default_graph()
r_neuron = 120    

## 1. Construct the tensors
X = tf.placeholder(tf.float32, [None, n_windows, n_input])   
y = tf.placeholder(tf.float32, [None, n_windows, n_output])

## 2. create the model
basic_cell = tf.contrib.rnn.BasicRNNCell(num_units=r_neuron, activation=tf.nn.relu)   
rnn_output, states = tf.nn.dynamic_rnn(basic_cell, X, dtype=tf.float32)              

stacked_rnn_output = tf.reshape(rnn_output, [-1, r_neuron])          
stacked_outputs = tf.layers.dense(stacked_rnn_output, n_output)       
outputs = tf.reshape(stacked_outputs, [-1, n_windows, n_output])   

## 3. Loss + optimization
learning_rate = 0.001  
 
loss = tf.reduce_sum(tf.square(outputs - y))    
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)         
training_op = optimizer.minimize(loss)                                          

init = tf.global_variables_initializer() 

Vous entraรฎnerez le modรจle en utilisant 1500 150 รฉpoques et imprimerez la perte toutes les itรฉrations. Une fois le modรจle entraรฎnรฉ, vous รฉvaluez le modรจle sur l'ensemble de test et crรฉez un objet contenant les prรฉdictions, comme indiquรฉ dans l'exemple de rรฉseau neuronal rรฉcurrent ci-dessous.

iteration = 1500 

with tf.Session() as sess:
    init.run()
    for iters in range(iteration):
        sess.run(training_op, feed_dict={X: X_batches, y: y_batches})
        if iters % 150 == 0:
            mse = loss.eval(feed_dict={X: X_batches, y: y_batches})
            print(iters, "\tMSE:", mse)
    
    y_pred = sess.run(outputs, feed_dict={X: X_test})
0 	MSE: 502893.34
150 	MSE: 13839.129
300 	MSE: 3964.835
450 	MSE: 2619.885
600 	MSE: 2418.772
750 	MSE: 2110.5923
900 	MSE: 1887.9644
1050 	MSE: 1747.1377
1200 	MSE: 1556.3398
1350 	MSE: 1384.6113

Enfin, dans ce didacticiel RNN Deep Learning, vous pouvez tracer la valeur rรฉelle de la sรฉrie avec la valeur prรฉdite. Si votre modรจle est corrigรฉ, les valeurs prรฉdites doivent รชtre placรฉes au-dessus des valeurs rรฉelles.

Comme vous pouvez le constater, le modรจle peut encore รชtre amรฉliorรฉ. A vous de modifier les hyperparamรจtres comme les fenรชtres, la taille du lot du nombre de neurones rรฉcurrents.

plt.title("Forecast vs Actual", fontsize=14)
plt.plot(pd.Series(np.ravel(y_test)), "bo", markersize=8, label="Actual", color='green')
plt.plot(pd.Series(np.ravel(y_pred)), "r.", markersize=8, label="Forecast", color='red')
plt.legend(loc="lower left")
plt.xlabel("Time")

plt.show()
Prรฉvisions vs Rรฉel

Prรฉvisions vs Rรฉel

Rรฉsumรฉ

Un rรฉseau de neurones rรฉcurrent est une architecture robuste pour traiter des sรฉries chronologiques ou des analyses de texte. La sortie de l'รฉtat prรฉcรฉdent est un retour pour prรฉserver la mรฉmoire du rรฉseau au fil du temps ou d'une sรฉquence de mots.

Dans TensorFlow, vous pouvez utiliser les codes suivants pour entraรฎner un rรฉseau neuronal rรฉcurrent TensorFlow pour les sรฉries temporelles :

Paramรจtres du modรจle

n_windows = 20   
n_input =  1
n_output = 1
size_train = 201

Dรฉfinir le modรจle

X = tf.placeholder(tf.float32, [None, n_windows, n_input])   
y = tf.placeholder(tf.float32, [None, n_windows, n_output])

basic_cell = tf.contrib.rnn.BasicRNNCell(num_units=r_neuron, activation=tf.nn.relu)   
rnn_output, states = tf.nn.dynamic_rnn(basic_cell, X, dtype=tf.float32)              

stacked_rnn_output = tf.reshape(rnn_output, [-1, r_neuron])          
stacked_outputs = tf.layers.dense(stacked_rnn_output, n_output)       
outputs = tf.reshape(stacked_outputs, [-1, n_windows, n_output])

Construire l'optimisation

learning_rate = 0.001  
 
loss = tf.reduce_sum(tf.square(outputs - y))    
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)         
training_op = optimizer.minimize(loss)                                          

Former le modรจle

init = tf.global_variables_initializer() 
iteration = 1500 

with tf.Session() as sess:
    init.run()
    for iters in range(iteration):
        sess.run(training_op, feed_dict={X: X_batches, y: y_batches})
        if iters % 150 == 0:
            mse = loss.eval(feed_dict={X: X_batches, y: y_batches})
            print(iters, "\tMSE:", mse)
    
    y_pred = sess.run(outputs, feed_dict={X: X_test})

Rรฉsumez cet article avec :