LSTM и GRU
Рекуррентные нейронные сети уникальны тем, что способны обрабатывать последовательности данных, будь то тексты, временные ряды или даже музыка. В отличие от их бро — сверточных нейронных сетей, которые идеально подходят для обработки изображений, RNN обладают способностью «помнить» предыдущую информацию и использовать ее для обработки текущих данных. Это делает их идеальными для задач, где контекст важен, например, при генерации текста или прогнозировании временных рядов.
Но не все так радужно, как может показаться на первый взгляд. Основной головной болью при работе с RNN являются проблемы затухания и взрыва градиента. Эти явления возникают в процессе обучения сети, когда веса модели корректируются с помощью обратного распространения ошибки. Затухание градиента происходит, когда веса корректируются настолько слабо, что обучение становится неэффективным. С другой стороны, взрыв градиента происходит, когда эти корректировки слишком велики, что также ведет к нестабильности обучения. Обе эти проблемы могут серьезно затруднить обучение RNN.
К счастью, на помощь приходят LSTM и GRU — две разновидности RNN, разработанные специально для борьбы с этими проблемами.
Рекуррентные сети, способные обрабатывать последовательности данных и сохранять информацию о предыдущих состояниях, были представлены в 1980-х годах. Однако они столкнулись с серьезными проблемами при обучении из-за затухания и взрыва градиента, что ограничивало их способность сохранять информацию на длительные периоды времени.
LSTM была предложена в 1997 году Йоханнесом Шмидхубером и Зеппом Хохрайтером. Эта концепция была революционной: LSTM предназначалась для сохранения информации на длительные периоды времени и ее эффективного извлечения, когда это необходимо. Основной идеей было внедрение так называемых «ворот» в структуру нейронной сети, которые контролируют поток информации, позволяя избежать проблемы затухания градиента.
Основной инновацией в LSTM являются три типа ворот: входные (input gates), забывания (forget gates) и выходные (output gates). Эти ворота позволяют модели решать, какую информацию сохранить, какую обновить и какую передать дальше. Такая структура позволяет LSTM обрабатывать данные с долгосрочными зависимостями, что было недостижимо для традиционных RNN.
LSTM начала применяться в различных областях, где необходимо было учитывать долгосрочные зависимости в данных. Одним из первых значительных применений LSTM стало распознавание рукописного текста. В последующие годы LSTM нашла широкое применение в обработке естественного языка, прогнозировании временных рядов, генерации музыки и многих других областях.
Со временем LSTM подвергалась различным модификациям и улучшениям. Например, были предложены вариации, упрощающие оригинальную модель, такие как GRU, которая обладает меньшим числом параметров, но при этом сохраняет многие ключевые особенности LSTM.
Ячейка LSTM состоит из нескольких компонентов:
Ворота забывания (Forget Gates)
Ворота забывания в LSTM предназначены для управления продолжительностью памяти в ячейке, решая, какую информацию следует забыть, а какую сохранить.
Ворота забывания принимают два основных входа:
- hₜ₋₁: Выход предыдущего состояния LSTM.
- xₜ: Текущий входной вектор.
Следующий шаг — применение сигмоидной функции активации к этим входным данным. Сигмоидная функция выбрана потому, что она возвращает значения в диапазоне от 0 до 1. Эти значения интерпретируются как степень «забывания» информации.
Выход сигмоидной функции получается следующим образом:
fₜ = σ (Wₓₓ * xₜ + Wₕₕ * hₜ₋₁ + bₜ)
Где:
- σ — сигмоидная функция,
- Wₓₓ и Wₕₕ — весовые матрицы для входных данных и предыдущего состояния соответственно,
- bₜ — вектор смещения (bias),
- fₜ — выход ворот забывания.
Выход ворот забывания fₜ умножается на предыдущее состояние ячейки памяти Cₜ₋₁. Это умножение определяет, какая часть прошлой информации сохранится. Значение близкое к 1 означает, что информация сохраняется, в то время как значение близкое к 0 означает, что информация «забывается».
Обновленное состояние ячейки Cₜ получается путем объединения результатов ворот забывания с результатами входных ворот, которые добавляют новую информацию в ячейку.
Входные ворота (Input Gates)
Входные ворота определяют, какая часть новой информации должна быть сохранена в долгосрочной памяти ячейки LSTM. Они не только фильтруют входные данные, но и решают, какая информация достаточно важна для сохранения.
Аналогично воротам забывания, входные ворота принимают два входа:
- hₜ₋₁: Выход из предыдущего состояния LSTM.
- xₜ: Текущий входной вектор.
Входные ворота используют сигмоидную функцию активации для определения важности входных данных. Сигмоид возвращает значения между 0 и 1, где 1 означает полное сохранение информации, а 0 — полное отклонение.
Одновременно, входные ворота применяют гиперболический тангенс к тем же входным данным для создания вектора кандидатов на добавление в ячейку памяти.
Выход входных ворот iₜ и кандидат на добавление Cₜ вычисляются следующим образом:
Где:
- σ — сигмоидная функция,
- tanh — гиперболический тангенс,
- W и b — весовые матрицы и векторы смещения для различных частей ворот,
- iₜ — выход входных ворот,
- Cₜ — кандидат на добавление в состояние ячейки.
Выход входных ворот iₜ умножается на Cₜ₋₁ (кандидат на добавление), что определяет новую информацию, которая будет добавлена в состояние ячейки. Это умножение позволяет входным воротам регулировать величину добавляемой информации.
Выходные ворота (Output Gates)
Выходные ворота определяют, какая информация из текущего состояния ячейки будет передана в выходной сигнал сети. Это включает в себя решение о том, какие аспекты сохраненной информации являются релевантными для текущего задания или контекста.
Выходные ворота анализируют два основных вида входных данных:
— hₜ₋₁: Предыдущий выходной сигнал LSTM.
— xₜ: Текущий входной вектор.
Выходные ворота также используют сигмоидную функцию активации σ, как и другие ворота в LSTM. Сигмоид преобразует входные данные в значения от 0 до 1, которые указывают на степень важности каждой части состояния ячейки для выходного сигнала.
Формула для выходных ворот oₜ выглядит следующим образом:
oₜ = σ (Wₓ * xₜ + Wₕ * hₜ₋₁ + bo)
Где:
— Wₓ и Wₕ — весовые матрицы для входных данных и предыдущего выхода соответственно,
— b_o — вектор смещения (bias) для выходных ворот,
— oₜ — выход выходных ворот.
Выход oₜ умножается на тангенс гиперболический от текущего состояния ячейки Cₜ, чтобы создать окончательный выходной сигнал LSTM. Это умножение позволяет регулировать, какая часть информации из ячейки памяти должна быть передана дальше.
В LSTM память обрабатывается текущими входными данными и выходом предыдущего шага. Новая информация постоянно влияет на краткосрочное состояние ячейки и модифицируется через ворота, что позволяет сети помнить или забывать информацию.
Ячейка состояния в LSTM действует как носитель долгосрочной памяти. Она способна переносить информацию на протяжении множества шагов, благодаря своей способности добавлять или удалять информацию через ворота. Это позволяет LSTM запоминать информацию на долгие периоды времени, что является ключевым преимуществом по сравнению с традиционными RNN.
Как LSTM решает проблемы RNN
Главные «болячки» RNN — это затухание и взрыв градиента. При обратном распространении ошибки в глубоких RNN, градиенты, которые используются для обновления весов, могут становиться либо слишком большими, что приводит к взрыву градиента, либо слишком маленькими, что ведет к затуханию градиента. Это создает серьезные препятствия для обучения, особенно при работе с длинными последовательностями данных.
Благодаря воротам забывания LSTM может избавляться от ненужной информации, что помогает предотвратить затухание градиента. Это позволяет LSTM обрабатывать гораздо более длинные последовательности данных, чем это возможно для стандартных RNN.
Входные и выходные ворота контролируют, какая информация должна быть сохранена в долгосрочной памяти и как она должна использоваться. Это обеспечивает более точное и эффективное распространение информации через сеть.
GRU, или Gated Recurrent Unit, является одним из видов рекуррентных нейронных сетей (RNN), аналогичным LSTM (Long Short-Term Memory). Разработанная в 2014 году, эта архитектура была предназначена для упрощения и ускорения обучения по сравнению с LSTM, сохраняя при этом большую часть ее эффективности, особенно в задачах обработки последовательностей данных.
В отличие от LSTM, в GRU нет отдельного долгосрочного состояния ячейки. Состояние ячейки в GRU является комбинацией прошлого состояния и новых входных данных, модулируемых через обновляющие и сбрасывающие ворота. Это состояние обновляется на каждом шаге и переносит информацию по всей сети.
Ворота обновления в GRU контролируют, насколько новая информация будет влиять на состояние ячейки. Они определяют, какую часть прошлого состояния следует сохранить и какую часть текущего ввода следует учесть.
Ворота сброса помогают модели решить, какая информация из прошлого необходима для текущего выхода. Если ворота сброса близки к нулю, то это означает, что прошлая информация не будет учитываться, что позволяет модели отбросить нерелевантные данные.
В GRU нет отдельной ячейки памяти, как в LSTM. Вместо этого, она обновляет скрытое состояние напрямую. Ворота обновления помогают модели решить, какая часть предыдущего скрытого состояния должна быть сохранена. Это делается путем комбинирования прошлого состояния и новой информации.
Ворота сброса определяют, какая часть прошлого состояния важна для текущего ввода, а ворота обновления используют эту информацию для формирования нового скрытого состояния. Это позволяет GRU более гибко регулировать поток информации.
GRU выполняет серию математических операций для обновления своего состояния, включая использование сигмоидной функции для ворот и гиперболического тангенса для создания новых кандидатов на состояние. Эти операции помогают GRU динамически регулировать поток информации.
Сравнение c LSTM
1. Количество ворот:
— LSTM: Имеет три типа ворот — ворота забывания (forget gates), входные ворота (input gates) и выходные ворота (output gates).
— GRU: Имеет два типа ворот — ворота обновления (update gates) и ворота сброса (reset gates).
2. Состояние ячейки:
— LSTM: Включает в себя отдельное состояние ячейки и скрытое состояние, что обеспечивает дополнительный контроль над потоком информации.
— GRU: Использует только скрытое состояние, что упрощает ее структуру.
3. Управление информацией:
— LSTM: Ворота забывания и входные ворота независимо контролируют поток информации, что позволяет более точно регулировать, какая информация сохраняется или отбрасывается.
— GRU: Ворота обновления одновременно контролируют информацию, которая сохраняется из прошлого состояния, и добавляемую новую информацию, что приводит к более глобальной регуляции.
Если важна скорость обучения и доступные вычислительные ресурсы ограничены, GRU может быть предпочтительнее из-за своей более простой структуры и меньшего количества параметров по сравнению с LSTM.
Для более простых или меньших наборов данных GRU может быть достаточной, поскольку она может достаточно эффективно обучаться на таких данных, не теряя в производительности.
Если задача требует более детального управления информацией и долгосрочной памяти (например, в сложных задачах обработки естественного языка с длинными зависимостями), LSTM может быть более подходящим выбором благодаря своей дополнительной сложности и дополнительному контролю над информацией.
Примеры с LSTM
1. Основная LSTM модель:
from keras.models import Sequential
from keras.layers import LSTM, Dense
model = Sequential()
model.add(LSTM(50, input_shape=(100, 1))) # 100 time steps, 1 feature
model.add(Dense(1))
model.compile(optimizer='adam', loss='mse')
2. LSTM с множественными слоями:
model = Sequential()
model.add(LSTM(50, return_sequences=True, input_shape=(100, 1)))
model.add(LSTM(50))
model.add(Dense(1))
model.compile(optimizer='adam', loss='mse')
3. LSTM для классификации:
model = Sequential()
model.add(LSTM(100, input_shape=(100, 1)))
model.add(Dense(10, activation='softmax'))
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
4. Стековая LSTM:
model = Sequential()
model.add(LSTM(100, return_sequences=True, input_shape=(100, 1)))
model.add(LSTM(100))
model.add(Dense(1, activation='sigmoid'))
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
5. LSTM с регуляризацией Dropout:
from keras.layers import Dropout
model = Sequential()
model.add(LSTM(100, input_shape=(100, 1)))
model.add(Dropout(0.5))
model.add(Dense(1, activation='sigmoid'))
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
Примеры с GRU
6. Основная GRU модель:
from keras.layers import GRU
model = Sequential()
model.add(GRU(50, input_shape=(100, 1)))
model.add(Dense(1))
model.compile(optimizer='adam', loss='mse')
7. GRU с множественными слоями:
model = Sequential()
model.add(GRU(50, return_sequences=True, input_shape=(100, 1)))
model.add(GRU(50))
model.add(Dense(1))
model.compile(optimizer='adam', loss='mse')
8. GRU для классификации:
model = Sequential()
model.add(GRU(100, input_shape=(100, 1)))
model.add(Dense(10, activation='softmax'))
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
9. Стековая GRU:
model = Sequential()
model.add(GRU(100, return_sequences=True, input_shape=(100, 1)))
model.add(GRU(100))
model.add(Dense(1, activation='sigmoid'))
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
10. GRU с регуляризацией Dropout:
model = Sequential()
model.add(GRU(100, input_shape=(100, 1)))
model.add(Dropout(0.5))
model.add(Dense(1, activation='sigmoid'))
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
Заключение
Выбор между LSTM и GRU в конкретной задаче зависит от множества факторов, включая размер и природу данных, требуемую вычислительную мощность и конкретные цели проекта. Хотя LSTM имеет более сложную структуру и предоставляет лучшую сохранность информации на длинных последовательностях, GRU выигрывает за счет своей эффективности и скорости обучения на небольших до средних данных.