<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          pytorch優(yōu)化器與學習率設(shè)置詳解

          共 8760字,需瀏覽 18分鐘

           ·

          2022-01-13 04:51

          點擊上方“程序員大白”,選擇“星標”公眾號

          重磅干貨,第一時間送達



          作者 | 小新
          來源 |?https://a.3durl.cn/YrcZbc
          編輯丨極市平臺
          本文僅作學術(shù)分享,版權(quán)屬于原作者,侵權(quán)請聯(lián)系刪文。

          導讀

          ?

          在很多學習過程中,都會采用動態(tài)調(diào)整學習率的方法。剛開始訓練的時候,學習率設(shè)置大一點,以加快學習速度;之后逐漸減小學習率,來尋找最優(yōu)解。那么在Pytorch中,如在訓練過程中動態(tài)地調(diào)整學習率呢?

          學習率設(shè)置對于學習過程來說相當重要。學習率過低會導致學習速度太慢,學習率過高又容易導致難以收斂。在很多學習過程中,都會采用動態(tài)調(diào)整學習率的方法。剛開始訓練的時候,學習率設(shè)置大一點,以加快學習速度;之后逐漸減小學習率,來尋找最優(yōu)解。

          那么在Pytorch中,如在訓練過程中動態(tài)地調(diào)整學習率呢?

          目錄

          • 優(yōu)化器Optimizer
            • 只訓練模型的一部分參數(shù)
            • 不同部分的參數(shù)設(shè)置不同的學習率(以及其他屬性)
            • Optimizer基本屬性
            • optimizer基本方法
          • 動態(tài)更新learning rate
            • torch.optim.lr_scheduler
            • torch.optim.lr_scheduler.LambdaLr
            • torch.optim.lr_scheduler.StepLR
            • torch.optim.lr_scheduler.MultiStepLR
            • torch.optim.lr_scheduler.ExponentialLR
            • torch.optim.lr_scheduler.CosineAnnealingLR
            • torch.optim.lr_scheduler.ReduceLROnPlateau
            • 手動修改lr

          優(yōu)化器Optimizer

          在說學習率調(diào)整方法之前,先來了解一下Pytorch中的優(yōu)化器Optimizer機制。

          用過Pytorch的都知道,模型訓練時的固定搭配。

          loss.backward()
          optimizer.step()
          optimizer.zero_grad()
          ...

          簡單來說,loss.backward()就是反向計算出各參數(shù)的梯度,然后optimizer.step()就是更新網(wǎng)絡(luò)中的參數(shù),optimizer.zero_grad()將這一輪的梯度清零,防止這一輪的梯度影響下一輪的更新。

          常用優(yōu)化器都在torch.optim包中,因此需要先導入包:

          import?torch.optim.Adam
          import?torch.optim.SGD

          這里以常用的Adam優(yōu)化器和SGD優(yōu)化器為例,介紹一下Pytorch中的優(yōu)化器使用方法。

          假設(shè)我們有一個網(wǎng)絡(luò)如下,下面的例子都以此網(wǎng)絡(luò)作為例子:

          class?Net(nn.Module):
          ????def?__init__(self):
          ????????super(Net,?self).__init__()
          ????????self.layer?=?nn.Linear(10,?2)
          ????????self.layer2?=?nn.Linear(2,?10)

          ????def?forward(self,?input):
          ????????return?self.layer(input)???????

          # Optimizer基本屬性

          所有Optimizer公有的一些基本屬性:

          • lr: learning rate,學習率
          • eps: 學習率最小值,在動態(tài)更新學習率時,學習率最小不會小于該值。
          • weight_decay: 權(quán)值衰減。相當于對參數(shù)進行L2正則化(使模型復雜度盡可能低,防止過擬合),該值可以理解為正則化項的系數(shù)。
          • betas: (待研究)
          • amsgrad: (bool)(待研究)

          每個Optimizer都維護一個param_groups的list。該list中維護需要優(yōu)化的參數(shù)以及對應(yīng)的屬性設(shè)置。

          optimizer基本方法

          • add_param_group(param_group): 為optimizer的param_groups增加一個參數(shù)組。這在微調(diào)預先訓練的網(wǎng)絡(luò)時非常有用,因為凍結(jié)層可以訓練并隨著訓練的進行添加到優(yōu)化器中。
          • load_state_dict(state_dict): 加載optimizer state。參數(shù)必須是optimizer.state_dict()返回的對象。
          • state_dict(): 返回一個dict,包含optimizer的狀態(tài):state和param_groups。
          • step(closure): 執(zhí)行一次參數(shù)更新過程。
          • zero_grad(): 清除所有已經(jīng)更新的參數(shù)的梯度。

          我們在構(gòu)造優(yōu)化器時,最簡單的方法通常如下:

          model?=?Net()
          optimizer_Adam?=?torch.optim.Adam(model.parameters(),?lr=0.1)

          model.parameters()返回網(wǎng)絡(luò)model的全部參數(shù)。

          將model的全部參數(shù)傳入Adam中構(gòu)造出一個Adam優(yōu)化器,并設(shè)置 learning rate=0.1。因此該 Adam 優(yōu)化器的 param_groups 維護的就是模型 model 的全部參數(shù),并且學習率為0.1。這樣在調(diào)用optimizer_Adam.step()時,就會對model的全部參數(shù)進行更新。

          Optimizer的param_groups是一個list,其中的每個元素都是一組獨立的參數(shù),以dict的方式存儲。結(jié)構(gòu)如下:

          -param_groups
          ????-0(dict)??#?第一組參數(shù)
          ????????params:??#?維護要更新的參數(shù)
          ????????lr:??#?該組參數(shù)的學習率
          ????????betas:
          ????????eps:??#?該組參數(shù)的學習率最小值
          ????????weight_decay:??#?該組參數(shù)的權(quán)重衰減系數(shù)
          ????????amsgrad:??
          ????-1(dict)??#?第二組參數(shù)
          ????-2(dict)??#?第三組參數(shù)
          ????...
          ????...

          這樣可以實現(xiàn)很多靈活的操作,比如以下。

          只訓練模型的一部分參數(shù)

          例如,只想訓練上面的model中的layer參數(shù),而保持layer2的參數(shù)不動。可以如下設(shè)置Optimizer:

          model?=?Net()
          optimizer_Adam?=?torch.optim.Adam(model.layer.parameters(),?lr=0.1)??#?只傳入layer層的參數(shù),就可以只更新layer層的參數(shù)而不影響其他參數(shù)。

          不同部分的參數(shù)設(shè)置不同的學習率(以及其他屬性)

          例如,要想使model的layer參數(shù)學習率為0.1,layer2的參數(shù)學習率為0.2,可以如下設(shè)置Optimizer:

          model?=?Net()
          params_dict?=?[{'params':?model.layer.parameters(),?'lr':?0.1},
          ???????????????????{'params':?model.layer2.parameters(),?'lr':?0.2}]
          optimizer_Adam?=?torch.optim.Adam(params_dict)

          這種方法更為靈活,手動構(gòu)造一個params_dict列表來初始化Optimizer。注意,字典中的參數(shù)部分的 key 必須為 ‘params’。

          這樣就可以靈活的設(shè)置Optimizer啦。

          動態(tài)更新learning rate

          了解了Optimizer的基本結(jié)構(gòu)和使用方法,接下來就可以看一下,如何在訓練過程中動態(tài)更新learning rate。

          手動修改lr

          上面我們了解到,Optimizer的每一組參數(shù)維護一個lr,因此,最直接的方法就是我們在訓練過程中手動修改Optimizer中對應(yīng)的lr的值:

          model?=?Net()??#?生成網(wǎng)絡(luò)
          optimizer_Adam?=?torch.optim.Adam(model.parameters(),?lr=0.1)??#?生成優(yōu)化器

          lr_list?=?[]
          for?epoch?in?range(100):??#?假設(shè)迭代100次
          ????if?epoch?%?5?==?0:??#?每迭代5次,更新一次學習率
          ????????for?params?in?optimizer_Adam.param_groups:??#?遍歷Optimizer中的每一組參數(shù)
          ????????????params['lr']?*=?0.9??#?將該組參數(shù)的學習率?*?0.9
          ????????????#?params['weight_decay']?=?0.5??#?當然也可以修改其他屬性
          ????lr_list.append(optimizer_Adam.state_dict()['param_groups'][0]['lr'])
          plt.plot(range(100),?lr_list,?color='r')
          plt.show()
          手動修改lr

          torch.optim.lr_scheduler

          torch.optim.lr_scheduler包中提供了一些類,用于動態(tài)修改lr。

          • torch.optim.lr_scheduler.LambdaLr
          • torch.optim.lr_scheduler.StepLR
          • torch.optim.lr_scheduler.MultiStepLR
          • torch.optim.lr_scheduler.ExponentialLR
          • torch.optim.lr_sheduler.CosineAnneaingLR
          • torch.optim.lr_scheduler.ReduceLROnPlateau

          注意: pytorch 1.1.0版本之后,在創(chuàng)建了lr_scheduler對象之后,會自動執(zhí)行第一次lr更新(可以理解為執(zhí)行一次scheduler.step())。因此,在使用的時候,需要先調(diào)用optimizer.step(),再調(diào)用scheduler.step()。如果創(chuàng)建了lr_scheduler對象之后,先調(diào)用scheduler.step(),再調(diào)用optimizer.step(),則會跳過了第一個學習率的值。

          #?調(diào)用順序
          loss.backward()
          optimizer.step()
          scheduler.step()
          ...

          注意: 創(chuàng)建scheduler時,所傳入的Optimizer的param_groups必須有一個initial_lr鍵作為初始學習率。如果last_epoch=-1,則用于初始化的Optimizer可以沒有initial_lr鍵,以 lr 鍵初始化為initial_lr。

          torch.optim.lr_scheduler.LambdaLr

          torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda, last_epoch=-1)

          • Optimizer:優(yōu)化器實例
          • lr_lambda:是一個函數(shù)(常用lambda表達式)或函數(shù)列表,該函數(shù)接收一個int參數(shù)(epoch),然后計算出一個系數(shù),最后學習率更新為
            。其中l(wèi)r_lambda如果傳入多個函數(shù)的list的話,則對應(yīng)每組param_groups的學習率調(diào)整策略。
          • last_epoch:(int)上一個epoch數(shù)。默認為-1,且當last_epoch=-1時,將lr設(shè)置為initial_lr。第一次更新lr時,就按照epoch = last_epoch + 1更新。(比如last_epoch = 1,則第一次lr更新時,就將epoch=2傳入上面的lr_lambda函數(shù),得出系數(shù)

          需要注意的是,該scheduler每次lr更新,是用initial_lr 乘以系數(shù) ? ,而不是用上一次的lr 乘以系數(shù) ,即

          Lambda_lr

          torch.optim.lr_scheduler.StepLR

          torch.optim.lr_scheduler.StepLR(optimizer, step_size, gamma=0.1, last_epoch=-1)
          每迭代step_size次,學習率乘以gamma。

          model?=?Net()
          optimizer_Adam?=?torch.optim.Adam(model.parameters(),?lr=0.1)
          #?創(chuàng)建scheduler,每迭代5次,學習率衰減一半
          scheduler?=?torch.optim.lr_scheduler.StepLR(optimizer_Adam,?step_size=5,?gamma=0.5,?last_epoch=-1)

          lr_list_1?=?[]
          for?epoch?in?range(100):
          ????scheduler.step()
          ????lr_list_1.append(optimizer_Adam.state_dict()['param_groups'][0]['lr'])
          plt.plot(range(100),?lr_list_1,?color='r',?label='lr')
          plt.legend()
          plt.show()
          StepLR

          torch.optim.lr_scheduler.MultiStepLR

          torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones, gamma=0.1, last_epoch=-1)

          多段衰減法。milestones傳入一個list,指定多個epoch數(shù),每迭代到指定的epoch次數(shù)時,lr乘以gamma。
          例子:

          model?=?Net()
          optimizer_Adam?=?torch.optim.Adam(model.parameters(),?lr=0.1)??#?初始?lr=0.1
          #?lr?變化
          #?0?-?20?epoch:?0.1
          #?21?-?40?epoch:?0.05
          #?41?-?60?epoch:?0.025
          #?60?-?80?epoch:?0.0125
          #?80?-?end?epoch:?0.01125
          scheduler?=?torch.optim.lr_scheduler.MultiStepLR(optimizer_Adam,?milestones=[20,?40,?60,?80],?gamma=0.5,?last_epoch=-1)

          lr_list_1?=?[]
          for?epoch?in?range(100):
          ????scheduler.step()
          ????lr_list_1.append(optimizer_Adam.state_dict()['param_groups'][0]['lr'])
          plt.plot(range(100),?lr_list_1,?color='r',?label='lr')
          plt.legend()
          plt.show()
          MultiStepLR

          torch.optim.lr_scheduler.ExponentialLR

          torch.optim.lr_scheduler.ExponentialLR(optimizer, gamma, last_epoch=-1)

          每個epoch按指數(shù)衰減 lr。

          model?=?Net()
          optimizer_Adam?=?torch.optim.Adam(model.parameters(),?lr=0.1)
          #?指數(shù)衰減學習率,衰減率為?gamma=0.9
          scheduler?=?torch.optim.lr_scheduler.ExponentialLR(optimizer_Adam,?gamma=0.9,?last_epoch=-1)
          lr_list_1?=?[]
          for?epoch?in?range(100):
          ????scheduler.step()?
          ????lr_list_1.append(optimizer_Adam.state_dict()['param_groups'][0]['lr'])
          plt.plot(range(100),?lr_list_1,?color='r',?label='lr')
          plt.legend()
          plt.show()
          ExponentialLR

          torch.optim.lr_scheduler.CosineAnnealingLR

          torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max, eta_min=0, last_epoch=-1)

          按照三角函數(shù)規(guī)則來更新學習率。

          • 表示最小學習率, 即正弦函數(shù)最低點
          • 表示最大學習率, 設(shè)置為initial_Ir (在last_epoch=-1 時, 即為Ir)。
          • 表示當前epoch數(shù)
          • 表示 周期所對應(yīng)的epoch數(shù)值
          model?=?Net()
          optimizer_Adam?=?torch.optim.Adam(model.parameters(),?lr=0.1)
          #?周期為50epoch,lr最小值為0(默認)
          scheduler?=?torch.optim.lr_scheduler.CosineAnnealingLR(optimizer_Adam,?eta_min=0,?T_max=25,?last_epoch=-1)
          lr_list_1?=?[]
          for?epoch?in?range(100):
          ????scheduler.step()
          ????lr_list_1.append(optimizer_Adam.state_dict()['param_groups'][0]['lr'])
          plt.plot(range(100),?lr_list_1,?color='r',?label='lr')
          plt.legend()
          plt.show()
          CosineAnnealingLR

          torch.optim.lr_scheduler.ReduceLROnPlateau

          torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.1, patience=10, verbose=False, threshold=0.0001, threshold_mode='rel', cooldown=0, min_lr=0, eps=1e-08)

          根據(jù)指定的指標量來調(diào)整學習率。如果指標量停止變化時,就減小學習率。
          參數(shù):

          • mode:(str),從(min, max)中選擇。
            • min:如果指定量不再下降,就減小lr
            • max:如果指定量不再上升,就減小lr
          • factor:(float),衰減因子,每次更新lr = lr * factor
          • patience:(int),容忍度,如果經(jīng)過patience次迭代后,指標沒有變化(上升或下降),就更新lr。
          • verbose:(bool),每次更新lr,是否向std輸出。
          • threshold:(float),閾值,對于制定的指標只有超過閾值才算有變化
          • threshold_mode:(str),從(rel,abs)總選擇。性能衡量方式。
            • max模式下:dynamic_threshold = best + threshold
            • min模式下:dynamic_threshold = best - threshold
            • max模式下:dynamic_threshold = best * ( 1 + threshold )
            • min模式下:dynamic_threshold = best * ( 1 - threshold )
            • rel:
            • abs:
          • cooldown:(int),每次調(diào)整lr之后,冷卻cooldown個epoch,避免lr下降過快
          • min_lr:(float or list),學習率最小值。如果給定一個標量值,就param_groups中所有組都設(shè)置該最小值;也可以用一個list為每組指定一個最小值。
          • eps:(float),lr變化最小值,如果lr的兩次變化差距小于eps,則忽略這次變化。
          optimizer?=?torch.optim.SGD(model.parameters(),?lr=0.1,?momentum=0.9)
          scheduler?=?ReduceLROnPlateau(optimizer,?'min')
          for?epoch?in?range(10):
          ????train(...)
          ????val_loss?=?validate(...)
          ????#?Note?that?step?should?be?called?after?validate()
          ????scheduler.step(val_loss)

          13個你一定要知道的PyTorch特性

          解讀:為什么要做特征歸一化/標準化?

          一文搞懂 PyTorch 內(nèi)部機制

          張一鳴:每個逆襲的年輕人,都具備的底層能力


          關(guān)


          西質(zhì)結(jié)關(guān)[]


          瀏覽 65
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  有码无码一区二区 | 日韩三级免费 | 九色丨老熟女丨91啦 | 一本道高清无码视频 | 九哥操逼视频 |