web-dev-qa-db-ja.com

pytorch .requires_grad Falseの設定方法

モデルの一部をフリーズしたい。公式ドキュメントに従って:

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

ただし、Trueの代わりにFalseを出力します。モデルをevalモードに設定する場合、どうすればよいですか?

16
Qian Wang

requires_grad = False

モデルの一部をフリーズして残りをトレーニングする場合は、フリーズするパラメーターのrequires_gradFalseに設定できます。

たとえば、VGG16の畳み込み部分のみを固定したい場合:

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

requires_gradフラグをFalseに切り替えると、演算の入力の1つが勾配を必要とするポイントに計算が到達するまで、中間バッファーは保存されません。

torch.no_grad()

コンテキストマネージャー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コンテキストで行われたため、勾配は計算されませんでした。

model.eval()

目標が微調整ではなく、モデルを推論モードに設定する場合、最も便利な方法はtorch.no_gradコンテキストマネージャーを使用することです。この場合、モデルを評価モードに設定する必要もあります。これは、nn.Moduleeval()を呼び出すことで実現できます。次に例を示します。

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

この操作は、レイヤーの属性self.trainingFalseに設定します。実際には、これはDropoutBatchNormなどの、トレーニング時とテスト時に異なる動作をする必要がある操作の動作を変更します。

20
iacolippo

ここに方法があります。

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)

出力:偽

5
Salih Karagoz

@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)
3
benjaminplanche

いいね秘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(_)
0
prosti

この チュートリアル が役立つ場合があります。

簡単に言えば、この質問の良い方法は次のようになると思います。

linear = nn.Linear(1,1)

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

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

0
Meiqi