close

5.3 學習率調整策略

 

<<AI人工智慧 PyTorch自學>> 5.3 學習率調整

 

深度學習模型訓練中調整最頻繁的就屬學習率了,好的學習率可以使模型逐漸收斂並獲得更好的精度。

本小節將介紹pytorch提供的十四種學習率調整方法,首先瞭解lr_scheduler整體結構設計,然後以StepLR為例,深度剖析一個學習率調整器的原始程式碼實現細節,最後總結十四個學習率調整策略。

lr_scheduler 設計

lr_scheduler模組的設計與優化器一樣,定義了一個核心基類_LRScheduler,在_LRScheduler中設計好學習率調整器的屬性與方法。

 

 

核心屬<<AI人工智慧 PyTorch自學>> 5.3 學習率調整性有optimizerbase_lrslast_epoch

optimizer是調整器所管理的優化器,優化器中所管理的參數組有對應的學習率,調整器要調整的內容就在那裡。

base_lrs是基礎學習率,來自於optimizer一開始設定的那個值。self.base_lrs = [group['initial_lr'] for group in optimizer.param_groups]

last_epoch是記錄反覆運算次數,通常用於計算下一輪學習率。注意,默認初始值是-1,因為last_epoch的管理邏輯是執行一次,自加1

核心方法有state_dict()load_state_dict()get_last_lr()get_lr()print_lr()step()

state_dict()load_state_dict()分別是獲取調整器的狀態資料與載入狀態資料。

get_last_lr()get_lr() 分別為獲取上一次和當前的學習率。

print_lr()是列印學習率。

step()為更新學習率的介面函數,使用者調用 scheduler.step()即完成一次更新。

lr_scheduler 使用流程

第一步:產生實體。scheduler = optim.lr_scheduler.StepLR(optimizer, gamma=0.1, step_size=50)

第二步:合適的位置執行step()。大家要注意,不同的調整器的更新策略是不一樣的,有的是基於epoch維度,有的是基於iteration維度,這個需要注意。

StepLR 原始程式碼解讀

StepLR是依據設定的step_size,以固定的間隔進行調整,調整規則為 lr_new = lr_old * gamma 通常gamma設置為0.1,即一定次數訓練後,學習率下降10倍。

下面觀察代碼,在代碼104行與146行打斷點進行調試,依次觀察初始化過程、step更新過程。

初始化過程

StepLR__init__()函數:

        self.step_size = step_size

        self.gamma = gamma

        super(StepLR, self).__init__(optimizer, last_epoch, verbose)

Copy

跳轉到_LRScheduler__init__()函數:

第一步:獲取初始學習率:group.setdefault('initial_lr', group['lr'])

第二步:記錄基礎學習率:self.base_lrs = [group['initial_lr'] for group in optimizer.param_groups]

self.last_epoch = last_epoch

第三步:執行首次step(),也就是在初始化的時候會自動執行一次step(),這也是為什麼last_epoch的預設值是-1的原因。

step中會進行第0epoch的學習率獲取,具體過程如代碼所示:

torch/optim/lr_scheduler.py 151168

        with _enable_get_lr_call(self):

            if epoch is None:

                self.last_epoch += 1

                values = self.get_lr()

            else:

                warnings.warn(EPOCH_DEPRECATION_WARNING, UserWarning)

                self.last_epoch = epoch

                if hasattr(self, "_get_closed_form_lr"):

                    values = self._get_closed_form_lr()

                else:

                    values = self.get_lr()

 

        for i, data in enumerate(zip(self.optimizer.param_groups, values)):

            param_group, lr = data

            param_group['lr'] = lr

            self.print_lr(self.verbose, i, lr, epoch)

 

        self._last_lr = [group['lr'] for group in self.optimizer.param_groups]

Copy

step更新過程

在初始化過程已經進行過一次step,這裡再仔細分析一遍。

首先通過154代碼,獲取新一輪學習率 values = self.get_lr()

然後通過165代碼,對優化器中的學習率進行更新param_group['lr'] = lr

可以發現step()函數由基類_LRScheduler實現,即所有學習率調整器均採用這個流程,具體的一步更新策略則委託給子類的.get_lr()函數,這樣的架構設計值得學習。

此處,關注的是StepLR,下面深入 StepLR.get_lr()函數觀察。

if (self.last_epoch == 0) or (self.last_epoch % self.step_size != 0):

    return [group['lr'] for group in self.optimizer.param_groups]

return [group['lr'] * self.gamma

        for group in self.optimizer.param_groups]

Copy

可以看到,核心在兩個return行。

第一個return表示未達到step_size,新學習率保持不變

第二個return表示達到step_size,學習率均需要乘以 gamma

至此,整個學習率更新過程及邏輯講解完畢,其餘十三個學習率調整整體邏輯一樣,均是step()get_lr()的配合來實現學習率調整,請大家舉一反三,自行深入研究其它調整器。

十四個調整器匯總

lr_scheduler.LambdaLR

Sets the learning rate of each parameter group to the initial lr times a given function.

lr_scheduler.MultiplicativeLR

Multiply the learning rate of each parameter group by the factor given in the specified function.

lr_scheduler.StepLR

Decays the learning rate of each parameter group by gamma every step_size epochs.

lr_scheduler.MultiStepLR

Decays the learning rate of each parameter group by gamma once the number of epoch reaches one of the milestones.

lr_scheduler.ConstantLR

Decays the learning rate of each parameter group by a small constant factor until the number of epoch reaches a pre-defined milestone: total_iters.

lr_scheduler.LinearLR

Decays the learning rate of each parameter group by linearly changing small multiplicative factor until the number of epoch reaches a pre-defined milestone: total_iters.

lr_scheduler.ExponentialLR

Decays the learning rate of each parameter group by gamma every epoch.

lr_scheduler.CosineAnnealingLR

Set the learning rate of each parameter group using a cosine annealing schedule, where \eta{max}ηmax is set to the initial lr and T{cur}Tcu**r is the number of epochs since the last restart in SGDR:

lr_scheduler.ChainedScheduler

Chains list of learning rate schedulers.

lr_scheduler.SequentialLR

Receives the list of schedulers that is expected to be called sequentially during optimization process and milestone points that provides exact intervals to reflect which scheduler is supposed to be called at a given epoch.

lr_scheduler.ReduceLROnPlateau

Reduce learning rate when a metric has stopped improving.

lr_scheduler.CyclicLR

Sets the learning rate of each parameter group according to cyclical learning rate policy (CLR).

lr_scheduler.OneCycleLR

Sets the learning rate of each parameter group according to the 1cycle learning rate policy.

lr_scheduler.CosineAnnealingWarmRestarts

Set the learning rate of each parameter group using a cosine annealing schedule, where \eta{max}ηmax is set to the initial lr, T{cur}Tcu**r is the number of epochs since the last restart and T_{i}T**i is the number of epochs between two warm restarts in SGDR:

小結

本小節通過lr_scheduler結構設計出發,分析十四個優化器是如何組織實現的,並通過_LRScheduler基類與StepLR的代碼講解學習率調整的機制。

總結下來即:初始化時建立scheduleroptimizer的聯繫,scheduler在每次step()時修改optimizer中的lrstep()獲取新lr的功能委託給get_lr()函數實現。

最後對六個學習率調整器進行了測試並繪圖,繪圖代碼位於配套代碼

 

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

    HCHUNGW的部落格

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