Учебное пособие по RNN (рекуррентной нейронной сети): пример TensorFlow

⚡ Умное резюме

Рекуррентные нейронные сети добавляют состояние памяти к обычным нейронам, передавая каждый выходной сигнал обратно в качестве следующего входного, чтобы модель могла обучаться на основе порядка. В этом пошаговом руководстве показана реализация такой сети в TensorFlow и прогнозирование временного ряда.

  • 🔘 Состояние памяти: Каждый рекуррентный нейрон получает предыдущий выходной сигнал наряду с новым входным сигналом, что и обеспечивает сети временную осведомленность.
  • ☑️ Форма вывода: Запуск тестовой сети возвращает тензор (3, 2, 6): пакеты данных, временные шаги и нейроны в указанном порядке.
  • Правило пакетной обработки: Входные данные временных рядов преобразуются в трехмерное пространство, а массив меток представляет собой тот же ряд, сдвинутый на один период вперед.
  • 🧪 Модель скелета: В качестве заполнителей используются BasicRNNCell, обернутый в dynamic_rnn, плотная проекция, а затем среднеквадратичная ошибка с оптимизатором Adam.
  • 🇧🇷 Тренировочный забег: 1,500 эпох на 120 рекуррентных нейронах приводят к уменьшению ошибки с 502 893 до примерно 1,385.
  • 📉 Известный предел: Длинные последовательности вызывают проблему затухания градиента, для решения которой были разработаны LSTM и их вентильные варианты.

RNN (Рекуррентная нейронная сеть)

Зачем нам нужна рекуррентная нейронная сеть (RNN)?

Рекуррентная нейронная сеть (RNN) позволяет моделировать блоки памяти для сохранения данных и моделирования краткосрочных зависимостей. Он также используется при прогнозировании временных рядов для выявления корреляций и закономерностей данных. Это также помогает получать результаты прогнозирования для последовательных данных, обеспечивая поведение, аналогичное человеческому мозгу.

Структура Искусственная нейронная сеть Это относительно простая модель, в основном основанная на умножении матриц. На первом этапе входные данные умножаются на изначально случайные веса и смещение, преобразованные с помощью функции активации, а выходные значения используются для прогнозирования. Этот шаг позволяет оценить, насколько сеть отличается от реальности.

Применяемая метрика – это потери. Чем выше функция потерь, тем глупее модель. Чтобы улучшить знание сети, необходима некоторая оптимизация путем корректировки весов сети. Стохастический градиентный спуск — это метод, используемый для изменения значений весов в правильном направлении. После внесения корректировок сеть может использовать еще один пакет данных для проверки своих новых знаний.

К счастью, ошибка меньше, чем раньше, но всё ещё недостаточно мала. Этап оптимизации выполняется итеративно до тех пор, пока ошибка не будет минимизирована, то есть пока не станет невозможно получить дополнительную информацию.tracТед.

Проблема с моделями этого типа в том, что у них нет памяти. Это означает, что вход и выход независимы. Другими словами, модель не заботится о том, что было раньше. Возникает некоторый вопрос, когда вам нужно предсказать временные ряды или предложения, поскольку сети необходима информация об исторических данных или прошлых словах.

Чтобы решить эту проблему, был разработан новый тип архитектуры: рекуррентная нейронная сеть (далее RNN).

Что такое рекуррентная нейронная сеть (RNN)?

Рекуррентная нейронная сеть (РНН) — это класс искусственных нейронных сетей, в которых связи между различными узлами образуют ориентированный граф, обеспечивающий динамическое поведение во времени. Она помогает моделировать последовательные данные, полученные из сетей прямого распространения. Она работает аналогично человеческому мозгу, выдавая прогнозные результаты.

Рекуррентная нейронная сеть очень похожа на традиционную нейронную сеть, за исключением того, что к нейронам добавляется состояние памяти. Вычисление включения памяти простое.

Представьте себе простую модель всего с одним нейроном, получающим на вход пакет данных. В традиционной нейронной сети модель выдает результат, умножая входные данные на вес и функцию активации. В рекуррентной нейронной сети этот результат возвращается сам себе определённое количество раз. Мы называем это шаг времени Время, в течение которого выходные данные становятся входными данными для следующего матричного умножения.

Например, на рисунке ниже вы можете видеть, что сеть состоит из одного нейрона. Сеть вычисляет умножение матриц между входными данными и весом и добавляет нелинейность с помощью функции активации. Он становится выходом в момент t-1. Этот вывод является входом второго матричного умножения.

Одиночный рекуррентный нейрон отправляет свой выходной сигнал в момент времени t-1 обратно в качестве входного сигнала для следующего умножения.

Рекуррентная нейронная сеть (RNN)

Ниже мы кодируем простую RNN в TensorFlow, чтобы понять шаг, а также форму выходных данных.

Сеть состоит из:

  • Четыре входа
  • Шесть нейронов
  • 2-кратные шаги

Сеть будет работать, как показано на рисунке ниже.

Развернутая рекуррентная нейронная сеть с четырьмя входами, шестью нейронами и двумя временными шагами.

Сеть называется «рекуррентной», потому что она выполняет одну и ту же операцию в каждом квадрате активации. Прежде чем использовать функцию активации, сеть вычислила веса входных данных и предыдущих выходных данных.

Примечание к версии: Код в этом руководстве ориентирован на API графов TensorFlow 1.x. В TensorFlow 2.x тот же скрипт продолжает работать после выполнения команды. import tensorflow.compat.v1 as tf плюс tf.disable_v2_behavior(), потому что заполнители, сессии и модуль rnn_cell теперь находятся в другом месте. tf.compat.v1. Идиоматический эквивалент версии 2.x — это 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
    ])

Мы можем построить сеть с заполнителем для данных, повторяющимся этапом и выходными данными.

Определите заполнитель для данных

X = tf.placeholder(tf.float32, [None, n_timesteps, n_inputs])

Вот:

  • Нет: Неизвестно и будет соответствовать размеру пакета.
  • n_timesteps: сколько раз сеть отправит выходные данные обратно в нейрон.
  • n_inputs: количество входных данных на пакет

Определить рекуррентную сеть

Как указано на рисунке выше, сеть состоит из 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):

  • 3: Количество партий
  • 2: Номер временного шага
  • 6: Количество нейронов

Оптимизация рекуррентной нейронной сети идентична традиционной нейронной сети. Более подробно вы увидите, как оптимизировать код, в следующей части этого руководства по рекуррентной нейронной сети.

Приложения РНН

RNN имеет множество применений, особенно когда речь идет о предсказании будущего. В финансовой отрасли RNN может быть полезна для прогнозирования цен на акции или знака направления фондового рынка (т. е. положительного или отрицательного).

RNN полезен для беспилотного автомобиля, поскольку он может избежать автомобильной аварии, предугадав траекторию движения транспортного средства.

RNN широко используется в анализе текста, субтитрах к изображениям, анализе настроений и машинном переводе. Например, можно использовать рецензию на фильм, чтобы понять чувства, которые зритель испытал после просмотра фильма. Автоматизация этой задачи очень полезна, когда у кинокомпании недостаточно времени для просмотра, маркировки, консолидации и анализа рецензий. Машина может выполнять работу с более высоким уровнем точности.

Ограничения RNN

Теоретически RNN должен передавать информацию до нескольких раз. Однако довольно сложно распространить всю эту информацию, если временной шаг слишком велик. Когда сеть имеет слишком много глубоких слоев, она становится необучаемой. Эта проблема называется: исчезающая проблема градиента. Если вы помните, нейронная сеть обновляет вес, используя алгоритм градиентного спуска. Градиенты становятся меньше, когда сеть переходит на более низкие уровни.

В заключение, градиенты остаются постоянными, а значит, возможности для улучшения отсутствуют. Модель обучается на основе изменения градиента; это изменение влияет на выходные данные сети. Однако, если разница в градиенте слишком мала (т.е. веса изменяются незначительно), сеть не может ничему научиться, и, следовательно, выходные данные также не улучшаются. Таким образом, сеть, сталкивающаяся с проблемой исчезающего градиента, не может сойтись к хорошему решению.

Улучшение ЛСТМ

Для преодоления потенциальной проблемы затухания градиента, с которой сталкиваются рекуррентные нейронные сети (RNN), три исследователя — Хохрайтер, Шмидхубер и Бенджио — усовершенствовали RNN, используя архитектуру, называемую долговременной кратковременной памятью (LSTM). Вкратце, LSTM предоставляет сети релевантную информацию из прошлого для более позднего времени. Машина использует более совершенную архитектуру для выбора и переноса информации в более поздний период времени.

Архитектура LSTM доступна в TensorFlow, tf.contrib.rnn.LSTMCell. LSTM выходит за рамки данного руководства. Вы можете обратиться к официальной документации. документации для дополнительной информации

В TensorFlow 2.x доступ к этой ячейке осуществляется следующим образом: tf.compat.v1.nn.rnn_cell.LSTMCell, в то время как в новом коде обычно используется tf.keras.layers.LSTM или более светозащищенный tf.keras.layers.GRU, что позволяет достичь сопоставимой точности при меньшем количестве параметров.

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

Слева — сгенерированный временной ряд, справа — десятишаговый обучающий пример со смещенными целевыми значениями.

Правая часть графика показывает все временные ряды. Они начинаются с 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) Создайте поезд и протестируйте

Прежде всего, вы преобразуете серию в NumPy множество; затем вы определяете окна (т. е. количество времени, в течение которого сеть будет учиться), количество входных, выходных данных и размер набора поездов, как показано в примере 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. РНН
  3. Потери и оптимизация

Шаг 3.1) Переменные показатели

Вам необходимо указать переменные X и y соответствующей формы. Этот шаг тривиален. Тензор имеет ту же размерность, что и объекты X_batches и y_batches.

Например, тензор X является заполнителем (см. руководство по этому вопросу). Введение в TensorFlow чтобы освежить ваше представление об объявлении переменных) имеет три измерения:

  • Примечание: размер партии
  • 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 TensorFlow вам необходимо определить архитектуру сети. Как и раньше, вы используете объект BasicRNNCell и динамический_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 такая же, как и раньше; вы используете оптимизатор Адама для уменьшения потерь (т. е. MSE):

tf.train.AdamOptimizer(learning_rate=learning_rate)

оптимизатор.минимизировать(потеря)

Вот и все, вы можете собрать все воедино, и ваша модель готова к обучению.

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

График зависимости прогноза от фактического значения, где зелеными точками показаны фактические значения, а красными — прогнозируемые.

Прогноз против факта

Часто задаваемые вопросы (FAQ)

Начните с окна, охватывающего один полный цикл паттерна, а затем настройте его. Более длинные окна позволяют получить больше контекста, но замедляют обучение и ухудшают затухание градиента. Десять шагов достаточно для ежедневной серии; для еженедельной сезонности обычно требуется больше.

Да, с помощью заглушки. Замените импорт на tensorflow.compat.v1 и вызовите disable_v2_behavior(), поскольку плейсхолдеры, сессии и rnn_cell перемещены в пространство имен compat. Свежий код. TensorFlow В проектах следует использовать tf.keras.layers.SimpleRNN вместо этого.

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

Copilot хорошо справляется с повторяющимися структурами данных: блоками сессий, словарями потоков и периодической печатью данных о потерях. Наиболее рискованной частью остаются формы тензоров и сдвиг меток, поэтому всегда проверяйте размеры пакета самостоятельно, прежде чем доверять сгенерированному циклу.

Рекуррентные слои ожидают (пакет, временной шаг, признак). Преобразование в (-1, окна, вход) сообщает фреймворку, сколько последовательностей существует, насколько далеко назад каждая из них заглядывает и сколько значений поступает на шаге. Отсутствие измерения приводит к ошибке ранжирования.

LSTM использует три вентиля плюс отдельное состояние ячейки; GRU объединяет вентили забывания и ввода и отбрасывает состояние ячейки. GRU обучается быстрее с меньшим количеством параметров, в то время как LSTM часто превосходит GRU при работе с очень длинными зависимостями.

Непрерывные прогнозы минимизируют среднеквадратичную ошибку, как это показано в данном пошаговом руководстве на примере функции reduce_sum of squared residuals. Классификация последовательностей, например, метки настроения или задачи обработки изображений, рассмотренные в [ссылка на руководство]. CNN В этом руководстве используется кросс-энтропия.

Трансформеры доминируют в задачах обработки языков, поскольку механизм внимания распараллеливает последовательность. Рекуррентные модели остаются конкурентоспособными для потоковых сигналов, коротких одномерных прогнозов и устройств с небольшим объемом памяти, где обработка пошагово является преимуществом, а не узким местом.

Подведем итог этой публикации следующим образом: