モデルの一部をフリーズしたい。公式ドキュメントに従って:
with torch.no_grad():
linear = nn.Linear(1, 1)
linear.eval()
print(linear.weight.requires_grad)
ただし、True
の代わりにFalse
を出力します。モデルをevalモードに設定する場合、どうすればよいですか?
モデルの一部をフリーズして残りをトレーニングする場合は、フリーズするパラメーターのrequires_grad
をFalse
に設定できます。
たとえば、VGG16の畳み込み部分のみを固定したい場合:
model = torchvision.models.vgg16(pretrained=True)
for param in model.features.parameters():
param.requires_grad = False
requires_grad
フラグをFalse
に切り替えると、演算の入力の1つが勾配を必要とするポイントに計算が到達するまで、中間バッファーは保存されません。
コンテキストマネージャーtorch.no_grad
を使用することは、その目標を達成するための別の方法です。no_grad
コンテキストでは、入力にrequires_grad=False
が含まれる場合でも、計算のすべての結果に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
コンテキストで行われたため、勾配は計算されませんでした。
目標が微調整ではなく、モデルを推論モードに設定する場合、最も便利な方法はtorch.no_grad
コンテキストマネージャーを使用することです。この場合、モデルを評価モードに設定する必要もあります。これは、nn.Module
でeval()
を呼び出すことで実現できます。次に例を示します。
model = torchvision.models.vgg16(pretrained=True)
model.eval()
この操作は、レイヤーの属性self.training
をFalse
に設定します。実際には、これはDropout
やBatchNorm
などの、トレーニング時とテスト時に異なる動作をする必要がある操作の動作を変更します。
ここに方法があります。
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)
出力:偽
@Salih_Karagozの答えを完成させるために、 torch.set_grad_enabled()
コンテキスト(詳細なドキュメント here )があり、これを使用してtrain/evalモードを簡単に切り替えることができます。
linear = nn.Linear(1,1)
is_train = False
with torch.set_grad_enabled(is_train):
linear.eval()
print(linear.weight.requires_grad)
いいね秘Theは、線形レイヤーを定義するときに、デフォルトでパラメーターに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
を本当にオフにする予定がある場合は、次の方法でも実行できます。
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(_)
この チュートリアル が役立つ場合があります。
簡単に言えば、この質問の良い方法は次のようになると思います。
linear = nn.Linear(1,1)
for param in linear.parameters():
param.requires_grad = False
linear.eval()
print(linear.weight.requires_grad)