與優化函數相關的部分在torch.optim
模塊中,其中包含了大部分現在已有的流行的優化方法。
如何使用Optimizer
要想使用optimizer,需要創建一個optimizer 對象,這個對象會保存當前狀態,並根據梯度更新參數。
怎樣構造Optimizer
要構造一個Optimizer
,需要使用一個用來包含所有參數(Tensor
形式)的iterable,把相關參數(如learning rate、weight decay等)裝進去。
注意,如果想要使用.cuda()
方法來將model移到GPU中,一定要確保這一步在構造Optimizer
之前。因爲調用.cuda()
之後,model裏面的參數已經不是之前的參數了。
示例代碼如下:
optimizer = optim.SGD(model.parameters(), lr = 0.01, momentum = 0.9)
optimizer = optim.Adam([var1, var2], lr = 0.0001)
單獨指定參數
也可以用一個dict的iterable指定參數。這裏的每個dict都必須要params
這個key,params
包含它所屬的參數列表。除此之外的key必須它的Optimizer
(如SGD
)裏面有的參數。
You can still pass options as keyword arguments. They will be used as defaults, in the groups that didn’t override them. This is useful when you only want to vary a single option, while keeping all others consistent between parameter groups.
這在針對特定部分進行操作時很有用。比如只希望給指定的幾個層單獨設置學習率:
optim.SGD([
{'params': model.base.parameters()},
{'params': model.classifier.parameters(), 'lr': 0.001}
],
lr = 0.01, momentum = 0.9)
在上面這段代碼中model.base
將會使用默認學習率0.01,而model.classifier
的參數蔣歡使用0.001的學習率。
怎樣進行單次優化
所有optimizer都實現了step()
方法,調用這個方法可以更新參數,這個方法有以下兩種使用方法:
optimizer.step()
多數optimizer裏都可以這麼做,每次用backward()
這類的方法計算出了梯度後,就可以調用一次這個方法來更新參數。
示例程序:
for input, target in dataset:
optimizer.zero_grad()
ouput = model(input)
loss = loss_fn(output, target)
loss.backward()
optimizer.step()
optimizer.step(closure)
有些優化算法會多次重新計算函數(比如Conjugate Gradient、LBFGS),這樣的話你就要使用一個閉包(closure)來支持多次計算model的操作。這個closure的運行過程是,清除梯度,計算loss,返回loss。
(這個我不太理解,因爲這些優化算法不熟悉)
示例程序:
for input, target in dataset:
def closure():
optimizer.zero_grad()
output = model(input)
loss = loss_fn(output, target)
loss.backward()
return loss
optimizer.step(closure)
優化算法
這裏就不完整介紹documentation中的內容了,只介紹基類。具體的算法的參數需要理解它們的原理才能明白,這個改天單獨來一篇文章介紹。
Optimizer
class torch.optim.Optimizer(params, defaults)
這是所有optimizer的基類。
注意,各參數的順序必須保證每次運行都一致。有些數據結構就不滿足這個條件,比如dictionary的iterator和set。
參數
params
(iterable)是torch.Tensor
或者dict
的iterable。這個參數指定了需要更新的Tensor。defaults
(dict)是一個dict,它包含了默認的的優化選項。
方法
add_param_group(param_group)
這個方法的作用是增加一個參數組,在fine tuning一個預訓練的網絡時有用。
load_state_dict(state_dict)
這個方法的作用是加載optimizer的狀態。
state_dict()
獲取一個optimizer的狀態(一個dict)。
zero_grad()
方法用於清空梯度。
step(closure)
用於進行單次更新。
Adam
class torch.optim.Adam(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08, weight_decay=0, amsgrad=False)