#debugging #machine-learning #neural-network #deep-learning #recurrent-neural-network
#отладка #машинное обучение #нейронная сеть #глубокое обучение #рекуррентная нейронная сеть
Вопрос:
В настоящее время я пишу свой собственный RNN с нуля, используя практически только numpy. Я в основном застрял, потому что я проверил все градиенты с каждого отдельного слоя, и у меня есть все модульные тесты здесь:https://github.com/OneRaynyDay/BibleNet/blob/master/Unit tests.ipynb
https://github.com/OneRaynyDay/BibleNet/blob/master/Gradient Solver Unit Test.ipynb
Однако, когда я выполняю обратное распространение в своей сети с относительно разумной инициализацией весов и модульными оптимизаторами градиента (), я вижу, что график ОПРЕДЕЛЕННО не то, что я хочу. Я перешел к относительно простому корпусу, который в основном представляет собой эту статью отсюда:http://www.dailycal.org/2016/10/18/students-gather-hear-faculty-speak-trump-teach / который составляет менее 1000 слов, его должно быть очень легко переопределить. Однако функция затрат выглядит примерно так: Это определенно не то, что сходится. Он прыгает вверх и вниз, как будто на самом деле ничему не учится. Что я должен делать с точки зрения отладки?
Я не могу предоставить MVCE для этого примера просто потому, что это ошибка функционального теста, которая объединяет все части библиотеки, которую я создал. Следовательно, MVCE — это весь проект. Не стесняйтесь клонировать его с github.
Подозрительные места
Я чувствую, что ошибка возникает из-за моей архитектуры нейронной сети. Возможно, способ, которым я обрабатываю продолжающиеся итерации, неверен. Вот увеличенный код:
# Save typing
c = lambda arg: self.constants[arg]
p = lambda arg: self.params[arg]
# Step 1: Word embedding forward:
words_chosen = word_embedding_forward(p("words"), x)
# Step 2: rnn forward:
h = rnn_forward(words_chosen, p("W_xh"), p("W_hh"), p("b_rnn"), h0)
# Step 3: affine forward:
affine = rnn_affine_forward(h, p("W_hy"), p("b_affine"))
# step 4: softmax forward and backward:
loss, dout = rnn_softmax(affine, y)
# step 3: affine backward:
dh, dW_hy, db_affine = rnn_affine_backward(h, p("W_hy"), p("b_affine"), dout)
# step 2: rnn backward:
dW_hh, dW_xh, dx, db_rnn, dh0 = rnn_backward(words_chosen, p("W_xh"), p("W_hh"), p("b_rnn"), h0, h, dh)
# step 1: Word embedding backward:
dwords = word_embedding_backward(dx, p("words"), x)
# Returns the loss and all the derivatives along with the fields.
return (loss, [[p("words"), dwords],
[p("W_xh"), dW_xh],
[p("W_hh"), dW_hh],
[p("W_hy"), dW_hy],
[p("b_affine"), db_affine],
[p("b_rnn"), db_rnn],
[h0, dh0]], h[:,-1,:])
Другое подозрение заключается в том, что я неправильно обрабатываю скрытые состояния. Я беру скрытое состояние из предыдущего образца и подключаю это состояние скрытого слоя прямо к следующему образцу.
Вот иллюстрация: [a,b,c,d,e,f,g] is the sequence
input (a,b,c) -> (b,c,d) output (uses zeros as initial hidden layer)
We skip over to d: input (d,e,f) -> (e,f,g) output (uses previous hidden state of c)
Комментарии:
1. Проверяли ли вы свои нормы градиента с течением времени? С помощью Vanilla RNN вы легко переходите к появлению / исчезновению градиентов.
2. Привет — нет, у меня нет, но проблема в том, что это происходит даже при размере временной последовательности 2, где градиент взрыва / исчезновения не так очевиден. (На самом деле, приведенный здесь график имеет размер временного шага 2)