1. 程式人生 > >PyTorch學習系列(十)——如何在訓練時固定一些層?

PyTorch學習系列(十)——如何在訓練時固定一些層?

有時我們會用其他任務(如分類)預訓練好網路,然後固定卷積層作為影象特徵提取器,然後用當前任務的資料只訓練全連線層。那麼PyTorch如何在訓練時固定底層只更新上層呢?這意味著我們希望反向傳播計算梯度時,我們只希望計算到最上面的卷積層,對於卷積層,我們並不希望計算梯度並用梯度來更新引數。
我們知道,網路中的所有操作物件都是Variable物件,而Variable有兩個引數可以用於這個目的:requires_grad和volatile。

requires_grad=False

在使用者手動定義Variable時,引數requires_grad預設值是False。而在Module中的層在定義時,相關Variable的requires_grad引數預設是True。
在計算圖中,如果有一個輸入的requires_grad是True,那麼輸出的requires_grad也是True。只有在所有輸入的requires_grad都為False時,輸出的requires_grad才為False。

>>>x = Variable(torch.randn(2, 3), requires_grad=True)
>>>y = Variable(torch.randn(2, 3), requires_grad=False)
>>>z = Variable(torch.randn(2, 3), requires_grad=False)
>>>out1 = x+y
>>>out1.requires_grad
True
>>>out2 = y+z
>>>out2.requires_grad 
False

在訓練時如果想要固定網路的底層,那麼可以令這部分網路對應子圖的引數requires_grad為False。這樣,在反向過程中就不會計算這些引數對應的梯度:

model = torchvision.models.resnet18(pretrained=True)
for param in model.parameters():#nn.Module有成員函式parameters()
    param.requires_grad = False
# Replace the last fully-connected layer
# Parameters of newly constructed modules have requires_grad=True by default
model.fc = nn.Linear(512, 100)#resnet18中有self.fc,作為前向過程的最後一層。 # Optimize only the classifier optimizer = optim.SGD(model.fc.parameters(), lr=1e-2, momentum=0.9)#optimizer用於更新網路引數,預設情況下更新所有的引數

volatile=True

Variable的引數volatile=True和requires_grad=False的功能差不多,但是volatile的力量更大。當有一個輸入的volatile=True時,那麼輸出的volatile=True。volatile=True推薦在模型的推理過程(測試)中使用,這時只需要令輸入的voliate=True,保證用最小的記憶體來執行推理,不會儲存任何中間狀態。

>>> regular_input = Variable(torch.randn(5, 5))
>>> volatile_input = Variable(torch.randn(5, 5), volatile=True)
>>> model = torchvision.models.resnet18(pretrained=True)
>>> model(regular_input).requires_grad #輸出的requires_grad應該是True,因為中間層的Variable的requires_grad預設是True
True
>>> model(volatile_input).requires_grad#輸出的requires_grad是False,因為輸出的volatile是True(等價於requires_grad是False)
False
>>> model(volatile_input).volatile
True