Рекуррентные нейронные сети — различия между версиями
Adel (обсуждение | вклад) |
Adel (обсуждение | вклад) |
||
Строка 98: | Строка 98: | ||
== Пример кода == | == Пример кода == | ||
Пример кода на Python с использованием библиотеки Keras.<ref name=KerasRNN>[https://keras.io/layers/recurrent/ Keras RNN]</ref> | Пример кода на Python с использованием библиотеки Keras.<ref name=KerasRNN>[https://keras.io/layers/recurrent/ Keras RNN]</ref> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | # Устанавливаем seed для обеспечения повторяемости результатов | + | <font color="green"># Импорты</font> |
− | np.random.seed(42) | + | '''import''' numpy '''as''' np |
− | + | '''from''' keras.preprocessing '''import''' sequence | |
− | # Указываем количество слов из частотного словаря, которое будет использоваться (отсортированы по частоте использования) | + | '''from''' keras.models '''import''' Sequential |
− | max_features = 5000 | + | '''from''' keras.layers '''import''' Dense, Activation, Embedding |
− | + | '''from''' keras.layers '''import''' LSTM | |
− | # Загружаем данные (датасет IMDB содержит 25000 рецензий на фильмы с правильным ответом для обучения и 25000 рецензий на фильмы с правильным ответом для тестирования) | + | '''from''' keras.datasets '''import''' imdb |
− | (X_train, y_train), (X_test, y_test) = imdb.load_data(nb_words = max_features) | + | |
− | + | <font color="green"># Устанавливаем seed для обеспечения повторяемости результатов</font> | |
− | # Устанавливаем максимальную длину рецензий в словах, чтобы они все были одной длины | + | np.random.seed(<font color="blue">42</font>) |
− | maxlen = 80 | + | |
− | + | <font color="green"># Указываем количество слов из частотного словаря, которое будет использоваться (отсортированы по частоте использования)</font> | |
− | # Заполняем короткие рецензии пробелами, а длинные обрезаем | + | max_features = <font color="blue">5000</font> |
− | X_train = sequence.pad_sequences(X_train, maxlen = maxlen) | + | |
− | X_test = sequence.pad_sequences(X_test, maxlen = maxlen) | + | <font color="green"># Загружаем данные (датасет IMDB содержит 25000 рецензий на фильмы с правильным ответом для обучения и 25000 рецензий на фильмы с правильным ответом для тестирования)</font> |
− | + | (X_train, y_train), (X_test, y_test) = imdb.load_data(nb_words = max_features) | |
− | # Создаем модель последовательной сети | + | |
− | model = Sequential() | + | <font color="green"># Устанавливаем максимальную длину рецензий в словах, чтобы они все были одной длины</font> |
− | # Добавляем слой для векторного представления слов (5000 слов, каждое представлено вектором из 32 чисел, отключаем входной сигнал с вероятностью 20% для предотвращения переобучения) | + | maxlen = <font color="blue">80</font> |
− | model.add(Embedding(max_features, 32, dropout = 0.2)) | + | |
− | # Добавляем слой долго-краткосрочной памяти (100 элементов для долговременного хранения информации, отключаем входной сигнал с вероятностью 20%, отключаем рекуррентный сигнал с вероятностью 20%) | + | <font color="green"># Заполняем короткие рецензии пробелами, а длинные обрезаем</font> |
− | model.add(LSTM(100, dropout_W = 0.2, dropout_U = 0.2)) | + | X_train = sequence.pad_sequences(X_train, maxlen = maxlen) |
− | # Добавляем полносвязный слой из 1 элемента для классификации, в качестве функции активации будем использовать сигмоидальную функцию | + | X_test = sequence.pad_sequences(X_test, maxlen = maxlen) |
− | model.add(Dense(1, activation = "sigmoid | + | |
− | + | <font color="green"># Создаем модель последовательной сети</font> | |
− | # Компилируем модель нейронной сети | + | model = Sequential() |
− | model.compile(loss = 'binary_crossentropy', | + | <font color="green"># Добавляем слой для векторного представления слов (5000 слов, каждое представлено вектором из 32 чисел, отключаем входной сигнал с вероятностью 20% для предотвращения переобучения)</font> |
− | + | model.add(Embedding(max_features, <font color="blue">32</font>, dropout = <font color="blue">0.2</font>)) | |
− | + | <font color="green"># Добавляем слой долго-краткосрочной памяти (100 элементов для долговременного хранения информации, отключаем входной сигнал с вероятностью 20%, отключаем рекуррентный сигнал с вероятностью 20%)</font> | |
− | + | model.add(LSTM(<font color="blue">100</font>, dropout_W = <font color="blue">0.2</font>, dropout_U = <font color="blue">0.2</font>)) | |
− | # Обучаем нейронную сеть (данные для обучения, ответы к данным для обучения, количество рецензий после анализа которого будут изменены веса, число эпох обучения, тестовые данные, показывать progress bar или нет) | + | <font color="green"># Добавляем полносвязный слой из 1 элемента для классификации, в качестве функции активации будем использовать сигмоидальную функцию</font> |
− | model.fit(X_train, y_train, | + | model.add(Dense(<font color="blue">1</font>, activation = <font color="red">'sigmoid'</font>)) |
− | + | ||
− | + | <font color="green"># Компилируем модель нейронной сети</font> | |
− | + | model.compile(loss = <font color="red">'binary_crossentropy'</font>, | |
− | + | optimizer = <font color="red">'adam'</font>, | |
− | + | metrics = [<font color="red">'accuracy'</font>]) | |
− | # Проверяем качество обучения на тестовых данных (если есть данные, которые не участвовали в обучении, лучше использовать их, но в нашем случае таковых нет) | + | |
− | scores = model.evaluate(X_test, y_test, batch_size = 64) | + | <font color="green"># Обучаем нейронную сеть (данные для обучения, ответы к данным для обучения, количество рецензий после анализа которого будут изменены веса, число эпох обучения, тестовые данные, показывать progress bar или нет)</font> |
− | print("Точность на тестовых данных: %.2f%% | + | model.fit(X_train, y_train, |
− | </ | + | batch_size = <font color="blue">64</font>, |
+ | nb_epoch = <font color="blue">7</font>, | ||
+ | validation_data = (X_test, y_test), | ||
+ | verbose = <font color="blue">1</font>) | ||
+ | |||
+ | <font color="green"># Проверяем качество обучения на тестовых данных (если есть данные, которые не участвовали в обучении, лучше использовать их, но в нашем случае таковых нет)</font> | ||
+ | scores = model.evaluate(X_test, y_test, batch_size = <font color="blue">64</font>) | ||
+ | print(<font color="red">'Точность на тестовых данных: %.2f%%'</font> % (scores[1] * <font color="blue">100</font>)) | ||
==См. также== | ==См. также== |
Версия 16:57, 23 января 2019
Рекуррентная нейронная сеть (англ. recurrent neural network, RNN) — вид нейронных сетей, где связи между элементами образуют направленную последовательность.
Содержание
Описание
Рекуррентные нейронные сети — сети с циклами, которые хорошо подходят для обработки последовательностей.
Обучение RNN аналогично обучению обычной нейронной сети. Мы также используем алгоритм обратного распространения ошибки (backpropagation), но с небольшим изменением. Поскольку одни и те же параметры используются на всех временных этапах в сети, градиент на каждом выходе зависит не только от расчетов текущего шага, но и от предыдущих временных шагов. Например, чтобы вычислить градиент при t = 4, нам нужно было бы «распространить ошибку» на 3 шага и суммировать градиенты. Этот алгоритм называется «алгоритмом обратного распространения ошибки сквозь время» (англ. Backpropagation Through Time, BPTT).[1][2]
Области и примеры применения
Используются, когда важно соблюдать последовательность, когда нужен порядок того, что у нас происходит.
- Обработка текста на естественном языке
- Анализ текста
- Автоматический перевод
- Обработка аудио
- Автоматическое распознавание речи
- Обработка видео
- Прогнозирование следующего кадра на основе предыдущих
- Распознавание эмоций
- Обработка изображений
- Прогнозирование следующего пикселя на основе окружения
- Генерация описания изображений
Архитектуры
Полностью рекуррентная сеть
Это базовая архитектура, разработанная в 1980-х. Сеть строится из узлов, каждый из которых соединён со всеми другими узлами. У каждого нейрона порог активации меняется со временем и является вещественным числом. Каждое соединение имеет переменный вещественный вес. Узлы разделяются на входные, выходные и скрытые.
Рекурсивная сеть
Рекурсивные нейронные сети представляют собой более общий случай рекуррентных сетей, когда сигнал в сети проходит через структуру в виде дерева (обычно бинарные деревья). Те же самые матрицы весов используются рекурсивно по всему графу в соответствии с его топологией.
Нейронная сеть Хопфилда
Тип рекуррентной сети, когда все соединения симметричны. Изобретена Джоном Хопфилдом в 1982 году и гарантируется, что динамика такой сети сходится к одному из положений равновесия.
Двунаправленная ассоциативная память (BAM)
Вариацией сети Хопфилда является двунаправленная ассоциативная память (BAM). BAM имеет два слоя, каждый из которых может выступать в качестве входного, находить (вспоминать) ассоциацию и генерировать результат для другого слоя.
Сеть Элмана
Нейронная сеть Элмана состоит из трёх слоев: x, y, z (см рис. Сеть Элмана). Дополнительно к сети добавлен набор «контекстных блоков»: u (см рис. Сеть Элмана). Средний (скрытый) слой соединён с контекстными блоками с фиксированным весом, равным единице. С каждым шагом времени на вход поступает информация, которая проходит прямой ход к выходному слою в соответствии с правилами обучения. Фиксированные обратные связи сохраняют предыдущие значения скрытого слоя в контекстных блоках (до того как скрытый слой поменяет значение в процессе обучения). Таким способом сеть сохраняет своё состояние, что может использоваться в предсказании последовательностей, выходя за пределы мощности многослойного перцептрона.
Обозначения переменных и функций:
- : вектор входного слоя
- : вектор скрытого слоя
- : вектор выходного слоя
- : матрица и вектор параметров
- : функция активации
Сеть Джордана
Нейронная сеть Джордана подобна сети Элмана, но контекстные блоки связаны не со скрытым слоем, а с выходным слоем. Контекстные блоки таким образом сохраняют своё состояние. Они обладают рекуррентной связью с собой.
Эхо-сети
Эхо-сеть (англ. Echo State Network, ESN) характеризуется одним скрытым слоем (который называется резервуаром) со случайными редкими связями между нейронами. При этом связи внутри резервуара фиксированы, но связи с выходным слоем подлежат обучению. Состояние резервуара (state) вычисляется через предыдущие состояния резервуара, а также предыдущие состояния входного и выходного сигналов. Так как эхо-сети обладают только одним скрытым слоем, они обладают достаточно низкой вычислительной сложностью.
Нейронный компрессор истории
Нейронный компрессор исторических данных — это блок, позволяющий в сжатом виде хранить существенные исторические особенности процесса, который является своего рода стеком рекуррентной нейронной сети, формируемым в процессе самообучения.
Сети долго-краткосрочной памяти
Сеть долго-краткосрочной памяти (англ. Long short-term memory, LSTM) является самой популярная архитектура рекуррентной нейронной сети на данный момент, данная архитектура способна запоминать данные на долгое время.[3]
Разберем работу слоев подробнее[4]:
Первый слой вычисляет, насколько на данном шаге ему нужно забыть предыдущую информацию — по сути множители к компонентам вектора памяти.
Второй слой вычисляет, насколько ему интересна новая информация, пришедшая с сигналом — такой же множитель, но уже для наблюдения.
На третьем слое вычисляется линейная комбинация памяти и наблюдения с только вычисленными весами для каждой из компонент. Так получается новое состояние памяти, которое в таком же виде передаётся далее.
Осталось вычислить output. Но поскольку часть входного сигнала уже в памяти, не нужно считать активацию по всему сигналу. Сначала сигнал проходит через сигмоиду, которая решает, какая его часть важна для дальнейших решений, затем гиперболический тангенс «размазывает» вектор памяти на отрезок от -1 до 1, и в конце эти два вектора перемножаются.
Полученные таким образом
и передаются далее по цепочке.Управляемые рекуррентные блоки
Управляемые рекуррентные блоки (англ. Gated Recurrent Units, GRU) — обладает меньшим количеством параметров, чем у LSTM, и в ней отсутствует выходное управление. При этом производительность в моделях речевого сигнала или полифонической музыки оказалась сопоставимой с LSTM.
Пример кода
Пример кода на Python с использованием библиотеки Keras.[5]
# Импорты import numpy as np from keras.preprocessing import sequence from keras.models import Sequential from keras.layers import Dense, Activation, Embedding from keras.layers import LSTM from keras.datasets import imdb # Устанавливаем seed для обеспечения повторяемости результатов np.random.seed(42) # Указываем количество слов из частотного словаря, которое будет использоваться (отсортированы по частоте использования) max_features = 5000 # Загружаем данные (датасет IMDB содержит 25000 рецензий на фильмы с правильным ответом для обучения и 25000 рецензий на фильмы с правильным ответом для тестирования) (X_train, y_train), (X_test, y_test) = imdb.load_data(nb_words = max_features) # Устанавливаем максимальную длину рецензий в словах, чтобы они все были одной длины maxlen = 80 # Заполняем короткие рецензии пробелами, а длинные обрезаем X_train = sequence.pad_sequences(X_train, maxlen = maxlen) X_test = sequence.pad_sequences(X_test, maxlen = maxlen) # Создаем модель последовательной сети model = Sequential() # Добавляем слой для векторного представления слов (5000 слов, каждое представлено вектором из 32 чисел, отключаем входной сигнал с вероятностью 20% для предотвращения переобучения) model.add(Embedding(max_features, 32, dropout = 0.2)) # Добавляем слой долго-краткосрочной памяти (100 элементов для долговременного хранения информации, отключаем входной сигнал с вероятностью 20%, отключаем рекуррентный сигнал с вероятностью 20%) model.add(LSTM(100, dropout_W = 0.2, dropout_U = 0.2)) # Добавляем полносвязный слой из 1 элемента для классификации, в качестве функции активации будем использовать сигмоидальную функцию model.add(Dense(1, activation = 'sigmoid')) # Компилируем модель нейронной сети model.compile(loss = 'binary_crossentropy', optimizer = 'adam', metrics = ['accuracy']) # Обучаем нейронную сеть (данные для обучения, ответы к данным для обучения, количество рецензий после анализа которого будут изменены веса, число эпох обучения, тестовые данные, показывать progress bar или нет) model.fit(X_train, y_train, batch_size = 64, nb_epoch = 7, validation_data = (X_test, y_test), verbose = 1) # Проверяем качество обучения на тестовых данных (если есть данные, которые не участвовали в обучении, лучше использовать их, но в нашем случае таковых нет) scores = model.evaluate(X_test, y_test, batch_size = 64) print('Точность на тестовых данных: %.2f%%' % (scores[1] * 100))