淺談Pytorch torch.optim優化器個性化的使用
阿新 • • 發佈:2020-02-21
一、簡化前饋網路LeNet
import torch as t class LeNet(t.nn.Module): def __init__(self): super(LeNet,self).__init__() self.features = t.nn.Sequential( t.nn.Conv2d(3,6,5),t.nn.ReLU(),t.nn.MaxPool2d(2,2),t.nn.Conv2d(6,16,2) ) # 由於調整shape並不是一個class層, # 所以在涉及這種操作(非nn.Module操作)需要拆分為多個模型 self.classifiter = t.nn.Sequential( t.nn.Linear(16*5*5,120),t.nn.Linear(120,84),t.nn.Linear(84,10) ) def forward(self,x): x = self.features(x) x = x.view(-1,16*5*5) x = self.classifiter(x) return x net = LeNet()
二、優化器基本使用方法
建立優化器例項
迴圈:
清空梯度
向前傳播
計算Loss
反向傳播
更新引數
from torch import optim # 通常的step優化過程 optimizer = optim.SGD(params=net.parameters(),lr=1) optimizer.zero_grad() # net.zero_grad() input_ = t.autograd.Variable(t.randn(1,3,32,32)) output = net(input_) output.backward(output) optimizer.step()
三、網路模組引數定製
為不同的子網路引數不同的學習率,finetune常用,使分類器學習率引數更高,學習速度更快(理論上)。
1.經由構建網路時劃分好的模組進行學習率設定,
# # 直接對不同的網路模組制定不同學習率 optimizer = optim.SGD([{'params': net.features.parameters()},# 預設lr是1e-5 {'params': net.classifiter.parameters(),'lr': 1e-2}],lr=1e-5)
2.以網路層物件為單位進行分組,並設定學習率
# # 以層為單位,為不同層指定不同的學習率 # ## 提取指定層物件 special_layers = t.nn.ModuleList([net.classifiter[0],net.classifiter[3]]) # ## 獲取指定層引數id special_layers_params = list(map(id,special_layers.parameters())) print(special_layers_params) # ## 獲取非指定層的引數id base_params = filter(lambda p: id(p) not in special_layers_params,net.parameters()) optimizer = t.optim.SGD([{'params': base_params},{'params': special_layers.parameters(),'lr': 0.01}],lr=0.001)
四、在訓練中動態的調整學習率
'''調整學習率''' # 新建optimizer或者修改optimizer.params_groups對應的學習率 # # 新建optimizer更簡單也更推薦,optimizer十分輕量級,所以開銷很小 # # 但是新的優化器會初始化動量等狀態資訊,這對於使用動量的優化器(momentum引數的sgd)可能會造成收斂中的震盪 # ## optimizer.param_groups:長度2的list,optimizer.param_groups[0]:長度6的字典 print(optimizer.param_groups[0]['lr']) old_lr = 0.1 optimizer = optim.SGD([{'params': net.features.parameters()},{'params': net.classifiter.parameters(),'lr': old_lr*0.1}],lr=1e-5)
可以看到optimizer.param_groups結構,[{'params','lr','momentum','dampening','weight_decay','nesterov'},{……}],集合了優化器的各項引數。
torch.optim的靈活使用
重寫sgd優化器
import torch from torch.optim.optimizer import Optimizer,required class SGD(Optimizer): def __init__(self,params,lr=required,momentum=0,dampening=0,weight_decay1=0,weight_decay2=0,nesterov=False): defaults = dict(lr=lr,momentum=momentum,dampening=dampening,weight_decay1=weight_decay1,weight_decay2=weight_decay2,nesterov=nesterov) if nesterov and (momentum <= 0 or dampening != 0): raise ValueError("Nesterov momentum requires a momentum and zero dampening") super(SGD,self).__init__(params,defaults) def __setstate__(self,state): super(SGD,self).__setstate__(state) for group in self.param_groups: group.setdefault('nesterov',False) def step(self,closure=None): """Performs a single optimization step. Arguments: closure (callable,optional): A closure that reevaluates the model and returns the loss. """ loss = None if closure is not None: loss = closure() for group in self.param_groups: weight_decay1 = group['weight_decay1'] weight_decay2 = group['weight_decay2'] momentum = group['momentum'] dampening = group['dampening'] nesterov = group['nesterov'] for p in group['params']: if p.grad is None: continue d_p = p.grad.data if weight_decay1 != 0: d_p.add_(weight_decay1,torch.sign(p.data)) if weight_decay2 != 0: d_p.add_(weight_decay2,p.data) if momentum != 0: param_state = self.state[p] if 'momentum_buffer' not in param_state: buf = param_state['momentum_buffer'] = torch.zeros_like(p.data) buf.mul_(momentum).add_(d_p) else: buf = param_state['momentum_buffer'] buf.mul_(momentum).add_(1 - dampening,d_p) if nesterov: d_p = d_p.add(momentum,buf) else: d_p = buf p.data.add_(-group['lr'],d_p) return loss
以上這篇淺談Pytorch torch.optim優化器個性化的使用就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。