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(_)