RNN (Recurrent Neural Network) Tutorial: TensorFlow Eksempel
Hvorfor har vi brug for et tilbagevendende neuralt netværk (RNN)?
Recurrent Neural Network (RNN) giver dig mulighed for at modellere hukommelsesenheder til at bevare data og modellere kortsigtede afhængigheder. Det bruges også i tidsserieprognoser til identifikation af datakorrelationer og -mønstre. Det hjælper også med at producere prædiktive resultater for sekventielle data ved at levere lignende adfærd som en menneskelig hjerne.
Strukturen af et kunstigt neuralt netværk er relativt enkel og handler hovedsageligt om matrixmultiplikation. I løbet af det første trin multipliceres inputs med initialt tilfældige vægte, og bias transformeres med en aktiveringsfunktion, og outputværdierne bruges til at lave en forudsigelse. Dette trin giver en idé om, hvor langt netværket er fra virkeligheden.
Den anvendte metrik er tabet. Jo højere tabsfunktion, jo dummere er modellen. For at forbedre kendskabet til netværket kræves der en vis optimering ved at justere nettets vægte. Den stokastiske gradientnedstigning er den metode, der anvendes til at ændre vægtens værdier i den rigtige retning. Når justeringen er foretaget, kan netværket bruge endnu en batch af data til at teste sin nye viden.
Fejlen er heldigvis lavere end før, men alligevel ikke lille nok. Optimeringstrinnet udføres iterativt, indtil fejlen er minimeret, dvs. der ikke kan udtrækkes mere information.
Problemet med denne type model er, at den ikke har nogen hukommelse. Det betyder, at input og output er uafhængige. Modellen er med andre ord ligeglad med, hvad der kom før. Det rejser nogle spørgsmål, når du skal forudsige tidsserier eller sætninger, fordi netværket skal have information om de historiske data eller tidligere ord.
For at løse dette problem er der udviklet en ny type arkitektur: Recurrent Neural Network (RNN herefter)
Hvad er et tilbagevendende neuralt netværk (RNN)?
A Recurrent Neural Network (RNN) er en klasse af Kunstigt neuralt netværk hvor forbindelsen mellem forskellige noder danner en rettet graf for at give en tidsmæssig dynamisk adfærd. Det hjælper med at modellere sekventielle data, der stammer fra feedforward-netværk. Det fungerer på samme måde som menneskelige hjerner til at levere forudsigelige resultater.
Et tilbagevendende neuralt netværk ligner et traditionelt neuralt netværk, bortset fra at en hukommelsestilstand tilføjes til neuronerne. Beregningen for at inkludere en hukommelse er enkel.
Forestil dig en simpel model med kun én neuron, der fødes af en batch af data. I et traditionelt neuralt net producerer modellen outputtet ved at gange inputtet med vægten og aktiveringsfunktionen. Med en RNN sendes dette output tilbage til sig selv et antal gange. Vi ringer tidstrin den tid, outputtet bliver input til den næste matrixmultiplikation.
For eksempel, på billedet nedenfor, kan du se netværket er sammensat af en neuron. Netværket beregner matrixmultiplikationen mellem input og vægt og tilføjer ikke-linearitet med aktiveringsfunktionen. Det bliver udgangen ved t-1. Dette output er input til den anden matrixmultiplikation.
Nedenfor koder vi en simpel RNN i TensorFlow for at forstå trinnet og også formen på outputtet.
Netværket er sammensat af:
- Fire indgange
- Seks neuroner
- 2-gange trin
Netværket fortsætter som vist på billedet nedenfor.
Netværket kaldes 'tilbagevendende', fordi det udfører den samme operation i hver aktiveret firkant. Netværket beregnede vægten af input og det tidligere output før for at bruge en aktiveringsfunktion.
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 ])
Vi kan bygge netværket med en pladsholder for data, det tilbagevendende trin og output.
- Definer pladsholderen for dataene
X = tf.placeholder(tf.float32, [None, n_timesteps, n_inputs])
Her:
- Ingen: Ukendt og vil tage størrelsen på batchen
- n_timesteps: Antal gange netværket vil sende output tilbage til neuronen
- n_inputs: Antal input pr. batch
- Definer det tilbagevendende netværk
Som nævnt på billedet ovenfor er netværket sammensat af 6 neuroner. Netværket vil beregne produkt med to prikker:
- Inputdata med det første sæt vægte (dvs. 6: lig med antallet af neuroner)
- Tidligere output med et andet sæt vægte (dvs. 6: svarende til antallet af output)
Bemærk, at under den første feedforward, er værdierne af det forrige output lig med nuller, fordi vi ikke har nogen værdi tilgængelig.
Objektet til at bygge et RNN er tf.contrib.rnn.BasicRNNCell med argumentet num_units for at definere antallet af input
basic_cell = tf.contrib.rnn.BasicRNNCell(num_units=n_neurons)
Nu hvor netværket er defineret, kan du beregne output og tilstande
outputs, states = tf.nn.dynamic_rnn(basic_cell, X, dtype=tf.float32)
Dette objekt bruger en intern sløjfe til at gange matricerne det passende antal gange.
Bemærk, at det tilbagevendende neuron er en funktion af alle input fra de foregående tidstrin. Sådan bygger netværket sin egen hukommelse. Oplysningerne fra forrige gang kan forplante sig i fremtidig tid. Dette er magien ved tilbagevendende neurale netværk
## 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]]
Til forklaringsformål udskriver du værdierne for den tidligere tilstand. Outputtet trykt ovenfor viser output fra den sidste tilstand. Udskriv nu alt output, du kan bemærke, at tilstandene er det forrige output for hver batch. Det vil sige, at det forrige output indeholder informationen om hele sekvensen.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)
Outputtet har formen (3, 2, 6):
- 3: Antal partier
- 2: Nummer på tidstrinnet
- 6: Antal neuroner
Optimeringen af et tilbagevendende neuralt netværk er identisk med et traditionelt neuralt netværk. Du vil se mere detaljeret, hvordan du koder optimering i den næste del af denne tutorial om tilbagevendende neuralt netværk.
Ansøgninger af RNN
RNN har flere anvendelser, især når det kommer til at forudsige fremtiden. I den finansielle industri kan RNN være behjælpelig med at forudsige aktiekurser eller tegnet på aktiemarkedets retning (dvs. positiv eller negativ).
RNN er nyttigt for en autonom bil, da det kan undgå en bilulykke ved at forudse køretøjets bane.
RNN er meget brugt i tekstanalyse, billedtekstning, sentimentanalyse og maskinoversættelse. For eksempel kan man bruge en filmanmeldelse til at forstå den følelse, tilskueren opfattede efter at have set filmen. Automatisering af denne opgave er meget nyttig, når filmselskabet ikke har tid nok til at gennemgå, mærke, konsolidere og analysere anmeldelserne. Maskinen kan udføre arbejdet med en højere grad af nøjagtighed.
Begrænsninger af RNN
I teorien formodes RNN at bære informationen op til tider. Det er dog ret udfordrende at udbrede al denne information, når tidstrinnet er for langt. Når et netværk har for mange dybe lag, bliver det utræneligt. Dette problem kaldes: forsvindende gradientproblem. Hvis du husker det, opdaterer det neurale netværk vægten ved hjælp af gradient descent-algoritmen. Gradienterne bliver mindre, når netværket går ned til lavere lag.
Som konklusion forbliver gradienterne konstante, hvilket betyder, at der ikke er plads til forbedringer. Modellen lærer af en ændring i gradienten; denne ændring påvirker netværkets output. Men hvis forskellen i gradienten er for lille (dvs. vægten ændrer sig lidt), kan netværket ikke lære noget, og så outputtet. Derfor kan et netværk, der står over for et forsvindende gradientproblem, ikke konvergere mod en god løsning.
Forbedring LSTM
For at overvinde det potentielle problem med forsvindende gradient, som RNN står over for, forbedrede tre forskere, Hochreiter, Schmidhuber og Bengio RNN med en arkitektur kaldet Long Short-Term Memory (LSTM). Kort sagt giver LSMT netværket relevant tidligere information til nyere tid. Maskinen bruger en bedre arkitektur til at vælge og transportere information tilbage til senere tid.
LSTM-arkitektur er tilgængelig i TensorFlow, tf.contrib.rnn.LSTMCell. LSTM er uden for selvstudiets omfang. Du kan henvise til embedsmanden dokumentation for mere information
RNN i tidsserier
I denne TensorFlow RNN-tutorial skal du bruge en RNN med tidsseriedata. Tidsserier er afhængige af tidligere tid, hvilket betyder, at tidligere værdier inkluderer relevant information, som netværket kan lære af. Ideen bag forudsigelse af tidsserier er at estimere den fremtidige værdi af en serie, lad os sige aktiekurs, temperatur, BNP og så videre.
Dataforberedelsen til Keras RNN og tidsserier kan være en lille smule vanskelig. Først og fremmest er målet at forudsige den næste værdi af serien, hvilket betyder, at du vil bruge den tidligere information til at estimere værdien ved t + 1. Etiketten er lig med inputsekvensen og flyttet en periode frem. For det andet sættes antallet af input til 1, dvs. én observation pr. gang. Endelig er tidstrinnet lig med rækkefølgen af den numeriske værdi. For eksempel, hvis du indstiller tidstrinnet til 10, vil inputsekvensen returnere ti på hinanden følgende gange.
Se på grafen nedenfor, vi har repræsenteret tidsseriedata til venstre og en fiktiv inputsekvens til højre. Du opretter en funktion til at returnere et datasæt med tilfældig værdi for hver dag fra januar 2001 til december 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)
Produktion
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()
Den højre del af grafen viser alle serier. Det startede fra 2001 og slutter i 2019. Det giver ingen mening at fodre alle data i netværket, i stedet skal du oprette en batch af data med en længde svarende til tidstrinnet. Denne batch vil være X-variablen. Y-variablen er den samme som X, men forskudt med én periode (dvs. du ønsker at forudsige t+1).
Begge vektorer har samme længde. Du kan se det i højre del af ovenstående graf. Linjen repræsenterer de ti værdier af X-inputtet, mens de røde prikker er de ti værdier af etiketten, Y. Bemærk, at etiketten starter en periode foran X og slutter en periode efter.
Byg en RNN til at forudsige tidsserier i TensorFlow
Nu i denne RNN-træning er det tid til at bygge dit første RNN til at forudsige serien ovenfor. Du skal angive nogle hyperparametre (modellens parametre, dvs. antal neuroner osv.) for modellen:
- Antal input: 1
- Tidstrin (vinduer i tidsserier): 10
- Antal neuroner: 120
- Antal output: 1
Dit netværk vil lære af en sekvens på 10 dage og indeholde 120 tilbagevendende neuroner. Du fodrer modellen med ét input, dvs. én dag. Du er velkommen til at ændre værdierne for at se, om modellen er blevet bedre.
Før du konstruerer modellen, skal du opdele datasættet i et togsæt og testsæt. Det fulde datasæt har 222 datapunkter; du skal bruge de første 201 point til at træne modellen og de sidste 21 point til at teste din model.
Når du har defineret et tog- og testsæt, skal du oprette et objekt, der indeholder batchene. I denne batches har du X-værdier og Y-værdier. Husk, at X-værdierne er en periode forsinket. Derfor bruger du de første 200 observationer og tidstrinnet er lig med 10. X_batches objektet skal indeholde 20 batches af størrelsen 10*1. y_batches har samme form som X_batches objektet, men med en periode forud.
Trin 1) Opret toget og test
Først og fremmest konverterer du serien til en bedøvet matrix; derefter definerer du vinduerne (dvs. antallet af gange netværket vil lære af), antallet af input, output og størrelsen på togsættet som vist i TensorFlow RNN-eksemplet nedenfor.
series = np.array(ts) n_windows = 20 n_input = 1 n_output = 1 size_train = 201
Derefter opdeler du simpelthen arrayet i to datasæt.
## Split data train = series[:size_train] test = series[size_train:] print(train.shape, test.shape) (201,) (21,)
Trin 2) Opret funktionen til at returnere X_batches og y_batches
For at gøre det nemmere kan du oprette en funktion, der returnerer to forskellige arrays, en for X_batches og en for y_batches.
Lad os skrive en RNN TensorFlow-funktion til at konstruere batchene.
Bemærk, at X-batcherne er forsinket med én periode (vi tager værdien t-1). Funktionens output skal have tre dimensioner. De første dimensioner svarer til antallet af partier, den anden størrelsen af vinduerne og den sidste er antallet af input.
Den vanskelige del er at vælge datapunkterne korrekt. For X-datapunkterne vælger du observationerne fra t = 1 til t =200, mens du for Y-datapunktet returnerer observationerne fra t = 2 til 201. Når først du har de rigtige datapunkter, er det ligetil at omforme serien.
For at konstruere objektet med batcherne skal du opdele datasættet i ti batches af samme længde (dvs. 20). Du kan bruge omformningsmetoden og sende -1, så serien svarer til batchstørrelsen. Værdien 20 er antallet af observationer pr. batch og 1 er antallet af input.
Du skal gøre det samme trin undtagen for etiketten.
Bemærk, at du skal flytte dataene til det antal gange, du vil prognose. For eksempel, hvis du vil forudsige én tid frem, så flytter du serien med 1. Hvis du vil forudse to dage, skal du flytte dataene med 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
Nu hvor funktionen er defineret, kan du kalde den for at oprette batcherne som vist i nedenstående RNN-eksempel.
X_batches, y_batches = create_batches(df = train, windows = n_windows, input = n_input, output = n_output)
Du kan udskrive formen for at sikre dig, at dimensionerne er korrekte.
print(X_batches.shape, y_batches.shape) (10, 20, 1) (10, 20, 1)
Du skal oprette testsættet med kun én batch af data og 20 observationer.
Bemærk, at du forudsiger dage efter dage, betyder det, at den anden forudsagte værdi vil være baseret på den sande værdi af den første dag (t+1) af testdatasættet. Faktisk vil den sande værdi være kendt.
Hvis du ønsker at forudsige t+2 (dvs. to dage frem), skal du bruge den forudsagte værdi t+1; hvis du skal forudsige t+3 (tre dage frem), skal du bruge den forudsagte værdi t+1 og t+2. Det giver mening, at det er svært at forudsige præcist t+n dage frem.
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)
Okay, din batchstørrelse er klar, du kan bygge RNN-arkitekturen. Husk, du har 120 tilbagevendende neuroner.
Trin 3) Byg modellen
For at oprette modellen skal du definere tre dele:
- Variablen med tensorerne
- RNN
- Tabet og optimeringen
Trin 3.1) Variabler
Du skal angive X- og y-variablerne med den passende form. Dette trin er trivielt. Tensoren har samme dimension som objekterne X_batches og y_batches.
For eksempel er tensoren X en pladsholder (tjek selvstudiet om Introduktion til Tensorflow for at genopfriske dit sind om variabel deklaration) har tre dimensioner:
- Bemærk: batchens størrelse
- n_windows: Længde på vinduerne. dvs. antallet af gange, modellen kigger bagud
- n_input: Antal input
Resultatet er:
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])
Trin 3.2) Opret RNN
I den anden del af dette RNN TensorFlow-eksempel skal du definere netværkets arkitektur. Som før bruger du objektet BasicRNNCell og dynamic_rnn fra TensorFlow estimator.
## 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)
Den næste del er en smule vanskeligere, men tillader hurtigere beregning. Du skal transformere kørselsoutputtet til et tæt lag og derefter konvertere det igen for at have samme dimension som inputtet.
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])
Trin 3.3) Skab tabet og optimeringen
Modeloptimeringen afhænger af den opgave, du udfører. I den forrige tutorial vedr CNN, dit mål var at klassificere billeder, i denne RNN-tutorial er målet lidt anderledes. Du bliver bedt om at lave en forudsigelse på en kontinuert variabel sammenlignet med en klasse.
Denne forskel er vigtig, fordi den vil ændre optimeringsproblemet. Optimeringsproblemet for en kontinuert variabel er at minimere den gennemsnitlige kvadratiske fejl. For at konstruere disse metrics i TF kan du bruge:
- tf.reduce_sum(tf.square(output – y))
Resten af RNN-koden er den samme som før; du bruger en Adam optimizer til at reducere tabet (dvs. MSE):
- tf.train.AdamOptimizer(learning_rate=learning_rate)
- optimizer.minimize(tab)
Det er det, du kan pakke alt sammen, og din model er klar til at træne.
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()
Du træner modellen ved at bruge 1500 epoker og udskriver tabet hver 150 iterationer. Når modellen er trænet, evaluerer du modellen på testsættet og opretter et objekt, der indeholder forudsigelserne som vist i nedenstående eksempel på Recurrent Neural Network.
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
Endelig i denne RNN Deep Learning-tutorial kan du plotte den faktiske værdi af serien med den forudsagte værdi. Hvis din model er rettet, skal de forudsagte værdier sættes oven på de faktiske værdier.
Som du kan se, har modellen plads til forbedringer. Det er op til dig at ændre hyperparametrene som windows, batchstørrelsen af antallet af tilbagevendende neuroner.
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()
Resumé
Et tilbagevendende neuralt netværk er en robust arkitektur til at håndtere tidsserier eller tekstanalyse. Outputtet fra den tidligere tilstand er feedback for at bevare netværkets hukommelse over tid eller sekvens af ord.
I TensorFlow kan du bruge følgende koder til at træne et TensorFlow Recurrent Neural Network til tidsserier:
Parametre for modellen
n_windows = 20 n_input = 1 n_output = 1 size_train = 201
Definer modellen
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])
Konstruer optimeringen
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)
Træn modellen
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})