Изменения

Перейти к: навигация, поиск

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

1448 байт добавлено, 03:15, 9 апреля 2019
Пример кода
'''Рекуррентная нейронная сеть''' (англ. ''recurrent neural network'', ''RNN'') {{---}} вид [[:Нейронные_сети,_перцептрон|нейронных сетей]], где связи между элементами образуют направленную последовательность.
 
== Описание ==
[[File:RNN.png|450px|thumb|[http://colah.github.io/posts/2015-08-Understanding-LSTMs/ RNN и ее развернутое представление]]]
[[File:RNN_layer.png|450px|thumb|[http://colah.github.io/posts/2015-08-Understanding-LSTMs/ Схема слоя рекуррентной сети]]]
 
'''Рекуррентная нейронная сеть''' (англ. ''recurrent neural network'', ''RNN'') {{---}} вид [[:Нейронные сети|нейронных сетей]], где связи между элементами образуют направленную последовательность.
 
== Описание ==
Рекуррентные нейронные сети {{---}} сети с циклами, которые хорошо подходят для обработки последовательностей.
[[File:RNN_BP.jpg|450px|thumb|RNN с задержкой на скрытом слое]]
[[File:RNN_BPTT.jpg|450px|thumb|Развертка RNN]]
Обучение RNN аналогично обучению обычной нейронной сети. Мы также используем [[:Обратное_распространение_ошибки|алгоритм обратного распространения ошибки (backpropagation)]]<sup>[на 28.01.19 не создан]</sup>, но с небольшим изменением. Поскольку одни и те же параметры используются на всех временных этапах в сети, градиент на каждом выходе зависит не только от расчетов текущего шага, но и от предыдущих временных шагов. Например, чтобы вычислить градиент при t = 4для четвертого элемента последовательности, нам нужно было бы «распространить ошибку» на 3 шага и суммировать градиенты. Этот алгоритм называется «алгоритмом обратного распространения ошибки сквозь время» (англ. Backpropagation Through Time, BPTT).<ref name=BPTT_1>[http://andrew.gibiansky.com/blog/machine-learning/recurrent-neural-networks/ Backpropagation Through Time]</ref><ref name=BPTT_2>[http://www.wildml.com/2015/10/recurrent-neural-networks-tutorial-part-3-backpropagation-through-time-and-vanishing-gradients/ Backpropagation Through Time]</ref> Алгоритм обратного распространения ошибки сквозь время: [[File:RNN_BPTT_GRAD.png|400px|frameless]]
== Области и примеры применения ==
Используются, когда важно соблюдать последовательность, когда нужен важен порядок того, что у нас происходитпоступающих объектов.* Обработка текста на естественном языке:** Анализ текста;** Автоматический перевод;* Обработка аудио :** Автоматическое распознавание речи;* Обработка видео:** Прогнозирование следующего кадра на основе предыдущих;** Распознавание эмоций;* Обработка изображений:** Прогнозирование следующего пикселя на основе окружения;** Генерация описания изображений. == Виды RNN ===== Один к одному ==={||-|[[File:RNN_OTO.jpg|100px|left]]|Архитектура по сути является обычной нейронной сетью.|} === Один ко многим ==={||-|[[File:RNN_OTM.jpg|100px|left]]|Один вход ко многим выходам может применяться, например, для генерации аудиозаписи. На вход подаем жанр музыки, который хотим получить, на выходе получаем последовательность аудиозаписи.|} === Многие к одному ==={||-|[[File:RNN_MTO.jpg|100px|left]]|Много входов и один выход может применяться, если мы хотим оценить тональность рецензии. На вход подаем слова рецензии, на выходе получаем оценку ее тональности: позитивная рецензия или негативная.|} === Многие ко многим ==={||-|[[File:RNN_MTM1.jpg|100px|left]]|Данную архитектуру можно использовать для перевода текста с одного языка на другой.|-|[[File:RNN_MTM2.jpg|100px|left]]|Такой вариант подойдет для определения для классификации каждого слова в предложении в зависимости от контекста.|}
== Архитектуры ==
=== Рекурсивная сеть ===
[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]] <sup>[на 28.01.19 не создан]</sup> представляют собой более общий случай рекуррентных сетей, когда сигнал в сети проходит через структуру в виде дерева (обычно бинарные деревья). Те же самые матрицы весов используются рекурсивно по всему графу в соответствии с его топологией.
=== Нейронная сеть Хопфилда ===
Нейронная сеть Элмана состоит из трёх слоев: x, y, z (см рис. Сеть Элмана). Дополнительно к сети добавлен набор «контекстных блоков»: u (см рис. Сеть Элмана). Средний (скрытый) слой соединён с контекстными блоками с фиксированным весом, равным единице. С каждым шагом времени на вход поступает информация, которая проходит прямой ход к выходному слою в соответствии с правилами обучения. Фиксированные обратные связи сохраняют предыдущие значения скрытого слоя в контекстных блоках (до того как скрытый слой поменяет значение в процессе обучения). Таким способом сеть сохраняет своё состояние, что может использоваться в предсказании последовательностей, выходя за пределы мощности многослойного перцептрона.
<math>h_t = \sigma_h(W_h x_t + U_h h_{t-1} + b_h)</math>,
<math>y_t = \sigma_y(W_y h_t + b_y)</math>,
Обозначения переменных и функций:
* <math>x_t</math>: вектор входного слоя;* <math>h_t</math>: вектор скрытого слоя;* <math>y_t</math>: вектор выходного слоя;* <math>W, U, b</math>: матрица и вектор параметров;* <math>\sigma_h, \sigma_y</math>: функция активации.
=== Сеть Джордана ===
Нейронная сеть Джордана подобна сети Элмана, но контекстные блоки связаны не со скрытым слоем, а с выходным слоем. Контекстные блоки таким образом сохраняют своё состояние. Они обладают рекуррентной связью с собой.
<math>h_t = \sigma_h(W_h x_t + U_h y_{t-1} + b_h)</math>,
<math>y_t = \sigma_y(W_y h_t + b_y)</math>,
=== Эхо-сети ===
=== Сети долго-краткосрочной памяти ===
[[:Долгая_краткосрочная_память|Сеть долго-краткосрочной памяти ]] (англ. Long short-term memory, LSTM) является самой популярная архитектура популярной архитектурой рекуррентной нейронной сети на данный текущий момент, данная такая архитектура способна запоминать данные на долгое время.<ref name=LSTM>[https://www.bioinf.jku.at/publications/older/2604.pdf Sepp Hochreiter, Jurgen Schmidhuber. Long short-term memory (1997). Neural Computation.]</ref> Разберем работу слоев подробнее<ref name=Understanding_LSTM>[http://colah.github.io/posts/2015-08-Understanding-LSTMs/ Understanding LSTM Networks]</ref>: Первый слой вычисляет, насколько на данном шаге ему нужно забыть предыдущую информацию {{---}} по сути множители к компонентам вектора памяти.[[File:LSTM_F1.png|none|250px]]<math>f_t = \sigma(W_f * [h_{t-1}, x_t] + b_f)</math> Второй слой вычисляет, насколько ему интересна новая информация, пришедшая с сигналом {{---}} такой же множитель, но уже для наблюдения.[[File:LSTM_F2.png|none|250px]]<math>i_t = \sigma(W_f * [h_{t-1}, x_t] + b_i)</math> <math>\tilde{C}_t = tanh(W_C * [h_{t-1}, x_t] + b_C)</math> На третьем слое вычисляется линейная комбинация памяти и наблюдения с только вычисленными весами для каждой из компонент. Так получается новое состояние памяти, которое в таком же виде передаётся далее.[[File:LSTM_F3.png|none|250px]]<math>C_t = f_t * C_{t-1} + i_t * \tilde{C}_t</math> Осталось вычислить output. Но поскольку часть входного сигнала уже в памяти, не нужно считать активацию по всему сигналу. Сначала сигнал проходит через сигмоиду, которая решает, какая его часть важна для дальнейших решений, затем гиперболический тангенс «размазывает» вектор памяти на отрезок от -1 до 1, и в конце эти два вектора перемножаются.[[File:LSTM_F4.png|none|250px]]<math>o_t = \sigma(W_o * [h_{t-1}, x_t] + b_o)</math> <math>h_t = o_t * tanh(C_t)</math> Полученные таким образом <math>h_t</math> и <math>C_t</math> передаются далее по цепочке.
=== Управляемые рекуррентные блоки ===
== Пример кода ==
===Пример кода на Python с использованием библиотеки Keras.<ref name=KerasRNN>[https://keras.io/layers/recurrent/ Keras RNN]</ref><pre># Импортыimport numpy as npfrom keras.preprocessing import sequencefrom keras.models import Sequentialfrom keras.layers import Dense, Activation, Embeddingfrom keras.layers import LSTMfrom keras.datasets import imdb===
<font color="green"># Импорты</font> '''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 <font color="green"># Устанавливаем seed для обеспечения повторяемости результатов</font> np.random.seed(<font color="blue">42</font>) <font color="green"># Указываем количество слов из частотного словаря, которое будет использоваться (отсортированы по частоте использования)</font> max_features = <font color="blue">5000</font> <font color="green"># Загружаем данные (датасет IMDB содержит 25000 рецензий на фильмы с правильным ответом для обучения и 25000 рецензий на фильмы с правильным ответом для тестирования)</font> (X_train, y_train), (X_test, y_test) = imdb.load_data(nb_words = max_features) <font color="green"># Устанавливаем максимальную длину рецензий в словах, чтобы они все были одной длины</font> maxlen = <font color="blue">80</font> <font color="green"># Заполняем короткие рецензии пробелами, а длинные обрезаем</font> X_train = sequence.pad_sequences(X_train, maxlen = maxlen) X_test = sequence.pad_sequences(X_test, maxlen = maxlen) <font color="green"># Создаем модель последовательной сети</font> model = Sequential() <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>)) <font color="green"># Добавляем полносвязный слой из 1 элемента для классификации, в качестве функции активации будем использовать сигмоидальную функцию</font> 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>]) <font color="green"># Обучаем нейронную сеть (данные для обучения, ответы к данным для обучения, количество рецензий после анализа которого будут изменены веса, число эпох обучения, тестовые данные, показывать progress bar или нет)</font> 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>))
# Указываем количество слов из частотного словаря, которое будет использоваться (отсортированы по частоте использования)max_features = 5000 # Загружаем данные (датасет IMDB содержит 25000 рецензий на фильмы с правильным ответом для обучения и 25000 рецензий на фильмы с правильным ответом для тестирования)(X_train, y_train), (X_test, y_test) = imdb.load_data(nb_words = max_features) # Устанавливаем максимальную длину рецензий в словах, чтобы они все были одной длиныmaxlen Пример на языке Java= 80 # Заполняем короткие рецензии пробелами, а длинные обрезаемX_train = sequence.pad_sequences(X_train, maxlen = maxlen)X_test = sequence[https://github.pad_sequences(X_test, maxlen = maxlen) # Создаем модель последовательной сетиmodel = Sequential()# Добавляем слой для векторного представления слов (5000 слов, каждое представлено вектором из 32 чисел, отключаем входной сигнал с вероятностью 20% для предотвращения переобучения)model.add(Embedding(max_features, 32, dropout = 0.2))# Добавляем слой долгоcom/deeplearning4j/dl4j-examples/blob/master/dl4j-краткосрочной памяти (100 элементов для долговременного хранения информации, отключаем входной сигнал с вероятностью 20%, отключаем рекуррентный сигнал с вероятностью 20%)modelexamples/src/main/java/org/deeplearning4j/examples/recurrent/basic/BasicRNNExample.add(LSTM(100, dropout_W = 0.2, dropout_U = 0.2))# Добавляем полносвязный слой из 1 элемента для классификации, в качестве функции активации будем использовать сигмоидальную функциюmodel.add(Dense(1, activation = "sigmoid")) # Компилируем модель java Пример] простой рекуррентной нейронной сети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))с применением библиотеки <code>deeplearning4j</precode>.
==См. также==
*[[:Сверточные_нейронные_сети|Сверточные нейронные сети]]
*[[:Нейронные_сети,_перцептрон|Нейронные сети, перцептрон]]
*[[:Рекурсивные нейронные сети|Рекурсивные нейронные сети]]<sup>[на 28.01.19 не создан]</sup>
==Примечания==
<references/>
 
[[Категория: Машинное обучение]]
[[Категория: Нейронные сети]]
[[Категория: Рекуррентные нейронные сети]]
Анонимный участник

Навигация