Урок за RNN (повтаряща се невронна мрежа): Пример за 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.BasicRNNCell с аргумента num_units за определяне на броя на входа

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

Сега, когато мрежата е дефинирана, можете да изчислите изходите и състоянията

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

Този обект използва вътрешен цикъл, за да умножи матриците съответния брой пъти.

Обърнете внимание, че повтарящият се неврон е функция на всички входове от предишните времеви стъпки. Ето как мрежата изгражда своя собствена памет. Информацията от предишното време може да се разпространява в бъдеще време. Това е магията на повтарящата се невронна мрежа

## 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 пренася информацията до пъти. Въпреки това е доста трудно да се разпространява цялата тази информация, когато времевата стъпка е твърде дълга. Когато една мрежа има твърде много дълбоки слоеве, тя става невъзможна за обучение. Този проблем се нарича: проблем с изчезващ градиент. Ако си спомняте, невронната мрежа актуализира теглото, използвайки алгоритъма за градиентно спускане. Градиентите стават по-малки, когато мрежата напредва надолу към по-ниските слоеве.

В заключение, градиентите остават постоянни, което означава, че няма място за подобрение. Моделът се учи от промяна в градиента; тази промяна засяга изхода на мрежата. Въпреки това, ако разликата в градиента е твърде малка (т.е. теглата се променят малко), мрежата не може да научи нищо и съответно изходът. Следователно мрежа, изправена пред проблем с изчезващ градиент, не може да се сближи към добро решение.

Подобрение 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 г. Няма смисъл да подавате всички данни в мрежата, вместо това трябва да създадете пакет от данни с дължина, равна на времевата стъпка. Тази партида ще бъде променливата X. Променливата Y е същата като X, но е изместена с един период (т.е. искате да прогнозирате t+1).

И двата вектора имат еднаква дължина. Можете да го видите в дясната част на горната графика. Линията представлява десетте стойности на входа X, докато червените точки са десетте стойности на етикета Y. Имайте предвид, че етикетът започва един период преди X и завършва един период след това.

Изградете RNN за прогнозиране на времеви редове в TensorFlow

Сега в това обучение за RNN е време да изградите своя първи RNN, за да прогнозирате сериите по-горе. Трябва да зададете някои хиперпараметри (параметрите на модела, т.е. брой неврони и т.н.) за модела:

  • Брой входове: 1
  • Времева стъпка (прозорци във времеви серии): 10
  • Брой неврони: 120
  • Брой изходи: 1

Вашата мрежа ще се учи от последователност от 10 дни и ще съдържа 120 повтарящи се неврони. Захранвате модела с един вход, т.е. един ден. Чувствайте се свободни да промените стойностите, за да видите дали моделът се е подобрил.

Преди да конструирате модела, трябва да разделите набора от данни на набор от влак и тестов набор. Пълният набор от данни има 222 точки от данни; ще използвате първите 201 точки, за да обучите модела и последните 21 точки, за да тествате вашия модел.

След като дефинирате обучаващ и тестов набор, трябва да създадете обект, съдържащ партидите. В тези партиди имате X стойности и Y стойности. Не забравяйте, че стойностите на X са с един период закъснение. Следователно, вие използвате първите 200 наблюдения и времевата стъпка е равна на 10. Обектът X_batches трябва да съдържа 20 партиди с размер 10*1. y_batches има същата форма като обекта X_batches, но с една точка напред.

Стъпка 1) Създайте влака и тествайте

Първо, преобразувате серията в a буца масив; след това дефинирате прозорците (т.е. броя времена, от които мрежата ще се учи), броя на входовете, изходите и размера на набора от влакове, както е показано в примера на 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 за конструиране на партидите.

Имайте предвид, че партидите X са изостанали с един период (приемаме стойност t-1). Резултатът от функцията трябва да има три измерения. Първите размери са равни на броя на партидите, вторият на размера на прозорците и последният на броя на входовете.

Сложната част е да изберете правилно точките от данни. За точките от данни X избирате наблюденията от 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, за да намалите загубата (т.е. MSE):

  • tf.train.AdamOptimizer(learning_rate=learning_rate)
  • optimizer.minimize(loss)

Това е всичко, можете да опаковате всичко заедно и вашият модел е готов за тренировка.

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 можете да начертаете действителната стойност на серията с прогнозираната стойност. Ако вашият модел е коригиран, прогнозираните стойности трябва да се поставят върху действителните стойности.

Както можете да видите, моделът има място за подобрение. От вас зависи да промените хиперпараметрите като прозорците, размера на партидата на броя на повтарящите се неврони.

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()
Прогноза срещу действителност

Прогноза срещу действителност

Oбобщение

Повтарящата се невронна мрежа е стабилна архитектура за работа с времеви серии или анализ на текст. Резултатът от предишното състояние е обратна връзка за запазване на паметта на мрежата във времето или последователност от думи.

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