假设我想手动计算相对于Kullback-Liebler散度损失的梯度更新,例如在变分自编码器(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(20×400)的形状不一致。比如,x只是一个400维的特征向量。那么我该如何在这个基础上进行随机梯度下降呢?x只是广播到第二个项吗,如果是,为什么?我觉得我在这里缺少一些数学理解…
回答:
让我们简化一下这个例子,假设一个全连接层,输入形状为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视为标量,而不是进行逐元素的偏导数计算。