Расчет обновления градиента

Допустим, я хочу вручную рассчитать обновление градиента по отношению к потере расхождения Кульбака-Либлера, скажем, на VAE (см. фактический пример из документации образца pytorch здесь):

KLD = -0.5 * torch.sum(1 + logvar - mu.pow(2) - logvar.exp())

где logvar (для простоты, игнорируя функции активации, несколько слоев и т. д.) в основном представляет собой однослойное преобразование из 400-мерного вектора признаков в 20-мерный вектор:

self.fc21 = nn.Linear(400, 20)
logvar = fc21(x)

Я просто математически не понимаю, как вы берете градиент этого по отношению к вектору весов для fc21. Математически я думал, что это будет выглядеть так:

KL = -.5sum(1 + Wx + b - m^2 - e^{Wx + b})

dKL/dW = -,5 (x - e^{Wx + b}x)

где W — весовая матрица слоя fc21. Но здесь этот результат не такой, как у W (20x400). Например, x — это всего лишь вектор из 400 признаков. Итак, как мне выполнить SGD на этом? Передаёт ли x только второй термин, и если да, то почему? Я чувствую, что мне просто не хватает некоторого математического понимания здесь...


person Matt    schedule 30.03.2018    source источник


Ответы (1)


Давайте немного упростим пример и предположим полностью связанный слой входной формы 3 и выходной формы 2, тогда:

W = [[w1, w2, w3], [w4, w5, w6]]
x = [x1, x2, x3]
y = [w1*x1 + w2*x2 + w3*x3, w4*x1 + w5*x2 + w6*x3]
D_KL = -0.5 * [ 1 + w1*x1 + w2*x2 + w3*x3 + w4*x1 + w5*x2 + w6*x3 + b - m^2 + e^(..)] 
grad(D_KL, w1) = -0.5 * [x1 + x1* e^(..)]
grad(D_KL, w2) = -0.5 * [x2 + x2* e^(..)]
...
grad(D_KL, W) = [[grad(D_KL, w1), grad(D_KL, w2), grad(D_KL,w3)], 
                 [grad(D_KL, w4), grad(D_KL, w5), grad(D_KL,w6)]
                ]

Это обобщается для тензоров более высокого порядка любой размерности. Ваше дифференцирование неверно, когда вы рассматриваете x и W как скаляры, а не берете поэлементные частные производные.

person KonstantinosKokos    schedule 30.03.2018
comment
Да, мой плохой. Исправлено! - person KonstantinosKokos; 01.04.2018