Странный результат с функцией градиента Julia Flux
После моего последнего вопроса о путанице при обучении повторяющейся нейронной сети с использованием Flux я углубился в процесс обучения Flux, и теперь я еще больше сбит с толку. Я думаю, что моя проблема связана с использованием суммы в функции, так что потеря учитывает множество точек в последовательности. См. Здесь, где убыток определяется как:
loss(x, y) = sum((Flux.stack(m.(x),1) .- y) .^ 2)
Если это последовательность с несколькими точками, и это соответствующий выход для каждой точки, эта функция оценивает потери для всей последовательности. Я пытаюсь понять, как Flux принимает градиент такой функции. Представьте, что упростите его до:
L(x, y) = sum((Flux.stack(rnn1.(xs), 1) .- y))
Мы также можем создать очень простую рекуррентную нейронную «сеть» в виде одного узла 1 -> 1 без функции активации:
m = Flux.RNN(1, 1, x -> x)
Это (вроде) эквивалент:
h = [0.0]
function m(x)
y = Wx .* x + Wh .* h .+ b
global h = y
return y
end
Какой градиент
loss
относительно
Wx
? Возьмем последовательность с двумя точками, x = [x1, x2] и y * = [y1 *, y2 *]. Поместите x1 через RNN, и вы получите:
y1 = h2 = Wx*x1 + Wh*h1 + b
Затем введите x2, и вы получите:
y2 = h3 = Wx * x2 + Wh* h2 + b = Wx * x2 + Wh* (Wx * x1 + Wh * h1 + b) + b.
Теперь посчитаем убыток:
L = y1 - y1 * + y2 - y2 * = Wx*x1 + Wh*h1 + b - y1 * + Wx * x2 + Wh* (Wx * x1 + Wh * h1 + b) + b - y2 *
Кажется очевидным, что dL / dWx должно быть x1 + x2 + Wh* x1. Итак, скажем
x
и
y
находятся:
x = [[0.3], [2.5]]
y = [0.5, 1.0]
и параметры инициализируются следующим образом:
Wxs = [0.5]
Whs = [0.001]
bs = [0.85]
Если вычислить dL / DWx = x1 + x2 + Wh* x1, получится 2,8003. Вы также можете попробовать конечную разницу:
h = [0.0]
q = loss(x, y)
Wx .+= 0.01
h = [0.0]
r = loss(x, y)
abs(q - r)/0.01 # = 2.8003
и получаем 2.8003. Но если вы используете функцию Flux:
Wx = [0.5]
h = [0.0]
gs = gradient(() -> loss(x, y), params(Wx, Wh, b))
gs[Wxs] # = 2.8025
вы получите 2,8025, что похоже на x1 + x2 + Wh* x2. Я не понимаю, почему результаты разные, особенно если учесть, что все согласуется при оценке самих двух разных функций потерь. Я что-то не замечаю? Что-то странное происходит в
gradient
?