Рекуррентные нейронные сети RNN, серия 5: Пользовательские единицы

искусственный интеллект TensorFlow Программа перевода самородков Нейронные сети

Краткое содержание статей из этой серии

  1. Рекуррентная нейронная сеть RNN, серия 1: базовая RNN против CHAR-RNN
  2. Рекуррентная нейронная сеть RNN, серия 2: классификация текста
  3. Рекуррентная нейронная сеть RNN, серия 3: кодировщик, декодер
  4. Рекуррентная нейронная сеть RNN, серия 4: механизм внимания
  5. Рекуррентные нейронные сети RNN, серия 5: Пользовательские единицы

Рекуррентные нейронные сети RNN, серия 5: Пользовательские единицы

В этой статье мы рассмотрим и попытаемся создать нашу собственную определенную ячейку RNN. Но перед этим нам нужно более подробно рассмотреть простые RNN, а затем перейти к более сложным единицам (таким как LSTM и GRU). Мы проанализируем код реализации этих модулей в tensorflow и, наконец, обратимся к этим кодам для создания нашего пользовательского модуля. В этой статье будут приведены картинки из отличной статьи Криса Ола о RNN и LSTM. Здесь я настоятельно рекомендую вам прочитатьэта статья, многие из которых будут повторяться в этой статье, но будут быстро пропущены, поскольку мы в основном сосредоточены на коде tf. В будущем, когда я захочу выполнить нормализацию слоя в структуре RNN, я также буду ссылаться на код в этой статье. Последующие статьи можно найти наздесьПроверять.

Базовый РНН:

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

screen-shot-2016-10-04-at-5-54-13-am
screen-shot-2016-10-04-at-5-54-13-am

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

Сеть с долговременной кратковременной памятью (LSTM):

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

Screen Shot 2016-11-16 at 6.25.04 PM.png
Screen Shot 2016-11-16 at 6.25.04 PM.png

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

Screen Shot 2016-11-16 at 6.28.06 PM.png
Screen Shot 2016-11-16 at 6.28.06 PM.png

Забытые ворота:

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

Screen Shot 2016-11-16 at 6.30.38 PM.png
Screen Shot 2016-11-16 at 6.30.38 PM.png

Screen Shot 2016-11-16 at 6.39.17 PM.png
Screen Shot 2016-11-16 at 6.39.17 PM.png

Вы можете обратиться к чему-то вроде tf_linearфункцию для его реализации. Но главное в воротах забвения — применить сигмоиду к входному и скрытому состоянию. Так что же делает эта сигмовидная? Напомним, что сигмоид выводит значения в диапазоне [0, 1], здесь мы применяем его к матрице [N X H], поэтому мы получаем NXH сигмовидно-вычисленных значений. Если сигмоид получает значение 0, соответствующее ему скрытое значение будет недействительным; если сигмоид получает значение 1, то скрытое значение будет использоваться в расчетах. Значение от 0 до 1 позволит продолжить часть сообщения. Таким образом, данные блока ввода могут быть хорошо пропущены через блокировку и выборочно для достижения цели управляющей информации.

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

Входные ворота:

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

Screen Shot 2016-11-16 at 6.48.07 PM.png
Screen Shot 2016-11-16 at 6.48.07 PM.png

Tanh здесь отличается от предыдущей сигмовидной операции. Напомним, что tanh изменяет входное значение на значение в диапазоне [-1, 1]. Это существенно изменяет представление ввода нелинейным образом. Этот шаг аналогичен тому, что мы делали в базовом блоке RNN, но здесь мы добавляем произведение двух значений к значению, полученному вентилем забывания, чтобы получить значение состояния этого блока.

Работу вентиля забывания и вентиля ввода можно рассматривать как одновременное сохранение части старого состояния (C_{t-1}) и части нового преобразованного (tanh) состояния ячейки (C~_t). . Эти веса будут обучаться на наших данных, чтобы узнать, сколько данных нужно сохранить и как выполнять правильные преобразования.

Выходные ворота:

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

Screen Shot 2016-11-16 at 6.54.29 PM.png
Screen Shot 2016-11-16 at 6.54.29 PM.png

Этот шаг по-прежнему включает сигмовидную, и ее значение умножается на тангенсное значение состояния ячейки, чтобы определить сохранение информации. Следует отметить, что расчет тангенса на этом этапе отличается от расчета тангенса входных ворот, Этот шаг больше не является расчетом нейронной сети, а просто вычисляет значение тангенса значения единичного состояния без какого-либо веса. Таким образом, мы можем заставить значение матрицы состояния ячейки [NXH] находиться в диапазоне [-1, 1].

Варианты

Есть много вариантов ячеек RNN, опять же, я рекомендую прочитать Криса Олаха.этот пост в блогеУзнайте больше об этом. Но то, что он обсуждает в статье, — это модель глазка (позволяющая всем гейтам наблюдать за значением состояния ячейки при вычислении C_{t-1} или C_t) и пара состояний ячейки (обновить и забыть одновременно). Однако текущим конкурентом LSTM является GRU (Gated Recurrent Unit), который широко используется.

ГРУ (закрытая рекуррентная единица):

Основной принцип GRU состоит в том, чтобы объединить ворота забывания и ворота ввода в ворота обновления.

Screen Shot 2016-11-16 at 7.01.15 PM.png
Screen Shot 2016-11-16 at 7.01.15 PM.png

На практике GRU работают наравне с LSTM, но менее требовательны к вычислениям, поэтому сейчас они набирают популярность.

Собственная реализация Tensorflow:

Давайте сначала рассмотрим официальный код реализации Tensorflow для модуля GRU, в основном сосредоточившись на его методе вызова функции, вводе и выводе. Затем мы скопируем его структуру, чтобы создать собственный модуль. Если вас интересуют другие юниты, вы можетездесьНайдите их реализацию. В этой статье основное внимание будет уделено GRU, поскольку в большинстве случаев он работает наравне с LSTM и менее сложен.

class GRUCell(RNNCell):
  """Gated Recurrent Unit cell (cf. http://arxiv.org/abs/1406.1078)."""

  def __init__(self, num_units, input_size=None, activation=tanh):
    if input_size is not None:
      logging.warn("%s: The input_size parameter is deprecated.", self)
    self._num_units = num_units
    self._activation = activation

  @property
  def state_size(self):
    return self._num_units

  @property
  def output_size(self):
    return self._num_units

  def __call__(self, inputs, state, scope=None):
    """Gated recurrent unit (GRU) with nunits cells."""
    with vs.variable_scope(scope or type(self).__name__):  # "GRUCell"
      with vs.variable_scope("Gates"):  # Reset gate and update gate.
        # We start with bias of 1.0 to not reset and not update.
        r, u = array_ops.split(1, 2, _linear([inputs, state],
                                             2 * self._num_units, True, 1.0))
        r, u = sigmoid(r), sigmoid(u)
      with vs.variable_scope("Candidate"):
        c = self._activation(_linear([inputs, r * state],
                                     self._num_units, True))
      new_h = u * state + (1 - u) * c
    return new_h, new_h

Класс GRUCell состоит изinitФункция начинает выполняться. существуетinitФункция определяет количество ячеек и функцию активации для использования. Функция активации, как правило, тангенциальная, но также можно использовать сигмовидную, чтобы зафиксировать значение в диапазоне [0, 1], чтобы мы могли контролировать поток информации. Кроме того, у него есть два свойства, которые при вызове возвращают self._num_units. окончательно определилсяcallфункция, которая обработает входное значение и выведет новое скрытое значение. Напомним, что у GRU нет значений состояния ячейки, как у LSTM.

существуетcall, мы сначала вычисляем r и u (u — это z на предыдущем рисунке). На этом шаге, вместо того, чтобы вычислять их по отдельности, мы объединяем веса, умножая их на 2, умноженные на num_units, и делим результат на два, чтобы получить их (split(dim, num_splits, value)). Затем к полученным значениям применяется сигмовидная функция активации для выборочного управления потоком информации. Затем вычисляется значение c, которое используется для вычисления значения нового представления скрытого состояния. Вы можете обнаружить, что порядок, в котором он вычисляет new_h, обратный, но поскольку веса тренируются одновременно, код по-прежнему работает нормально.

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


Программа перевода самородковэто сообщество, которое переводит высококачественные технические статьи из Интернета сНаггетсДелитесь статьями на английском языке на . Охват контентаAndroid,iOS,React,внешний интерфейс,задняя часть,продукт,дизайнЕсли вы хотите видеть более качественные переводы, пожалуйста, продолжайте обращать вниманиеПрограмма перевода самородков,официальный Вейбо,Знай колонку.