作者:xaipxan
链接:https://www.zhihu.com/question/322192259/answer/749589285
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
对于两个net1 net2两个网络,如何同时反向传播。
对于这个问题,我自己做过简陋的实验。
x = torch.rand(2, 3)
net1 = nn.Linear(3, 3)
net2 = nn.Linear(3, 3)
a = net1(x)
b = net2(a)
tgt = torch.rand(2, 3)
loss_fun = torch.nn.MSELoss()
opt1 = torch.optim.Adam(net1.parameters(), 0.002)
opt2 = torch.optim.Adam(net2.parameters(), 0.002)
for i in range(100):
tmp = net1(x)
output = net2(tmp)
loss = loss_fun(output, tgt)
net1.zero_grad()
net2.zero_grad()
loss.backward()
opt1.step()
opt2.step()
print('EPOCH:{},loss={}'.format(i, loss))
aa = net1(x)
bb = net2(aa)
print(a)
print(aa)
print(b)
print(bb)
先建立两个网络net1和net2,把net1的输出再输入net2 。
目的是用训练之前的net1输出a 和 net2输出b对比训练后的net1输出aa和net2输出bb。
训练中是net1用opt1(adam)优化,net2用opt2(adam)优化。
结果是a和aa,b和bb都不一样。说明权重得到了训练或者说发生了改变。
之后再用一个net把net1和net2封装进去。
xx = torch.rand(2, 3)
class net(nn.Module):
def __init__(self):
super().__init__()
self.n1 = nn.Linear(3, 3)
self.n2 = nn.Linear(3, 3)
def forward(self, xx):
output = self.n1(xx)
print(output)
output = self.n2(output)
return output
n = net()
tgt = torch.rand(2, 3)
loss_fun = torch.nn.MSELoss()
opt_n = torch.optim.Adam(n.parameters(), 0.002)
for i in range(100):
outout = n(xx)
loss = loss_fun(outout, tgt)
n.zero_grad()
loss.backward()
opt_n.step()
print('EPOCH:{},loss={}'.format(i, loss))
目的跟之前的一样。
在net的forward的部分屏幕打印出net1的输出,方便观察每次输出的矩阵跟之前的一样否。
跟之前的不同的是这次只需要优化net一个的就可以了。
分割线
就像encoder-decoder网络一样,有些人是各自写完class encoder和class decoder后把他们装进class net中。这样只需要优化net的参数即可。
有些人喜欢用两个opt各自优化encoder和decoder的参数。
效果一样。
所以上面结果梯度传播并不会有问题,可以正常训练。