Что такое рекуррентная нейронная сеть или RNN, как она работает, где ее можно использовать? Эта статья пытается ответить на поставленные выше вопросы. Он также показывает демонстрационную реализацию RNN, используемую для определенной цели, но вы можете обобщить ее для своих нужд.

Секрет производства. Требуются знания Python, CNN. CNN требуется для сравнения, почему и где RNN работает лучше, чем CNN? Не нужно разбираться в математике. Если вы хотите проверить, вернитесь к моей предыдущей статье, чтобы проверить, что такое CNN.

Мы начнем с употребления слова «рекуррентный». Почему это называется рекуррентным? На английском языке слово «повторяющийся» означает:

происходит часто или неоднократно

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

Зачем нам нужна RNN?

Возможно, вам интересно, что у нас есть обычные сети, такие как сверточные, которые работают очень хорошо. Зачем нам нужен другой тип сети? Существует очень специфический вариант использования, когда требуются RNN. Чтобы объяснить RNN, вам нужно сначала понять нечто, называемое последовательностью. Давайте сначала поговорим о последовательностях.

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

CNN обычно не работают хорошо, когда входные данные взаимозависимы в последовательном шаблоне. У CNN нет никакой корреляции между предыдущим вводом и следующим вводом. Таким образом, все выходы независимы. CNN принимает входные и выходные данные на основе обученной модели. Если вы запустите 100 разных входов, ни один из них не будет искажен предыдущим выходом. Но представьте себе такой сценарий, как генерация предложения или перевод текста. Все сгенерированные слова зависят от слов, сгенерированных ранее (в некоторых случаях это зависит и от слов, следующих после, но мы обсудим это позже). Таким образом, вам нужно иметь некоторую предвзятость, основанную на вашем предыдущем выводе. Вот где сияют RNN. В RNN есть некоторая память о том, что произошло ранее в последовательности данных. Это помогает системе получить контекст. Теоретически RNN имеют бесконечную память, что означает, что они могут бесконечно оглядываться назад. Под оглядкой назад я подразумеваю все предыдущие материалы. Но практически они могут оглянуться только на несколько последних шагов. (мы обсудим это позже)

Просто чтобы провести корреляцию с людьми в целом, мы также не принимаем решений на месте. Мы также основываем свои решения на предыдущих знаниях по этому вопросу. (** слишком упрощенно, сложно сказать, что я понимаю даже 0,1% человеческого мозга **)

Где использовать RNN?

RNN можно использовать в самых разных местах. Ниже приведены несколько примеров использования множества RNN.

1. Языковое моделирование и создание текста

Учитывая последовательность слов, здесь мы пытаемся предсказать вероятность следующего слова. Это полезно для перевода, поскольку наиболее вероятным будет правильное предложение.

2. Машинный перевод

При переводе текста с одного языка на другой используется та или иная форма RNN. Все практические дневные системы используют некоторую расширенную версию RNN.

3. Распознавание речи

Предсказание фонетических сегментов на основе входных звуковых волн и, таким образом, формулировка слова.

4. Создание описаний изображений

Очень важный вариант использования - понять, что происходит внутри изображения, поэтому у нас есть хорошее описание. Это работает в сочетании CNN и RNN. CNN выполняет сегментацию, а затем RNN использует сегментированные данные для воссоздания описания. Это элементарно, но возможности безграничны.

5. Добавление тегов к видео

Это можно использовать для поиска видео, где мы делаем описание изображения для видео по кадрам.

Давайте копать глубже!

Мы будем следовать указанной ниже последовательности тем, чтобы закончить документ. Каждый раздел основан на другом, поэтому не воспринимайте это как ссылку.

  1. Сети с прямой связью
  2. Рекуррентные сети
  3. Рецидивирующий нейрон
  4. Обратное распространение во времени (BPTT)
  5. Реализация RNN

Учебник по сетям с прямой связью

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

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

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

Сети с прямой связью не запоминают исторические входные данные во время тестирования, в отличие от повторяющихся сетей.

Решение всегда вовремя. Они запоминают только то, что им показали на этапе обучения.

Рекуррентные сети

С другой стороны, рекуррентные сети принимают в качестве входных данных не только текущий входной пример, который они видят, но также и то, что они воспринимали ранее во времени.

Давайте попробуем построить многослойный перцептрон, чтобы начать с объяснения. Проще говоря, есть входной слой, скрытый слой с определенными активациями и, наконец, мы получаем выход.

Если мы увеличим количество слоев в приведенном выше примере, входной слой будет принимать входные данные. Затем первый скрытый слой выполняет активацию, переходящую на следующие скрытые слои и так далее. Наконец, он достигает выходного уровня, который дает выходные данные. Каждый скрытый слой имеет свои веса и смещения. Теперь вопрос в том, можем ли мы вводить данные в скрытые слои.

Каждый слой имеет свой вес (W), смещения (B), функции активации (F). Эти слои ведут себя по-разному, и с технической точки зрения их сложно объединить. Чтобы их можно было объединить, давайте заменим все слои с одинаковыми весами и смещениями. Это будет выглядеть примерно так.

Теперь мы можем объединить все слои вместе. Все скрытые слои можно объединить в один повторяющийся слой. Итак, они начинают выглядеть примерно так:

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

Забавный анекдот из другой статьи: человека преследуют их дела

Давайте вернемся к проблеме и перефразируем вышеприведенное объяснение на примере, чтобы предсказать, какая буква будет следующей после последовательности букв. Представьте себе слово намаскар. Слово состоит из 8 букв.

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

Если бы мы пытались вычислить 8-ю букву после того, как 7 писем были переданы в сеть, что бы произошло. Скрытый слой прошел бы 8 итераций. Если бы мы развернули сеть, это была бы сеть из 8 слоев, по одному слою для каждой буквы. Итак, вы можете представить, что обычная нейронная сеть повторяется несколько раз. Количество раз, которое вы разворачиваете, напрямую зависит от того, насколько далеко в прошлом он может вспомнить. Но об этом позже.

Рецидивирующий нейрон

Здесь мы более подробно рассмотрим фактический нейрон, который отвечает за принятие решений. Мы будем использовать описанный выше пример намаскара. Мы попытаемся вычислить 8-ю букву, учитывая все предыдущие 7 букв. Общий словарь входных данных составляет {n, a, m, s, k, r}. В реальном мире у вас будут более сложные слова или предложения. Для простоты мы будем использовать этот простой словарь.

На приведенной выше диаграмме скрытый слой или блок RNN применяет формулу к текущему входу, а также к предыдущему состоянию. В этом случае перед буквой n из намасте нет ничего, поэтому мы перейдем к следующей букве a. Во время буквы a и предыдущего состояния, которое было буквой n, формула применяется скрытым слоем. Мы рассмотрим формулу немного позже. Каждое состояние, когда вход проходит через сеть, является временным шагом или шагом. Таким образом, если в момент времени t вход a, то в момент t-1 вход n. После применения формулы к n и a мы получаем новое состояние.

Формулу текущего состояния можно записать так:

ht - это новое состояние, а ht-1 - предыдущее состояние. xt - это вход в момент времени t. Теперь у нас есть ощущение предыдущих входных данных после того, как они прошли ту же формулу из предыдущих временных шагов. Мы пройдем через 7 таких входов в сеть, которая на каждом шаге будет проходить с одинаковыми весами и одной и той же функцией.

Теперь давайте попробуем определить f() простым способом. В качестве функции активации возьмем tanh. Веса определяются матрицей Whh, а входные данные определяются матрицей Wxh. Итак, формула выглядит так:

В приведенном выше примере в качестве памяти используется только последний шаг и, таким образом, слияние с данными последнего шага. Чтобы увеличить объем памяти сети и удерживать в памяти более длинные последовательности, мы должны добавить в уравнение больше состояний, например ht-2, ht-3 и т. Д. Наконец, выходные данные можно рассчитать, как во время тестирования:

где yt - выход. Выходные данные сравниваются с фактическими выходными данными, а затем вычисляется значение ошибки. Сеть учится путем обратного распространения ошибки через сеть для обновления весов. Об обратном распространении мы поговорим в следующем разделе.

Обратное распространение во времени (BPTT)

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

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

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

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

Мы берем скрытые единицы RNN и реплицируем их для каждого временного шага. Каждая репликация через временной шаг подобна слою в сети с прямой связью. Каждый временной шаг t слой соединяется со всеми возможными слоями на временном шаге t+1. Таким образом, мы случайным образом инициализируем веса, разворачиваем сеть и затем используем обратное распространение для оптимизации весов в скрытом слое. Инициализация выполняется путем передачи параметров на самый нижний уровень. Эти параметры также оптимизированы как часть обратного распространения ошибки.

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

Реализация RNN

Вот пример кода, в котором мы пытались реализовать RNN с использованием моделей Keras. Вот прямая ссылка на суть. Мы пытаемся предсказать следующую последовательность по набору текста.

Модель построила Яш Катария. Я немного обновил код, чтобы он соответствовал требованиям этой статьи. Код комментируется по мере продвижения, это говорит само за себя.

Заключение

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

  1. Исчезающие и взрывающиеся градиенты
  2. Проблема долговременных зависимостей
  3. Сети с долговременной краткосрочной памятью (LSTM)
  4. LSTM ворота
  5. Двунаправленные RNN
  6. Глубокие (двунаправленные) RNN
  7. Ячейки ГРУ (закрытые рекуррентные блоки)

Если вы хотите, чтобы я осветил некоторые вещи помимо этого, напишите сообщение в разделе комментариев. RNN - действительно мощная штука, и она очень близка к тому, как работает человеческий мозг. Я буду искать дальнейшее развитие в этой области, и я лично работаю над этим. О любых улучшениях я обязательно расскажу здесь. Так что, пожалуйста, подпишитесь на меня либо здесь, в Medium, либо в Twitter, чтобы оставаться в курсе.

Если вам понравилась эта статья, нажмите кнопку 👏, чтобы поддержать ее. Это поможет другим пользователям Medium найти его. Поделитесь этим в Twitter, чтобы охватить как можно больше читателей.