close

5.2 十三個優化器

Optimizer 簡介

有了資料、模型和損失函數,就要選擇一個合適的優化器(Optimizer)來優化該模型,使loss不斷降低,直到模型收斂。本節將介紹pytorch中優化器——Optimizer 優化器的實現在torch.optim中,torch.optim is a package implementing various optimization algorithms. 在其中有一個核心類是OptimizerOptimizerpytorch提供的功能是所有具體優化器的基類,它對優化器進行了抽象與定義,約定了一個優化器應有的功能,Optimizer與十三個優化器的關係如下圖所示: 

<<AI人工智慧 PyTorch自學>> 5.2 十三個優化

通過上圖可知道Optimizer定義了優化器應當具備的基礎功能,如獲取狀態資料,載入狀態資料,梯度清零,執行一步優化和添加參數組。

不同的優化方法會繼承Optimizer,同時只需要實現不同的step()即可。這一點與損失函數類似,不同的損失函數只需要在forward()函數中定義好不同的公式計算即可。

本小節將以SGD為例,深入講解優化器的以下函數,並具體地觀察SGD演算法的實現過程。

state_dict(self)

load_state_dict(self, state_dict)

zero_grad(self, set_to_none: bool = False)

step(self, closure)

add_param_group(self, param_group)

優化器工作方式

優化器如何工作,使得模型精度逐漸提高的?在此就不詳細講解,請大家自行補充機器學習基礎概念。

眾所周知,優化器是根據權重的梯度作為指導,定義權重更新的力度,對權重進行更新

過程很簡單,實現起來卻是複雜的,上述過程涉及幾個問題:

  1. 梯度哪裡來?
  2. 更新哪些權重?
  3. 怎麼執行權重更新?

依次回答上述問題,便可熟悉優化器工作方式。

梯度哪裡來? 梯度通過loss的反向傳播,得到每個權重的梯度值,其中利用pytorchautograd機制自動求導獲得各權重的梯度。 (如果對autograd機制不熟悉,請查看第二章第六節)

更新哪些權重?通過loss的反向傳播,模型(nn.Module)的權重(Parameter)上有了梯度(.grad)值,但是優化器對哪些權重進行操作呢?實際上優化器會對需要操作的權重進行管理,只有被管理的權重,優化器才會對其進行操作。在Optimizer基類中就定義了add_param_group()函數來實現參數的管理。通常在產生實體的時候,第一個參數就是需要被管理的參數。

怎麼執行權重更新?通過上述UML類圖不難發現,step()函數是進行優化操作的,step()函數中實現了對所管理的參數進行更新的步驟。

總結一下:優化器在產生實體時告訴它,需要對哪些參數進行管理,然後再每個iteration反覆運算時,借助loss.backward()得到梯度,接著優化器幹活 optimizer.step()完成一步參數更新。

(此過程可以回顧第二章第二節的模型訓練代碼

優化器基類 Optimizer

Optimizer類是所有具體優化器的基類(Base class for all optimizers.

下面分別介紹Optimizer的基礎屬性及方法。

屬性

  1. 參數組(param_groups)

finetune、某層定制學習率,某層學習率置零操作中,都會設計參數組的概念,因此首先瞭解參數組的概念非常有必要。

參數組是用於管理需要進行優化的那些參數,例如權值weight,偏置biasBNalpha/beta等。

注意,這裡是參數組不是參數,表明可以將所有參數進行分組,區別對待。

例如在finetune過程中,通常讓前面層的網路採用較小的學習率,後面幾層全連接層採用較大的學習率,

這是我們就要把網路的參數劃分為兩組,每一組有它對應的學習率。正是因為這種針對不同參數需要不同的更新策略的需求,才有了參數組的概念。

參數組是一個list,其元素是一個dictdict中包含,所管理的參數,對應的超參,例如學習率,momentumweight_decay等等。

案例:chapter-5/02_optimizer.py

  1. state

用於存儲優化策略中需要保存的一些緩存值,例如在用momentum時,需要保存之前的梯度,這些資料保存在state中。

  1. defaults:

優化方法默認的超參數;

<<AI人工智慧 PyTorch自學>> 5.2 十三個優化

方法:

  1. zero_grad()

功能:清零所管理參數的梯度。由於pytorch不會自動清零梯度,因此需要再optimizer中手動清零,然後再執行反向傳播,得出當前iterationloss對權值的梯度。

  1. step()

功能:執行一步更新,依據當前的梯度進行更新參數

  1. add_param_group(param_group)

功能:給optimizer管理的參數組中增加一組參數,可為該組參數定制lr,momentum,weight_decay等,在finetune中常用。

例如:optimizer_1.add_param_group({'params': w3, 'lr': 0.001, 'momentum': 0.8})

  1. state_dict()

功能:獲取當前state屬性。

通常在保存模型時同時保存優化器狀態,用於中斷點保存,下次繼續從當前狀態訓練;

  1. load_state_dict(state_dict)

功能:載入所保存的state屬性,恢復訓練狀態。

對優化器工作方式熟悉後,再看Optimizer的屬性和方法就簡單了,下面通過一個具體的優化演算法來熟悉完整的優化器使用。

SGD概念

torch.optim.SGD詳情請參照[官方文檔](

https://pytorch.org/docs/stable/generated/torch.optim.SGD.html#torch.optim.SGD)

SGD(stochastic gradient descent,隨機梯度下降)是深度學習模型優化過程中最基礎、最受歡迎、最穩定的一個,即使優化演算法層出不窮,僅pytorch就提供了十三個,但目前絕大多數論文中仍舊採用SGD進行訓練,因此SGD必須掌握。

SGD核心理論知識是梯度下降( gradient descent),即沿著梯度的負方向,是變化最快的方向。

而隨機則指的是一次更新中,採用了一部分樣本進行計算,即一個batch的資料可以看作是整個訓練樣本的隨機採樣。更多關於SGD的理論知識請自行學習機器學習基礎。

SGD更新公式可簡化為 w = w - w_grad,即參數減去梯度(學習率為1

不過通常會加入學習率來調整更新的步伐:w_ = w_ - (lr * w_grad)

對於加入L2正則(weight decay)時,變為:w_ = w_ - (lr (w_grad + weight_decay w_))

L2正則稱之為weight decay的原因,對比公式1發現W需要乘以一個小於1的係數,因此是衰減的:w_ = w_ - (lr (w_grad + weight_decay w_)) = w_舊(1 - lrweight_decay) - (lr w_grad)

對於其它momentum dampening nesterov 的加入就不詳細展開,可通過官方文檔查閱:

<<AI人工智慧 PyTorch自學>> 5.2 十三個優化

 

SGD使用

請結合代碼觀察SGD的使用

第一步:產生實體:optimizer = optim.SGD(model.parameters(), lr=0.1, momentum=0.9, weight_decay=5e-4)

第二步:loss.backward()之前進行梯度清零:optimizer.zero_grad()

第三步:loss.backward()之後執行一步更新:optimizer.step()

在代碼中還有一處用到了optimizer,那就是學習率調整模組:

scheduler = optim.lr_scheduler.StepLR(optimizer, gamma=0.1, step_size=50)

原理是將optimizer放到lr_scheduler進行管理,lr_scheduler會修改optimizer中的學習率

SGD代碼實現

SGD類繼承於Optimizer類,並重寫step函數實現核心功能。

SGD類中step函數首先對各參數組、參數進行超參數的獲取確定:for group in self.param_groups:

然後借助functional.sgd函數實現公式計算:

            F.sgd(params_with_grad,

                  d_p_list,

                  momentum_buffer_list,

                  weight_decay=weight_decay,

                  momentum=momentum,

                  lr=lr,

                  dampening=dampening,

                  nesterov=nesterov,

                  maximize=maximize,)

Copy

下面重點進入/torch/optim/_functional.py sgd()觀察:這裡為了講解過程,省略了momentum的代碼:

<<AI人工智慧 PyTorch自學>> 5.2 十三個優化

d_p:是梯度

weight_decay:是權重衰減係數,如 0.0001

param:是具體的權重參數

lr:是學習率

194行代碼: param = param + (alpha)* d_p

193行代碼: param = param + (-lr) d_p = **param - lr \ d_p**

177行代碼: param = param - lr (d_p + weight_decay param) = param(1 - lr * weight_decay) - lr*d_p

到這裡,就可以與上述理論部分對應上了。

小結

其餘十二個優化器可通過官方文檔查閱,相信大家熟悉SGD以及優化器使用邏輯,其它的優化器都可輕鬆掌握。

Adadelta

Implements Adadelta algorithm.

Adagrad

Implements Adagrad algorithm.

Adam

Implements Adam algorithm.

AdamW

Implements AdamW algorithm.

SparseAdam

Implements lazy version of Adam algorithm suitable for sparse tensors.

Adamax

Implements Adamax algorithm (a variant of Adam based on infinity norm).

ASGD

Implements Averaged Stochastic Gradient Descent.

LBFGS

Implements L-BFGS algorithm, heavily inspired by minFunc.

NAdam

Implements NAdam algorithm.

RAdam

Implements RAdam algorithm.

RMSprop

Implements RMSprop algorithm.

Rprop

Implements the resilient backpropagation algorithm.

SGD

Implements stochastic gradient descent (optionally with momentum).

下面梳理pytorch整個優化器實現的邏輯關係:

<<AI人工智慧 PyTorch自學>> 5.2 十三個優化

 

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 HCHUNGW 的頭像
    HCHUNGW

    HCHUNGW的部落格

    HCHUNGW 發表在 痞客邦 留言(0) 人氣()