pytorch как установить.requires_grad False

Я хочу, чтобы некоторые из моих моделей были заморожены. После официальных документов:

with torch.no_grad():
    linear = nn.Linear(1, 1)
    linear.eval()
    print(linear.weight.requires_grad)

Но он печатает True вместо False. Если я хочу установить модель в режиме eval, что мне делать?

Ответ 1

requires_grad = False

Если вы хотите заморозить часть своей модели и обучить остальных, вы можете установить requires_grad из параметров, которые хотите заморозить, для False.

Например, если вы хотите только сохранить сверточную часть VGG16:

model = torchvision.models.vgg16(pretrained=True)
for param in model.features.parameters():
    param.requires_grad = False

При переключении requires_grad флагов False, никаких промежуточных буфера не будут сохранены, пока вычисление не попадет в какой - то момент, когда один из входов операции требует градиента.

torch.no_grad()

Использование диспетчера контекста torch.no_grad - это другой способ достижения этой цели: в контексте no_grad все результаты вычислений будут иметь no_grad requires_grad=False, даже если входы requires_grad=True no_grad requires_grad=True. Обратите внимание, что вам не удастся отбросить градиент до слоев до no_grad. Например:

x = torch.randn(2, 2)
x.requires_grad = True

lin0 = nn.Linear(2, 2)
lin1 = nn.Linear(2, 2)
lin2 = nn.Linear(2, 2)
x1 = lin0(x)
with torch.no_grad():    
    x2 = lin1(x1)
x3 = lin2(x2)
x3.sum().backward()
print(lin0.weight.grad, lin1.weight.grad, lin2.weight.grad)

выходы:

(None, None, tensor([[-1.4481, -1.1789],
         [-1.4481, -1.1789]]))

Здесь lin1.weight.requires_grad был True, но градиент не был вычислен, потому что oepration был выполнен в контексте no_grad.

model.eval()

Если ваша цель не заканчиваться, но для установки вашей модели в режиме вывода наиболее удобным способом является использование torch.no_grad контекста torch.no_grad. В этом случае вам также необходимо настроить модель на режим оценки, это достигается путем вызова eval() в nn.Module, например:

model = torchvision.models.vgg16(pretrained=True)
model.eval()

Эта операция устанавливает атрибут self.training слоев в False, на практике это изменит поведение операций, таких как Dropout или BatchNorm которые должны вести себя по-разному на время обучения и тестирования.

Ответ 2

Вот путь;

linear = nn.Linear(1,1)

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

with torch.no_grad():
    linear.eval()
    print(linear.weight.requires_grad)

OUTPUT: False

Ответ 3

Чтобы завершить ответ @Salih_Karagoz, у вас также есть контекст torch.set_grad_enabled() (дополнительная документация здесь), который можно использовать для простого переключения между режимами поездов /eval:

linear = nn.Linear(1,1)

is_train = False
with torch.set_grad_enabled(is_train):
    linear.eval()
    print(linear.weight.requires_grad)

Ответ 4

Этот урок может помочь.

Короче говоря, я думаю, что хороший способ для этого вопроса может быть:

linear = nn.Linear(1,1)

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

linear.eval()
print(linear.weight.requires_grad)

Ответ 5

Ницца. Хитрость заключается в том, чтобы проверить, что при определении линейного слоя по умолчанию параметры будут иметь require_grad requires_grad=True, потому что мы хотели бы узнать, верно?

l = nn.Linear(1, 1)
p = l.parameters()
for _ in p:
    print (_)

# Parameter containing:
# tensor([[-0.3258]], requires_grad=True)
# Parameter containing:
# tensor([0.6040], requires_grad=True)    

Другая конструкция,

with torch.no_grad():

Означает, что вы не можете учиться здесь.

Таким образом, ваш код просто показывает, что вы способны к обучению, даже если вы находитесь в torch.no_grad() где обучение запрещено.

with torch.no_grad():
    linear = nn.Linear(1, 1)
    linear.eval()
    print(linear.weight.requires_grad) #true

Если вы действительно планируете отключить requires_grad для параметра weight, вы можете сделать это также с помощью:

linear.weight.requires_grad_(False)

или же

linear.weight.requires_grad = False

Таким образом, ваш код может выглядеть следующим образом:

with torch.no_grad():
    linear = nn.Linear(1, 1)
    linear.weight.requires_grad_(False)
    linear.eval()
    print(linear.weight.requires_grad)

Если вы планируете переключиться на require_grad для всех параметров в модуле:

l = nn.Linear(1, 1)
for _ in l.parameters():
    _.requires_grad_(False)
    print(_)