我将通过递归神经网络(RNN)实现二进制加法。我已经解决了使用Python实施该问题的问题,因此我决定在那里分享我的问题,以提出解决问题的想法。
从我的notebook code(时间反向传播(BPTT)部分中可以看出,如下所示,有一个链规则可以更新输入权重矩阵,如下所示:
我的问题是这部分:
我已经尝试在Python code或notebook code(class input_layer
,backward
方法)中实现此部分,但是尺寸不匹配会引发错误。
在我的示例代码中,W_hidden
为16*16
,而delta pre_hidden
的结果为1*2
。这会导致错误。如果运行代码,则可能会看到错误。
我花了很多时间来检查链式规则和代码。我猜我的连锁规则是正确的。导致此错误的唯一原因是我的代码。
据我所知,就维度而言,多个不匹配的矩阵是不可能的。如果我的链式规则正确,那么如何用Python实现呢?有什么主意吗?
提前感谢。
您需要在渐变上应用尺寸平衡。取自Stanford's cs231n课程,它归结为两个简单的修改:
鉴于和,我们将拥有:
,
这是我用来确保梯度计算正确的代码。您应该能够相应地更新代码。
import torch
torch.random.manual_seed(0)
x_1, x_2 = torch.zeros(size=(1, 8)).normal_(0, 0.01), torch.zeros(size=(1, 8)).normal_(0, 0.01)
y = torch.zeros(size=(1, 8)).normal_(0, 0.01)
h_0 = torch.zeros(size=(1, 16)).normal_(0, 0.01)
weight_ih = torch.zeros(size=(8, 16)).normal_(mean=0, std=0.01).requires_grad_(True)
weight_hh = torch.zeros(size=(16, 16)).normal_(mean=0, std=0.01).requires_grad_(True)
weight_ho = torch.zeros(size=(16, 8)).normal_(mean=0, std=0.01).requires_grad_(True)
h_1 = x_1.mm(weight_ih) + h_0.mm(weight_hh)
h_2 = x_2.mm(weight_ih) + h_1.mm(weight_hh)
g_2 = h_2.sigmoid()
j_2 = g_2.mm(weight_ho)
y_predicted = j_2.sigmoid()
loss = 0.5 * (y - y_predicted).pow(2).sum()
loss.backward()
delta_1 = -1 * (y - y_predicted) * y_predicted * (1 - y_predicted)
delta_2 = delta_1.mm(weight_ho.t()) * (g_2 * (1 - g_2))
delta_3 = delta_2.mm(weight_hh.t())
# 16 x 8
weight_ho_grad = g_2.t() * delta_1
# 16 x 16
weight_hh_grad = h_1.t() * delta_2 + (h_0.t() * delta_3)
# 8 x 16
weight_ih_grad = x_2.t() * delta_2 + x_1.t() * delta_3
atol = 1e-10
assert torch.allclose(weight_ho.grad, weight_ho_grad, atol=atol)
assert torch.allclose(weight_hh.grad, weight_hh_grad, atol=atol)
assert torch.allclose(weight_ih.grad, weight_ih_grad, atol=atol)