Tutoriel RNN (Recurrent Neural Network) : exemple TensorFlow

โšก Rรฉsumรฉ intelligent

Les rรฉseaux de neurones rรฉcurrents ajoutent une mรฉmoire aux neurones classiques, en rรฉutilisant chaque sortie comme entrรฉe suivante afin que le modรจle apprenne par sรฉquencement. Ce tutoriel explique comment en construire un avec TensorFlow et prรฉdire une sรฉrie temporelle.

  • (I.e. ร‰tat de la mรฉmoire : Chaque neurone rรฉcurrent reรงoit la sortie prรฉcรฉdente ainsi que la nouvelle entrรฉe, ce qui confรจre au rรฉseau sa conscience temporelle.
  • โ˜‘๏ธ Forme de sortie : Une exรฉcution du rรฉseau jouet renvoie un tenseur (3, 2, 6) : lots, pas de temps et neurones dans cet ordre.
  • โœ… Rรจgle de traitement par lots : Les entrรฉes de sรฉries temporelles sont remodelรฉes en trois dimensions et le tableau d'รฉtiquettes est la mรชme sรฉrie dรฉcalรฉe d'une pรฉriode.
  • ๐Ÿงช Squelette du modรจle : Des espaces rรฉservรฉs, une cellule BasicRNNCell enveloppรฉe dans dynamic_rnn, une projection dense, puis une erreur quadratique moyenne avec un optimiseur Adam.
  • ๏ธ Course d'entraรฎnement : 1 500 รฉpoques sur 120 neurones rรฉcurrents font passer la perte de 502 893 ร  environ 1 385.
  • (I.e. Limite connue : Les longues sรฉquences dรฉclenchent le problรจme de disparition du gradient, que les LSTM et leurs variantes ร  porte ont รฉtรฉ conรงues pour rรฉsoudre.

Rรฉseau neuronal rรฉcurrent (RNN)

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 neuronal artificiel Cette opรฉration est relativement simple et repose principalement sur la multiplication matricielle. Dans un premier temps, les entrรฉes sont multipliรฉes par des poids et un biais initialement alรฉatoires, puis transformรฉes par une fonction d'activation. Les valeurs de sortie ainsi obtenues servent ร  effectuer une prรฉdiction. Cette รฉtape permet d'รฉvaluer la prรฉcision du modรจle par rapport ร  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.

L'erreur est heureusement plus faible qu'auparavant, mais pas encore suffisamment rรฉduite. L'optimisation est donc effectuรฉe de maniรจre itรฉrative jusqu'ร  ce que l'erreur soit minimisรฉe, c'est-ร -dire jusqu'ร  ce qu'aucune information supplรฉmentaire ne puisse รชtre extraite.tracTed.

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) ?

Un rรฉseau de neurones rรฉcurrent (RNN) est un type de rรฉseau de neurones artificiels oรน les connexions entre les diffรฉrents nล“uds forment un graphe orientรฉ, ce qui lui confรจre un comportement dynamique dans le temps. Il permet de modรฉliser des donnรฉes sรฉquentielles issues de rรฉseaux ร  propagation directe. Son fonctionnement est similaire ร  celui du 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 de neurones 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. On l'appelle rรฉcursivitรฉ. pas de temps le temps nรฉcessaire pour que la sortie devienne l'entrรฉe de la multiplication matricielle suivante.

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.

Un seul neurone rรฉcurrent renvoie sa sortie ร  t-1 comme entrรฉe de la multiplication suivante

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 dรฉroulรฉ avec quatre entrรฉes, six neurones et deux รฉtapes temporelles

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.

Note de version : Le code de ce tutoriel cible l'API graphique de TensorFlow 1.x. Sur TensorFlow 2.x, le mรชme script s'exรฉcute toujours aprรจs import tensorflow.compat.v1 as tf plus tf.disable_v2_behavior(), car les espaces rรฉservรฉs, les sessions et le module rnn_cell rรฉsident dรฉsormais sous tf.compat.v1L'รฉquivalent idiomatique en 2.x est tf.keras.layers.SimpleRNN.

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.

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

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 pondรฉrations (c.-ร -d. 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 instants prรฉcรฉdents. C'est ainsi que le rรฉseau construit sa propre mรฉmoire. L'information de l'instant prรฉcรฉdent peut se propager dans le futur. C'est lร  toute la magie des rรฉseaux de neurones rรฉcurrents.

## 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]]

ร€ titre explicatif, vous affichez les valeurs de l'รฉtat prรฉcรฉdent. L'affichage ci-dessus correspond ร  la sortie du dernier รฉtat. Affichez maintenant toutes les sorties : vous constaterez que les รฉtats correspondent aux sorties prรฉcรฉdentes de chaque lot. Autrement dit, la sortie prรฉcรฉdente contient les informations relatives ร  la sรฉquence complรจte.

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)

La vue annotรฉe ci-dessous dรฉcompose le mรชme tenseur imprimรฉ lot par lot.

Tenseur de sortie RNN annotรฉ indiquant les trois lots, les six sorties neuronales et la forme (3, 2, 6).

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 gradients restent constants, ce qui signifie qu'il n'y a pas de marge d'amรฉlioration. Le modรจle apprend d'une variation du gradient ; cette variation influence la sortie du rรฉseau. Cependant, si la diffรฉrence de gradient est trop faible (c'est-ร -dire si les poids varient peu), le rรฉseau ne peut rien apprendre et, par consรฉquent, la sortie ne peut รฉvoluer. Ainsi, un rรฉseau confrontรฉ ร  un problรจme de gradient nul ne peut converger vers une solution satisfaisante.

Amรฉlioration LSTM

Pour pallier le problรจme potentiel de disparition du gradient auquel sont confrontรฉs les rรฉseaux de neurones rรฉcurrents (RNN), trois chercheurs, Hochreiter, Schmidhuber et Bengio, ont amรฉliorรฉ ces rรฉseaux grรขce ร  une architecture appelรฉe LSTM (Long Short-Term Memory). En rรฉsumรฉ, LSTM fournit au rรฉseau des informations passรฉes pertinentes pour les pรฉriodes plus rรฉcentes. Le systรจme utilise ainsi une architecture plus performante pour sรฉlectionner et transmettre les informations aux pรฉriodes ultรฉrieures.

L'architecture LSTM est disponible dans TensorFlow, sous le nom tf.contrib.rnn.LSTMCell. LSTM n'est pas abordรฉe dans ce tutoriel. Vous pouvez consulter la documentation officielle. Documentation pour plus d'informations

Sur TensorFlow 2.x, cette cellule est atteinte comme tf.compat.v1.nn.rnn_cell.LSTMCell, tandis que le nouveau code utilise normalement tf.keras.layers.LSTM ou le portail allumeur tf.keras.layers.GRU, ce qui permet d'atteindre une prรฉcision comparable avec moins de paramรจtres.

RNN en sรฉries chronologiques

Dans ce tutoriel TensorFlow sur les rรฉseaux de neurones rรฉcurrents (RNN), vous utiliserez un RNN avec des donnรฉes de sรฉries temporelles. Les sรฉries temporelles dรฉpendent des donnรฉes passรฉes, ce qui signifie que ces valeurs contiennent des informations pertinentes dont le rรฉseau peut tirer des enseignements. L'objectif de la prรฉdiction de sรฉries temporelles est d'estimer la valeur future d'une sรฉrie, par exemple le cours d'une 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()

Sรฉrie temporelle gรฉnรฉrรฉe ร  gauche et exemple d'entraรฎnement en dix รฉtapes avec cibles dรฉcalรฉes ร  droite

La partie droite du graphique prรฉsente toutes les sรฉries. Elles commencent en 2001 et se terminent en 2019. Il est inutile d'injecter toutes les donnรฉes dans le rรฉseau ; il est prรฉfรฉrable de crรฉer un lot de donnรฉes dont la longueur correspond ร  l'intervalle de temps. Ce lot constituera la variable X. La variable Y est identique ร  X, mais dรฉcalรฉe d'une pรฉriode (c'est-ร -dire que l'on souhaite prรฉvoir la valeur ร  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 comprendra 120 neurones rรฉcurrents. Vous alimenterez le modรจle avec une seule entrรฉe, soit un jour. N'hรฉsitez pas ร  modifier les valeurs pour observer si le modรจle s'est amรฉliorรฉ.

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

Aprรจs avoir dรฉfini les ensembles d'entraรฎnement et de test, vous devez crรฉer un objet contenant les lots. Ces lots comprennent les valeurs X et Y. Les valeurs X sont dรฉcalรฉes d'une pรฉriode. Par consรฉquent, vous utilisez les 200 premiรจres observations et le pas de temps est de 10. L'objet `X_batches` doit contenir 20 lots de taille 10 ร— 1. L'objet `y_batches` a la mรชme structure que `X_batches`, mais avec une pรฉriode d'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 qu'il est nรฉcessaire de dรฉcaler les donnรฉes du nombre de pรฉriodes de prรฉvision souhaitรฉes. Par exemple, pour une prรฉvision ร  un jour, dรฉcalez la sรฉrie de 1. Pour une prรฉvision ร  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 CNNDans votre tutoriel prรฉcรฉdent, l'objectif รฉtait de classifier des images. L'objectif est lรฉgรจrement diffรฉrent : il s'agit de prรฉdire si une variable continue appartient ร  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 รชtre amรฉliorรฉ. Il vous appartient de modifier les hyperparamรจtres tels que la taille des fenรชtres, la taille des lots ou le 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()

Graphique prรฉvisionnel versus rรฉel, avec les points rรฉels en vert et les points prรฉvus en rouge.

Prรฉvisions vs Rรฉel

FAQ

Commencez par une fenรชtre couvrant un cycle complet du motif, puis affinez-la. Des fenรชtres plus longues capturent davantage de contexte, mais ralentissent l'entraรฎnement et accentuent l'attรฉnuation du gradient. Dix รฉtapes suffisent pour la sรฉrie journaliรจre ; la saisonnalitรฉ hebdomadaire en nรฉcessite gรฉnรฉralement davantage.

Oui, avec un shim. Remplacez l'importation par tensorflow.compat.v1 et appelez disable_v2_behavior(), car les espaces rรฉservรฉs, les sessions et rnn_cell ont รฉtรฉ dรฉplacรฉs sous l'espace de noms compat. TensorFlow Les projets devraient plutรดt utiliser tf.keras.layers.SimpleRNN.

Les assistants IA suggรจrent des tailles de fenรชtre, repรจrent les incohรฉrences de forme avant l'exรฉcution et gรฉnรจrent un brouillon de code de chargement de donnรฉes ร  partir d'un schรฉma. Ils raccourcissent le cycle d'essais et d'erreurs qui caractรฉrise la modรฉlisation rรฉcurrente, mรชme si les choix dรฉfinitifs d'hyperparamรจtres nรฉcessitent toujours une validation sur des donnรฉes de test.

Copilot gรจre efficacement les tรขches rรฉpรฉtitives : blocs de session, dictionnaires dโ€™alimentation et impression pรฉriodique des pertes. La forme des tenseurs et le dรฉcalage des รฉtiquettes restent les points critiques ; il est donc essentiel de toujours vรฉrifier soi-mรชme les dimensions des lots avant de se fier ร  une boucle gรฉnรฉrรฉe.

Les couches rรฉcurrentes attendent un modรจle de type (lot, pas de temps, caractรฉristique). Le redimensionnement en (-1, fenรชtres, entrรฉe) indique au systรจme le nombre de sรฉquences existantes, la profondeur de chaque sรฉquence analysรฉe et le nombre de valeurs reรงues par pas. Une dimension manquante provoque une erreur de rang.

Le LSTM utilise trois portes logiques et un รฉtat de cellule distinct ; le GRU fusionne les portes d'oubli et d'entrรฉe et supprime l'รฉtat de cellule. Le GRU s'entraรฎne plus rapidement avec moins de paramรจtres, tandis que le LSTM prend souvent l'avantage sur les dรฉpendances trรจs longues.

Les prรฉvisions continues minimisent l'erreur quadratique moyenne, comme le montre cette dรฉmonstration avec la fonction `reduce_sum of squared residuals`. La classification de sรฉquences, telle que l'รฉtiquetage des sentiments ou les tรขches d'analyse d'images abordรฉes dans la sectionโ€ฆ CNN Ce tutoriel utilise ร  la place l'entropie croisรฉe.

Les modรจles Transformer dominent le traitement du langage naturel car l'attention est parallรฉlisรฉe tout au long d'une sรฉquence. Les modรจles rรฉcurrents restent compรฉtitifs pour les flux de donnรฉes, les prรฉvisions univariรฉes courtes et les appareils ร  faible mรฉmoire, oรน le traitement รฉtape par รฉtape constitue un avantage plutรดt qu'un goulot d'รฉtranglement.

Rรฉsumez cet article avec :