Οδηγός RNN (Recurrent Neural Network): Παράδειγμα TensorFlow

Γιατί χρειαζόμαστε ένα επαναλαμβανόμενο νευρωνικό δίκτυο (RNN);

Το επαναλαμβανόμενο νευρωνικό δίκτυο (RNN) σάς επιτρέπει να μοντελοποιείτε μονάδες μνήμης για να διατηρούνται δεδομένα και να μοντελοποιείτε βραχυπρόθεσμες εξαρτήσεις. Χρησιμοποιείται επίσης στην πρόβλεψη χρονοσειρών για τον προσδιορισμό συσχετίσεων και προτύπων δεδομένων. Βοηθά επίσης στην παραγωγή προγνωστικών αποτελεσμάτων για διαδοχικά δεδομένα, παρέχοντας παρόμοια συμπεριφορά με τον ανθρώπινο εγκέφαλο.

Η δομή ενός Τεχνητού Νευρωνικού Δικτύου είναι σχετικά απλή και αφορά κυρίως τον πολλαπλασιασμό μήτρας. Κατά τη διάρκεια του πρώτου βήματος, οι είσοδοι πολλαπλασιάζονται με αρχικά τυχαία βάρη και η προκατάληψη, μετασχηματίζεται με μια συνάρτηση ενεργοποίησης και οι τιμές εξόδου χρησιμοποιούνται για να γίνει μια πρόβλεψη. Αυτό το βήμα δίνει μια ιδέα για το πόσο απέχει το δίκτυο από την πραγματικότητα.

Η μέτρηση που εφαρμόζεται είναι η απώλεια. Όσο μεγαλύτερη είναι η συνάρτηση απώλειας, τόσο πιο χαζό είναι το μοντέλο. Για να βελτιωθεί η γνώση του δικτύου, απαιτείται κάποια βελτιστοποίηση με την προσαρμογή των βαρών του δικτύου. Η στοχαστική βαθμιδωτή κάθοδος είναι η μέθοδος που χρησιμοποιείται για την αλλαγή των τιμών των βαρών προς τη σωστή κατεύθυνση. Μόλις γίνει η προσαρμογή, το δίκτυο μπορεί να χρησιμοποιήσει μια άλλη παρτίδα δεδομένων για να δοκιμάσει τις νέες γνώσεις του.

Το σφάλμα, ευτυχώς, είναι μικρότερο από πριν, αλλά όχι αρκετά μικρό. Το βήμα βελτιστοποίησης γίνεται επαναληπτικά έως ότου ελαχιστοποιηθεί το σφάλμα, δηλαδή, δεν μπορούν να εξαχθούν περισσότερες πληροφορίες.

Το πρόβλημα με αυτόν τον τύπο μοντέλου είναι ότι δεν έχει μνήμη. Σημαίνει ότι η είσοδος και η έξοδος είναι ανεξάρτητες. Με άλλα λόγια, το μοντέλο δεν ενδιαφέρεται για το τι προηγήθηκε. Εγείρει κάποιο ερώτημα όταν χρειάζεται να προβλέψετε χρονοσειρές ή προτάσεις, επειδή το δίκτυο πρέπει να έχει πληροφορίες σχετικά με τα ιστορικά δεδομένα ή τις προηγούμενες λέξεις.

Για να ξεπεραστεί αυτό το ζήτημα, έχει αναπτυχθεί ένας νέος τύπος αρχιτεκτονικής: Επαναλαμβανόμενο νευρωνικό δίκτυο (RNN εφεξής)

Τι είναι ένα επαναλαμβανόμενο νευρωνικό δίκτυο (RNN);

A Επαναλαμβανόμενο νευρωνικό δίκτυο (RNN) είναι μια κατηγορία του Τεχνητό Νευρωνικό Δίκτυο στο οποίο η σύνδεση μεταξύ διαφορετικών κόμβων σχηματίζει ένα κατευθυνόμενο γράφημα για να δώσει μια χρονική δυναμική συμπεριφορά. Βοηθά στη μοντελοποίηση διαδοχικών δεδομένων που προέρχονται από δίκτυα προώθησης. Λειτουργεί παρόμοια με τον ανθρώπινο εγκέφαλο για να παρέχει προγνωστικά αποτελέσματα.

Ένα επαναλαμβανόμενο νευρωνικό δίκτυο μοιάζει αρκετά με ένα παραδοσιακό νευρωνικό δίκτυο εκτός από το ότι προστίθεται μια κατάσταση μνήμης στους νευρώνες. Ο υπολογισμός για τη συμπερίληψη μνήμης είναι απλός.

Φανταστείτε ένα απλό μοντέλο με μόνο έναν νευρώνα που τροφοδοτείται από μια παρτίδα δεδομένων. Σε ένα παραδοσιακό νευρωνικό δίκτυο, το μοντέλο παράγει την έξοδο πολλαπλασιάζοντας την είσοδο με το βάρος και τη συνάρτηση ενεργοποίησης. Με ένα RNN, αυτή η έξοδος αποστέλλεται πίσω στον εαυτό της πολλές φορές. Καλούμε χρονικό βήμα το χρονικό διάστημα που η έξοδος γίνεται η είσοδος του επόμενου πολλαπλασιασμού του πίνακα.

Για παράδειγμα, στην παρακάτω εικόνα, μπορείτε να δείτε ότι το δίκτυο αποτελείται από έναν νευρώνα. Το δίκτυο υπολογίζει τον πολλαπλασιασμό των πινάκων μεταξύ της εισόδου και του βάρους και προσθέτει μη γραμμικότητα με τη συνάρτηση ενεργοποίησης. Γίνεται η έξοδος στο t-1. Αυτή η έξοδος είναι η είσοδος του δεύτερου πολλαπλασιασμού του πίνακα.

Επαναλαμβανόμενο νευρωνικό δίκτυο (RNN)
Επαναλαμβανόμενο νευρωνικό δίκτυο (RNN)

Παρακάτω, κωδικοποιούμε ένα απλό RNN στο TensorFlow για να κατανοήσουμε το βήμα και επίσης το σχήμα της εξόδου.

Το δίκτυο αποτελείται από:

  • Τέσσερις είσοδοι
  • Έξι νευρώνες
  • 2-χρονικά βήματα

Το δίκτυο θα προχωρήσει όπως φαίνεται στην παρακάτω εικόνα.

Επαναλαμβανόμενο νευρωνικό δίκτυο (RNN)

Το δίκτυο ονομάζεται «επαναλαμβανόμενο» επειδή εκτελεί την ίδια λειτουργία σε κάθε τετράγωνο ενεργοποίησης. Το δίκτυο υπολόγισε τα βάρη των εισόδων και της προηγούμενης εξόδου πριν χρησιμοποιήσει μια συνάρτηση ενεργοποίησης.

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

Μπορούμε να δημιουργήσουμε το δίκτυο με ένα σύμβολο κράτησης θέσης για τα δεδομένα, το επαναλαμβανόμενο στάδιο και την έξοδο.

  1. Καθορίστε το σύμβολο κράτησης θέσης για τα δεδομένα
X = tf.placeholder(tf.float32, [None, n_timesteps, n_inputs])

Εδώ:

  • Κανένα: Άγνωστο και θα πάρει το μέγεθος της παρτίδας
  • n_timesteps: Πόσες φορές το δίκτυο θα στείλει την έξοδο πίσω στον νευρώνα
  • n_inputs: Αριθμός εισροών ανά παρτίδα
  1. Καθορίστε το επαναλαμβανόμενο δίκτυο

Όπως αναφέρθηκε στην παραπάνω εικόνα, το δίκτυο αποτελείται από 6 νευρώνες. Το δίκτυο θα υπολογίσει δύο κουκκίδες:

  • Εισαγάγετε δεδομένα με το πρώτο σύνολο βαρών (δηλαδή, 6: ίσο με τον αριθμό των νευρώνων)
  • Προηγούμενη έξοδος με ένα δεύτερο σύνολο βαρών (δηλαδή, 6: που αντιστοιχεί στον αριθμό εξόδου)

Σημειώστε ότι, κατά τη διάρκεια της πρώτης προώθησης, οι τιμές της προηγούμενης εξόδου είναι ίσες με μηδενικά, επειδή δεν έχουμε καμία διαθέσιμη τιμή.

Το αντικείμενο για τη δημιουργία ενός RNN είναι tf.contrib.rnn.BasicRNNCcell με το όρισμα num_units για τον καθορισμό του αριθμού εισόδου

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

Τώρα που έχει οριστεί το δίκτυο, μπορείτε να υπολογίσετε τις εξόδους και τις καταστάσεις

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

Αυτό το αντικείμενο χρησιμοποιεί έναν εσωτερικό βρόχο για να πολλαπλασιάσει τους πίνακες τον κατάλληλο αριθμό φορών.

Σημειώστε ότι ο επαναλαμβανόμενος νευρώνας είναι συνάρτηση όλων των εισόδων των προηγούμενων χρονικών βημάτων. Έτσι το δίκτυο χτίζει τη δική του μνήμη. Οι πληροφορίες από την προηγούμενη φορά μπορούν να διαδοθούν στο μέλλον. Αυτή είναι η μαγεία του Recurrent νευρωνικού δικτύου

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

Για επεξηγηματικούς σκοπούς, εκτυπώνετε τις τιμές της προηγούμενης κατάστασης. Η έξοδος που εκτυπώθηκε παραπάνω δείχνει την έξοδο από την τελευταία κατάσταση. Τώρα εκτυπώστε όλη την έξοδο, μπορείτε να παρατηρήσετε ότι οι καταστάσεις είναι η προηγούμενη έξοδος κάθε παρτίδας. Δηλαδή η προηγούμενη έξοδος περιέχει τις πληροφορίες για ολόκληρη την ακολουθία.ε

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)

Επαναλαμβανόμενο νευρωνικό δίκτυο (RNN)

Η έξοδος έχει το σχήμα (3, 2, 6):

  • 3: Αριθμός παρτίδων
  • 2: Αριθμός χρονικού βήματος
  • 6: Αριθμός νευρώνων

Η βελτιστοποίηση ενός επαναλαμβανόμενου νευρωνικού δικτύου είναι πανομοιότυπη με ένα παραδοσιακό νευρωνικό δίκτυο. Θα δείτε με περισσότερες λεπτομέρειες πώς να κωδικοποιήσετε τη βελτιστοποίηση στο επόμενο μέρος αυτού του σεμιναρίου για το περιοδικό νευρωνικό δίκτυο.

Εφαρμογές RNN

Το RNN έχει πολλαπλές χρήσεις, ειδικά όταν πρόκειται για την πρόβλεψη του μέλλοντος. Στον χρηματοπιστωτικό κλάδο, το RNN μπορεί να είναι χρήσιμο στην πρόβλεψη των τιμών των μετοχών ή του πρόσημου της κατεύθυνσης της χρηματιστηριακής αγοράς (δηλαδή, θετικό ή αρνητικό).

Το RNN είναι χρήσιμο για ένα αυτόνομο αυτοκίνητο καθώς μπορεί να αποφύγει ένα τροχαίο ατύχημα προβλέποντας την τροχιά του οχήματος.

Το RNN χρησιμοποιείται ευρέως στην ανάλυση κειμένου, τη δημιουργία λεζάντας εικόνων, την ανάλυση συναισθημάτων και τη μηχανική μετάφραση. Για παράδειγμα, μπορεί κανείς να χρησιμοποιήσει μια κριτική ταινίας για να καταλάβει το συναίσθημα που αντιλήφθηκε ο θεατής μετά την παρακολούθηση της ταινίας. Η αυτοματοποίηση αυτής της εργασίας είναι πολύ χρήσιμη όταν η εταιρεία ταινιών δεν έχει αρκετό χρόνο για να ελέγξει, να επισημάνει, να ενοποιήσει και να αναλύσει τις κριτικές. Το μηχάνημα μπορεί να κάνει τη δουλειά με υψηλότερο επίπεδο ακρίβειας.

Περιορισμοί του RNN

Θεωρητικά, το RNN υποτίθεται ότι μεταφέρει τις πληροφορίες μέχρι και πολλές φορές. Ωστόσο, είναι αρκετά δύσκολο να διαδοθούν όλες αυτές οι πληροφορίες όταν το χρονικό βήμα είναι πολύ μεγάλο. Όταν ένα δίκτυο έχει πάρα πολλά βαθιά στρώματα, γίνεται μη εκπαιδεύσιμο. Αυτό το πρόβλημα ονομάζεται: εξαφανισμένο πρόβλημα διαβάθμισης. Αν θυμάστε, το νευρωνικό δίκτυο ενημερώνει το βάρος χρησιμοποιώντας τον αλγόριθμο gradient descent. Οι κλίσεις γίνονται μικρότερες όταν το δίκτυο προχωρά σε χαμηλότερα επίπεδα.

Συμπερασματικά, οι κλίσεις παραμένουν σταθερές που σημαίνει ότι δεν υπάρχει χώρος για βελτίωση. Το μοντέλο μαθαίνει από μια αλλαγή στην κλίση. αυτή η αλλαγή επηρεάζει την έξοδο του δικτύου. Ωστόσο, εάν η διαφορά στη διαβάθμιση είναι πολύ μικρή (δηλαδή, τα βάρη αλλάζουν λίγο), το δίκτυο δεν μπορεί να μάθει τίποτα και έτσι η έξοδος. Επομένως, ένα δίκτυο που αντιμετωπίζει ένα πρόβλημα κλίσης που εξαφανίζεται δεν μπορεί να συγκλίνει προς μια καλή λύση.

Βελτίωση LSTM

Για να ξεπεραστεί το πιθανό πρόβλημα της εξαφάνισης της κλίσης που αντιμετωπίζει το RNN, τρεις ερευνητές, οι Hochreiter, Schmidhuber και Bengio βελτίωσαν το RNN με μια αρχιτεκτονική που ονομάζεται Long Short-Term Memory (LSTM). Εν συντομία, το LSMT παρέχει στο δίκτυο σχετικές προηγούμενες πληροφορίες για πιο πρόσφατους χρόνους. Το μηχάνημα χρησιμοποιεί καλύτερη αρχιτεκτονική για την επιλογή και τη μεταφορά πληροφοριών σε μεταγενέστερο χρόνο.

Η αρχιτεκτονική LSTM είναι διαθέσιμη στο TensorFlow, tf.contrib.rnn.LSTMCell. Το LSTM είναι εκτός του πεδίου εφαρμογής του σεμιναρίου. Μπορείτε να απευθυνθείτε στον επίσημο τεκμηρίωση για περισσότερες πληροφορίες

RNN σε χρονοσειρές

Σε αυτό το σεμινάριο TensorFlow RNN, θα χρησιμοποιήσετε ένα RNN με δεδομένα χρονοσειρών. Οι χρονικές σειρές εξαρτώνται από τον προηγούμενο χρόνο, πράγμα που σημαίνει ότι οι προηγούμενες τιμές περιλαμβάνουν σχετικές πληροφορίες από τις οποίες μπορεί να μάθει το δίκτυο. Η ιδέα πίσω από την πρόβλεψη χρονοσειρών είναι να εκτιμηθεί η μελλοντική αξία μιας σειράς, ας πούμε, η τιμή της μετοχής, η θερμοκρασία, το ΑΕΠ και ούτω καθεξής.

Η προετοιμασία δεδομένων για Keras RNN και χρονοσειρές μπορεί να είναι λίγο δύσκολη. Πρώτα απ 'όλα, ο στόχος είναι να προβλέψετε την επόμενη τιμή της σειράς, που σημαίνει ότι θα χρησιμοποιήσετε τις προηγούμενες πληροφορίες για να υπολογίσετε την τιμή στο t + 1. Η ετικέτα είναι ίση με την ακολουθία εισόδου και μετατοπίστηκε μια περίοδος μπροστά. Δεύτερον, ο αριθμός εισόδου ορίζεται σε 1, δηλαδή, μία παρατήρηση ανά φορά. Τέλος, το χρονικό βήμα είναι ίσο με την ακολουθία της αριθμητικής τιμής. Για παράδειγμα, εάν ορίσετε το χρονικό βήμα στο 10, η ακολουθία εισόδου θα επιστρέψει δέκα συνεχόμενες φορές.

Κοιτάξτε το παρακάτω γράφημα, έχουμε αναπαραστήσει τα δεδομένα χρονοσειρών στα αριστερά και μια εικονική ακολουθία εισόδου στα δεξιά. Δημιουργείτε μια συνάρτηση για να επιστρέψετε ένα σύνολο δεδομένων με τυχαία τιμή για κάθε ημέρα από τον Ιανουάριο του 2001 έως τον Δεκέμβριο του 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)

Παραγωγή

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 σε χρονολογική σειρά

Το δεξί μέρος του γραφήματος δείχνει όλες τις σειρές. Ξεκίνησε από το 2001 και τελειώνει το 2019 Δεν έχει νόημα να τροφοδοτείτε όλα τα δεδομένα στο δίκτυο, αντίθετα, πρέπει να δημιουργήσετε μια παρτίδα δεδομένων με μήκος ίσο με το χρονικό βήμα. Αυτή η παρτίδα θα είναι η μεταβλητή Χ. Η μεταβλητή Y είναι ίδια με το X, αλλά μετατοπίζεται κατά μία περίοδο (δηλαδή, θέλετε να προβλέψετε t+1).

Και τα δύο διανύσματα έχουν το ίδιο μήκος. Μπορείτε να το δείτε στο δεξιό μέρος του παραπάνω γραφήματος. Η γραμμή αντιπροσωπεύει τις δέκα τιμές της εισαγωγής X, ενώ οι κόκκινες κουκκίδες είναι οι δέκα τιμές της ετικέτας, Y. Σημειώστε ότι, η ετικέτα ξεκινά μια περίοδο πριν από το X και τελειώνει μια περίοδο μετά.

Δημιουργήστε ένα RNN για την πρόβλεψη χρονοσειρών στο TensorFlow

Τώρα σε αυτήν την εκπαίδευση RNN, ήρθε η ώρα να δημιουργήσετε το πρώτο σας RNN για να προβλέψετε την παραπάνω σειρά. Πρέπει να καθορίσετε ορισμένες υπερπαράμετρους (τις παραμέτρους του μοντέλου, δηλαδή, τον αριθμό των νευρώνων, κ.λπ.) για το μοντέλο:

  • Αριθμός εισόδου: 1
  • Χρονικό βήμα (παράθυρα σε χρονοσειρές): 10
  • Αριθμός νευρώνων: 120
  • Αριθμός εξόδου: 1

Το δίκτυό σας θα μάθει από μια ακολουθία 10 ημερών και θα περιέχει 120 επαναλαμβανόμενους νευρώνες. Τροφοδοτείτε το μοντέλο με μία είσοδο, δηλαδή μια μέρα. Μη διστάσετε να αλλάξετε τις τιμές για να δείτε εάν το μοντέλο βελτιώθηκε.

Πριν να κατασκευάσετε το μοντέλο, πρέπει να χωρίσετε το σύνολο δεδομένων σε ένα σύνολο αμαξοστοιχίας και ένα σύνολο δοκιμής. Το πλήρες σύνολο δεδομένων έχει 222 σημεία δεδομένων. Θα χρησιμοποιήσετε τους πρώτους 201 βαθμούς για να εκπαιδεύσετε το μοντέλο και τους τελευταίους 21 βαθμούς για να δοκιμάσετε το μοντέλο σας.

Αφού ορίσετε ένα σύνολο τρένου και δοκιμής, πρέπει να δημιουργήσετε ένα αντικείμενο που να περιέχει τις παρτίδες. Σε αυτές τις παρτίδες, έχετε τιμές Χ και τιμές Υ. Θυμηθείτε ότι οι τιμές Χ υστερούν κατά μία περίοδο. Επομένως, χρησιμοποιείτε τις πρώτες 200 παρατηρήσεις και το χρονικό βήμα είναι ίσο με 10. Το αντικείμενο X_batches θα πρέπει να περιέχει 20 παρτίδες μεγέθους 10*1. Το y_batches έχει το ίδιο σχήμα με το αντικείμενο X_batches αλλά με μία τελεία μπροστά.

Βήμα 1) Δημιουργήστε το τρένο και δοκιμάστε

Πρώτα απ 'όλα, μετατρέπετε τη σειρά σε α πολλοί παράταξη; Στη συνέχεια, ορίζετε τα παράθυρα (δηλαδή, τον αριθμό του χρόνου από τον οποίο θα μάθει το δίκτυο), τον αριθμό εισόδου, εξόδου και το μέγεθος του συνόλου της αμαξοστοιχίας όπως φαίνεται στο παράδειγμα του TensorFlow RNN παρακάτω.

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

Μετά από αυτό, απλά χωρίζετε τον πίνακα σε δύο σύνολα δεδομένων.

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

Βήμα 2) Δημιουργήστε τη συνάρτηση για επιστροφή X_batches και y_batches

Για να το κάνετε πιο εύκολο, μπορείτε να δημιουργήσετε μια συνάρτηση που επιστρέφει δύο διαφορετικούς πίνακες, έναν για X_batches και έναν για y_batches.

Ας γράψουμε μια συνάρτηση RNN TensorFlow για την κατασκευή των παρτίδων.

Σημειώστε ότι, οι παρτίδες Χ υστερούν κατά μία περίοδο (λαμβάνουμε την τιμή t-1). Η έξοδος της συνάρτησης πρέπει να έχει τρεις διαστάσεις. Οι πρώτες διαστάσεις ισούνται με τον αριθμό των παρτίδων, η δεύτερη το μέγεθος των παραθύρων και η τελευταία με τον αριθμό των εισροών.

Το δύσκολο κομμάτι είναι να επιλέξετε σωστά τα σημεία δεδομένων. Για τα σημεία δεδομένων Χ, επιλέγετε τις παρατηρήσεις από t = 1 έως t = 200, ενώ για το σημείο δεδομένων Y, επιστρέφετε τις παρατηρήσεις από t = 2 στο 201. Μόλις έχετε τα σωστά σημεία δεδομένων, είναι εύκολο να αναδιαμορφώσετε η σειρά.

Για να δημιουργήσετε το αντικείμενο με τις παρτίδες, πρέπει να χωρίσετε το σύνολο δεδομένων σε δέκα παρτίδες ίσου μήκους (δηλ. 20). Μπορείτε να χρησιμοποιήσετε τη μέθοδο ανασχηματισμού και να περάσετε το -1 έτσι ώστε η σειρά να είναι παρόμοια με το μέγεθος της παρτίδας. Η τιμή 20 είναι ο αριθμός των παρατηρήσεων ανά παρτίδα και 1 είναι ο αριθμός των εισροών.

Πρέπει να κάνετε το ίδιο βήμα αλλά για την ετικέτα.

Σημειώστε ότι, πρέπει να μετατοπίσετε τα δεδομένα στον αριθμό των φορών που θέλετε να κάνετε πρόβλεψη. Για παράδειγμα, εάν θέλετε να προβλέψετε μία φορά μπροστά, τότε αλλάζετε τη σειρά κατά 1. Εάν θέλετε να κάνετε πρόβλεψη δύο ημερών, μετατοπίστε τα δεδομένα κατά 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

Τώρα που ορίστηκε η συνάρτηση, μπορείτε να την καλέσετε για να δημιουργήσετε τις παρτίδες όπως φαίνεται στο παρακάτω παράδειγμα RNN.

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

Μπορείτε να εκτυπώσετε το σχήμα για να βεβαιωθείτε ότι οι διαστάσεις είναι σωστές.

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

Πρέπει να δημιουργήσετε το δοκιμαστικό σύνολο με μόνο μία παρτίδα δεδομένων και 20 παρατηρήσεις.

Σημειώστε ότι, προβλέπετε ημέρες μετά από ημέρες, σημαίνει ότι η δεύτερη προβλεπόμενη τιμή θα βασίζεται στην πραγματική τιμή της πρώτης ημέρας (t+1) του συνόλου δεδομένων δοκιμής. Στην πραγματικότητα, η πραγματική αξία θα γίνει γνωστή.

Εάν θέλετε να κάνετε πρόβλεψη t+2 (δηλαδή, δύο ημέρες πριν), πρέπει να χρησιμοποιήσετε την προβλεπόμενη τιμή t+1. εάν πρόκειται να προβλέψετε t+3 (τρεις ημέρες πριν), πρέπει να χρησιμοποιήσετε την προβλεπόμενη τιμή t+1 και t+2. Είναι λογικό ότι, είναι δύσκολο να προβλεφθεί με ακρίβεια t+n ημέρες μπροστά.

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)

Εντάξει, το μέγεθος της παρτίδας σας είναι έτοιμο, μπορείτε να δημιουργήσετε την αρχιτεκτονική RNN. Θυμηθείτε, έχετε 120 επαναλαμβανόμενους νευρώνες.

Βήμα 3) Δημιουργήστε το μοντέλο

Για να δημιουργήσετε το μοντέλο, πρέπει να ορίσετε τρία μέρη:

  1. Η μεταβλητή με τους τανυστές
  2. Το RNN
  3. Η απώλεια και η βελτιστοποίηση

Βήμα 3.1) Μεταβλητές

Πρέπει να καθορίσετε τις μεταβλητές X και y με το κατάλληλο σχήμα. Αυτό το βήμα είναι ασήμαντο. Ο τανυστής έχει την ίδια διάσταση με τα αντικείμενα X_batches και y_batches.

Για παράδειγμα, ο τανυστής X είναι ένα σύμβολο κράτησης θέσης (Ελέγξτε το σεμινάριο για την εισαγωγή στο Τάση ροής για να ανανεώσετε το μυαλό σας σχετικά με τη δήλωση μεταβλητής) έχει τρεις διαστάσεις:

  • Σημείωση: μέγεθος της παρτίδας
  • n_windows: Μήκος των παραθύρων. δηλαδή, ο αριθμός των φορών που το μοντέλο κοιτάζει προς τα πίσω
  • n_input: Αριθμός εισόδου

Το αποτέλεσμα είναι:

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

Βήμα 3.2) Δημιουργήστε το RNN

Στο δεύτερο μέρος αυτού του παραδείγματος RNN TensorFlow, πρέπει να ορίσετε την αρχιτεκτονική του δικτύου. Όπως και πριν, χρησιμοποιείτε το αντικείμενο BasicRNNCell και dynamic_rnn από τον εκτιμητή 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)   

Το επόμενο μέρος είναι λίγο πιο δύσκολο, αλλά επιτρέπει ταχύτερους υπολογισμούς. Πρέπει να μετατρέψετε την έξοδο εκτέλεσης σε ένα πυκνό στρώμα και στη συνέχεια να το μετατρέψετε ξανά ώστε να έχει την ίδια διάσταση με την είσοδο.

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.3) Δημιουργήστε την απώλεια και τη βελτιστοποίηση

Η βελτιστοποίηση του μοντέλου εξαρτάται από την εργασία που εκτελείτε. Στο προηγούμενο σεμινάριο σχετικά με CNN, ο στόχος σας ήταν να ταξινομήσετε τις εικόνες, σε αυτό το σεμινάριο RNN, ο στόχος είναι ελαφρώς διαφορετικός. Σας ζητείται να κάνετε μια πρόβλεψη για μια συνεχή μεταβλητή σε σύγκριση με μια τάξη.

Αυτή η διαφορά είναι σημαντική γιατί θα αλλάξει το πρόβλημα βελτιστοποίησης. Το πρόβλημα βελτιστοποίησης για μια συνεχή μεταβλητή είναι η ελαχιστοποίηση του μέσου τετραγώνου σφάλματος. Για να δημιουργήσετε αυτές τις μετρήσεις στο TF, μπορείτε να χρησιμοποιήσετε:

  • tf.reduce_sum(tf.square(έξοδοι – y))

Το υπόλοιπο του κώδικα RNN είναι το ίδιο με πριν. χρησιμοποιείτε ένα Adam optimizer για να μειώσετε την απώλεια (δηλαδή, MSE):

  • tf.train.AdamOptimizer(learning_rate=learning_rate)
  • optimizer.minimize(απώλεια)

Αυτό είναι όλο, μπορείτε να τα μαζέψετε όλα μαζί και το μοντέλο σας είναι έτοιμο για εκπαίδευση.

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

Θα εκπαιδεύσετε το μοντέλο χρησιμοποιώντας 1500 εποχές και θα εκτυπώσετε την απώλεια κάθε 150 επαναλήψεις. Μόλις εκπαιδευτεί το μοντέλο, αξιολογείτε το μοντέλο στο δοκιμαστικό σύνολο και δημιουργείτε ένα αντικείμενο που περιέχει τις προβλέψεις όπως φαίνεται στο παρακάτω παράδειγμα επαναλαμβανόμενου νευρωνικού δικτύου.

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

Επιτέλους, σε αυτό το σεμινάριο RNN Deep Learning, μπορείτε να σχεδιάσετε την πραγματική τιμή της σειράς με την προβλεπόμενη τιμή. Εάν το μοντέλο σας διορθωθεί, οι προβλεπόμενες τιμές θα πρέπει να τοποθετηθούν πάνω από τις πραγματικές τιμές.

Όπως μπορείτε να δείτε, το μοντέλο έχει περιθώρια βελτίωσης. Εναπόκειται σε εσάς να αλλάξετε τις υπερπαραμέτρους όπως τα παράθυρα, το μέγεθος παρτίδας του αριθμού των επαναλαμβανόμενων νευρώνων.

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()
Πρόβλεψη vs Πραγματική

Πρόβλεψη vs Πραγματική

Σύνοψη

Ένα επαναλαμβανόμενο νευρωνικό δίκτυο είναι μια ισχυρή αρχιτεκτονική για την αντιμετώπιση χρονοσειρών ή ανάλυσης κειμένου. Η έξοδος της προηγούμενης κατάστασης είναι ανάδραση για τη διατήρηση της μνήμης του δικτύου με την πάροδο του χρόνου ή την ακολουθία λέξεων.

Στο TensorFlow, μπορείτε να χρησιμοποιήσετε τους ακόλουθους κωδικούς για να εκπαιδεύσετε ένα επαναλαμβανόμενο νευρωνικό δίκτυο TensorFlow για χρονοσειρές:

Παράμετροι του μοντέλου

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

Καθορίστε το μοντέλο

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

Κατασκευάστε τη βελτιστοποίηση

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() 
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})