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

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

Вот простая реализация пошаговой функции в Vanilla RNN.

rnn = RNN()
y = rnn.step(x)

class RNN:
 
  def step(self, x):
    # update the hidden state
    self.h = np.tanh(np.dot(self.W_hh, self.h) + np.dot(self.W_xh,       x))
    # compute the output vector
    y = np.dot(self.W_hy, self.h)
    return y

Вышеуказанное определяет прямой проход ванильной RNN. Параметры этой RNN - это три матрицы W_hh, W_xh, W_hy. Скрытое состояние self.h инициализируется нулевым вектором. Функция np.tanh реализует нелинейность, которая сжимает активации до диапазона [-1, 1]. Внутри tanh есть два члена: один основан на предыдущем скрытом состоянии, а другой - на текущем вводе. В numpy np.dot умножение матриц. Два промежуточных продукта взаимодействуют с сложением, а затем сдавливаются tanh в новый вектор состояния. Мы также можем записать обновление скрытого состояния как

ht = tanh (W_ hh h_ t −1+ W_ xh x_ t)

где tanh применяется поэлементно. Обратите внимание, что есть три весовых метрики, это потому, что есть два входа: один, который модель уже изучила (W _ hh), другой - вход (W_xh), третий (W_hy) для вывода.

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

X t - это вход, а y t - выход. Как вы можете видеть на приведенной выше диаграмме, эта цепочечная природа очень похожа на последовательность и списки. Вот код для RNN с использованием набора данных tenorflow ON MNIST из 28x28 изображений рукописных цифр и их

import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, LSTM
mnist = tf.keras.datasets.mnist
#splitting dataset into train and testing
(x_train, y_train),(x_test, y_test) = mnist.load_data()  # unpacks images to x_train/x_test and labels to y_train/y_test
#normalizing values
x_train = x_train/255.0
x_test = x_test/255.0
print(x_train.shape)
print(x_train[0].shape)
model = Sequential()
model.add(LSTM(128, input_shape=(x_train.shape[1:]), activation='relu', return_sequences=True))
model.add(Dropout(0.2))
model.add(LSTM(128, activation='relu'))
model.add(Dropout(0.1))
model.add(Dense(32, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(10, activation='softmax'))
opt = tf.keras.optimizers.Adam(lr=0.001, decay=1e-6)
model.compile(loss='sparse_categorical_crossentropy',optimizer=opt,
metrics=['accuracy'],)
model.fit(x_train,y_train,epochs=3,validation_data=(x_test, y_test))

RNN используется, когда вы хотите просмотреть последнюю информацию, например, у нас есть предложение и мы хотим предсказать последнее слово «рыбы плавают в воде». очевидно, что последнее слово будет за водой. В этом случае разрыв между информацией невелик, RNN может научиться использовать прошлую информацию. Но есть случаи, когда нам нужно больше контекста. Рассмотрим предложение «Я вырос во Франции (2000 слов спустя)…». Я свободно говорю по-французски ». Недавняя информация предполагает, что следующее слово, вероятно, является названием языка, но если мы хотим сузить круг вопросов, нам понадобится контекст Франции, более ранний. Вполне возможно, что разрыв между релевантной информацией и точкой, в которой она необходима, станет очень большим. К сожалению, по мере того, как разрыв увеличивается, RNN становится неспособным научиться связывать информацию.

Это связано с тем, что градиент функции потерь экспоненциально спадает со временем (это называется проблемой исчезающего градиента). Сети LSTM - это тип RNN, в котором помимо стандартных модулей используются специальные модули. Модули LSTM включают в себя «ячейку памяти», которая может сохранять информацию в памяти в течение длительных периодов времени.

Сеть LSTM

Сети с долговременной краткосрочной памятью - обычно называемые просто «LSTM» - это особый вид RNN, способный изучать долгосрочные зависимости

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

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

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

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

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

Ворота - это способ пропускать информацию. Они состоят из слоя сигмоидной нейронной сети и операции точечного умножения.

Bi-LSTM: (двунаправленная долгосрочная краткосрочная память):
Двунаправленные рекуррентные нейронные сети (RNN) на самом деле просто объединяют две независимые RNN. Эта структура позволяет сетям иметь как обратную, так и прямую информацию о последовательности на каждом временном шаге.

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

Ссылки



Http://introtodeeplearning.com/slides/6S191_MIT_DeepLearning_L2.pdf

Https://medium.com/@raghavaggarwal0089/bi-lstm-bc3d68da8bd0