卡住pytorch中的权重以进行param_groups设置。

因此,如果您想在训练期间卡住体重:

for param in child.parameters():
    param.requires_grad = False

优化器也必须更新为不包含非梯度权重:
optimizer = torch.optim.Adam(filter(lambda p: p.requires_grad, model.parameters()), lr=opt.lr, amsgrad=True)

如果要使用不同的weight_decay/学习率作为偏倚和权重,这也可以使用不同的学习率:
param_groups = [{'params': model.module.bias_parameters(), 'weight_decay': args.bias_decay},
                {'params': model.module.weight_parameters(), 'weight_decay': args.weight_decay}]
param_groups定义了一组dic,并将其传递到SGD中,如下所示:
optimizer = torch.optim.Adam(param_groups, args.lr,
                                 betas=(args.momentum, args.beta))

如何通过卡住单个重量来实现?在dic列表上运行filter还是有办法单独向优化器添加张量?

最佳答案

实际上,我认为您不必更新optimizer。移交给Parametersoptimizer只是引用。

因此,当您更改requires_grad标志时,它将立即被更新。

但是,即使出于某种原因,情况并非如此-将requires_grad标志设置为False后,您就无法再为此重量计算任何新的梯度(请参见底部的None和零梯度),因此渐变不会再改变了,如果您使用optimizer.zero_grad(),它将保持为zero

因此,如果没有渐变,则也无需将它们从optimizer中排除。因为没有梯度,不管您使用什么学习速率,optimizer都将不起作用。

这是显示此行为的一个小示例:

import torch
import torch.nn as nn
import torch.optim as optim

n_dim = 5

p1 = nn.Linear(n_dim, 1)
p2 = nn.Linear(n_dim, 1)

optimizer = optim.Adam(list(p1.parameters())+list(p2.parameters()))
p2.weight.requires_grad = False
for i in range(4):
    dummy_loss = (p1(torch.rand(n_dim)) + p2(torch.rand(n_dim))).squeeze()
    optimizer.zero_grad()
    dummy_loss.backward()
    optimizer.step()
    print('p1: requires_grad =', p1.weight.requires_grad, ', gradient:', p1.weight.grad)
    print('p2: requires_grad =', p2.weight.requires_grad, ', gradient:', p2.weight.grad)
    print()

    if i == 1:
        p1.weight.requires_grad = False
        p2.weight.requires_grad = True

输出:

p1: requires_grad = True , gradient: tensor([[0.8522, 0.0020, 0.1092, 0.8167, 0.2144]])
p2: requires_grad = False , gradient: None

p1: requires_grad = True , gradient: tensor([[0.7635, 0.0652, 0.0902, 0.8549, 0.6273]])
p2: requires_grad = False , gradient: None

p1: requires_grad = False , gradient: tensor([[0., 0., 0., 0., 0.]])
p2: requires_grad = True , gradient: tensor([[0.1343, 0.1323, 0.9590, 0.9937, 0.2270]])

p1: requires_grad = False , gradient: tensor([[0., 0., 0., 0., 0.]])
p2: requires_grad = True , gradient: tensor([[0.0100, 0.0123, 0.8054, 0.9976, 0.6397]])

在这里您可以看到没有计算梯度。您可能已经注意到p2的梯度在开始时是None,后来在停用梯度后,它是tensor([[0., 0., 0., 0., 0.]])p1而不是None

之所以如此,是因为p1.weight.grad只是一个由backward()optimizer.zero_grad()修改的变量。

因此,在一开始,p1.weight.grad只是用None初始化,在将梯度写入或累积到此变量之后,它们不会自动清除。但是由于optimizer.zero_grad()被调用,它们被设置为零并保持这种状态,因为backward()无法再使用requires_grad=False计算新的渐变。

您还可以将if -statement中的代码更改为:

if i == 1:
    p1.weight.requires_grad = False
    p1.weight.grad = None
    p2.weight.requires_grad = True

因此,一旦重置为None,它们将保持不变并保持None:

p1: requires_grad = True , gradient: tensor([[0.2375, 0.7528, 0.1501, 0.3516, 0.3470]])
p2: requires_grad = False , gradient: None

p1: requires_grad = True , gradient: tensor([[0.5181, 0.5178, 0.6590, 0.6950, 0.2743]])
p2: requires_grad = False , gradient: None

p1: requires_grad = False , gradient: None
p2: requires_grad = True , gradient: tensor([[0.4797, 0.7203, 0.2284, 0.9045, 0.6671]])

p1: requires_grad = False , gradient: None
p2: requires_grad = True , gradient: tensor([[0.8344, 0.1245, 0.0295, 0.2968, 0.8816]])

我希望这对您有意义!

关于python - pytorch卡住权重并更新param_groups,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53159427/

10-13 08:55