Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/362.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 当我复制一个网络时,为什么它在Pytorch中';它的权重在反向传播后会自动更新吗?_Python_Machine Learning_Pytorch_Backpropagation - Fatal编程技术网

Python 当我复制一个网络时,为什么它在Pytorch中';它的权重在反向传播后会自动更新吗?

Python 当我复制一个网络时,为什么它在Pytorch中';它的权重在反向传播后会自动更新吗?,python,machine-learning,pytorch,backpropagation,Python,Machine Learning,Pytorch,Backpropagation,我编写了以下代码作为测试,因为在我最初的网络中,我使用moduledit,这取决于我提供的索引,它只对网络的一部分进行切片和训练 我想确保只有被切片的层才能更新它们的权重,所以我编写了一些测试代码来进行双重检查。我得到了一些奇怪的结果。假设我的模型有两层,第一层是FC,第二层是Conv2d,如果我分割网络,只使用第二层,我希望第一层的权重保持不变,因为它们未使用,第二层的权重将在1个历元后更新 因此,我的计划是在训练前使用for循环从网络中获取所有权重,然后在1optimizer.step()之

我编写了以下代码作为测试,因为在我最初的网络中,我使用moduledit,这取决于我提供的索引,它只对网络的一部分进行切片和训练

我想确保只有被切片的层才能更新它们的权重,所以我编写了一些测试代码来进行双重检查。我得到了一些奇怪的结果。假设我的模型有两层,第一层是FC,第二层是Conv2d,如果我分割网络,只使用第二层,我希望第一层的权重保持不变,因为它们未使用,第二层的权重将在1个历元后更新

因此,我的计划是在训练前使用
for
循环从网络中获取所有权重,然后在1
optimizer.step()之后执行。这两次我都会将这些权重完全分开存储在两个Python列表中,以便稍后比较它们的结果。出于某种原因,如果我将这两个列表与
torch.equal()
进行比较,它们是完全相同的。我认为这是因为内存中可能还有某种隐藏的链接?因此,当我从循环中抓取权重时,我尝试对权重使用
.detach()
,结果仍然相同。在这种情况下,第二层的权重应该不同,因为它应该包含训练前网络中的权重

在下面的代码中,我实际上使用了layer1而忽略了layer2

完整代码:

class mymodel(nn.Module):
    def __init__(self):
        super().__init__() 
        self.layer1 = nn.Linear(10, 5)
        self.layer2 = nn.Conv2d(1, 5, 4, 2, 1)
        self.act = nn.Sigmoid()
    def forward(self, x):
        x = self.layer1(x) #only layer1 and act are used layer 2 is ignored so only layer1 and act's weight should be updated
        x = self.act(x)
        return x
model = mymodel()

weights = []

for param in model.parameters(): # loop the weights in the model before updating and store them
    print(param.size())
    weights.append(param)

critertion = nn.BCELoss() #criterion and optimizer setup
optimizer = optim.Adam(model.parameters(), lr = 0.001)

foo = torch.randn(3, 10) #fake input
target = torch.randn(3, 5) #fake target

result = model(foo) #predictions and comparison and backprop
loss = criterion(result, target)
optimizer.zero_grad()
loss.backward()
optimizer.step()


weights_after_backprop = [] # weights after backprop
for param in model.parameters():
    weights_after_backprop.append(param) # only layer1's weight should update, layer2 is not used

for i in zip(weights, weights_after_backprop):
    print(torch.equal(i[0], i[1]))

# **prints all Trues when "layer1" and "act" should be different, I have also tried to call param.detach in the loop but I got the same result.

您必须
克隆
参数,否则只需复制引用即可

weights = []

for param in model.parameters():
    weights.append(param.clone())

criterion = nn.BCELoss() # criterion and optimizer setup
optimizer = optim.Adam(model.parameters(), lr=0.001)

foo = torch.randn(3, 10) # fake input
target = torch.randn(3, 5) # fake target

result = model(foo) # predictions and comparison and backprop
loss = criterion(result, target)
optimizer.zero_grad()
loss.backward()
optimizer.step()


weights_after_backprop = [] # weights after backprop
for param in model.parameters():
    weights_after_backprop.append(param.clone()) # only layer1's weight should update, layer2 is not used

for i in zip(weights, weights_after_backprop):
    print(torch.equal(i[0], i[1]))

False
False
True
True

非常感谢,我错了,我想detach()会做一些完全不同的事情,是时候再次查看文档了。对于任何想知道的人,在上面的代码中,我发现的唯一区别是:
对于model.parameters()中的param:weights.append(param.clone())