【Pytorch神经网络理论篇】 10 优化器模块+退化学习率
1 優化器模塊的作用
1.1 反向傳播的核心思想
反向傳播的意義在于告訴模型我們需要將權重修改到什么數值可以得到最優解,在開始探索合適權重的過程中,正向傳播所生成的結果與實際標簽的目標值存在誤差,反向傳播通過這個誤差傳遞給權重,要求權重進行適當的調整來達到一個合適的輸出,最終使得正向傳播所預測的結果與標簽的目標值的誤差達到最小,以上即為反向傳播的核心思想
1.2 優化器簡介
正向結構與損失函數獲取完畢之后,通過優化器模塊中優化函數來實現對學習參數的優化,其內部原理主要是梯度下降的方法實現的
1.2.1 優化器與梯度下降
優化器是指通過算法幫助模型在訓練過程中更快更好地將參數調整到位,梯度下降主要在損失函數求解出損失值時,它利用梯度下降的方向為前進方向,沿著梯度下降的方向求解最小值,幫助模型找到最小的那個損失值,從而可以反向推算出學習參數的權重,達到優化的目的。
1.3 優化器的類型
1.3.1 批量梯度下降
主要特點:遍歷全部數據集計算一次損失函數,根據函數結果更新梯度。
缺點:每次都要遍歷全部數據集,計算開銷大,計算慢,不支持在線學習。
1.3.2 隨機梯度下降
主要特點:每檢查一個數據就進行損失函數計算,求梯度更新函數
缺點:計算速度快,收斂性不好,易在最優點附近擺動,兩次參數也可能互相抵消,函數震蕩劇烈。
1.3.3 小批量梯度下降(折中)
主要特點:將數據集分成若干批,按照批次來實現更新參數,一批中的一組數據共同決定梯度的反向,梯度下降方向不易跑偏,減少隨機性,計算量小。
缺點:————————
2 優化器
2.1?常見的優化器
2.1.1 Adam
較為常用,學習率設為3e-4
2.1.2 Ranger
基于RAdam與Lookhead優化器基礎上融合而來,兼顧兩者的優點,綜合性能占優,使得其在各種模型中都具有較高的精度、收斂速度快、使用方便、無需手動調參。
- RAdam:帶有整流器的Adam,能夠利用潛在散度動態地打開或者管理自適應學習率。
- Lookhead:通過迭代更新兩組權重的方法,提前觀察另一個優化器生成的序列進而選擇探索方向。
2.1.3 AMSGrad
在Adam優化器基礎上使用二階沖量,在計算機視覺模型上表現更為出色
2.1.4 Adamax
在帶有詞向量的自然語言處理模型中表現得更好
2.2?如何選取優化器
2.2.1 手動精確調整模型方面
一般先使用Adam優化器訓練模型,在模型無法進一步收斂后,再使用SGD優化器進行手動調節學習率,進一步提升模型性能。
2.2.2 自動精確調整模型方面
一般以Adam優化器為最常用,在收斂速度、模型訓練精度都具有較好的效果,對于學習率設置較為寬松,更易于使用。
2.3?優化器的使用
2.3.1 優化器調用方法
優化器在工作時,先算出梯度(根據損失值對某個參數求偏導),再沿著該梯度的方向算出一段距離(由學習率決定),該差值作為變化值更新到原有參數上。
import torch ### Adam()是優化器方法 #model.parameters():待優化的權重參數,調用模型的parameters(),將返回值傳入 #lr:學習率,學習率越大收斂越快! optimizer = torch.optim.Adam(model.parameters(),lr = lreaning_rate)2.3.2 查看優化器的參數結構
Pytorch中的每個優化器類中均有param_groups屬性,該屬性包括每個待優化權重的配置參數,是一個列表對象
list(optimizer.param_group[0].keys()) #返回: ['params','lr','eps','weight_deacy','amsgrad'] #返回: ['優化器要作用的權重參數','學習率','','權重參數的衰減率','是否使用二階沖量的方式'] ### 權重參數的衰減率weight_deacy是指模型在訓練過程中使用L2鄭澤華的衰減參數,L2正則化是一種防止過擬合的方法3 退化學習率
3.1 退化學習率簡介
退化學習率/學習率衰減,即在剛訓練開始時,使用大的學習率加速,訓練到一定程度后使用小的學習率來提高精度。
3.1.1 退化學習率/學習率衰減 手動代碼實現
import sklearn.datasets import torch import numpy as np import matplotlib.pyplot as plt from LogicNet_fun import LogicNet, plot_losses, predict, plot_decision_boundary# 準備數據 np.random.seed(0) # 設置隨機種子 X, Y = sklearn.datasets.make_moons(200, noise=0.2) # 生成兩組半圓形數據 arg = np.squeeze(np.argwhere(Y == 0), axis=1) # 獲取第1組數據索引 arg2 = np.squeeze(np.argwhere(Y == 1), axis=1) # 獲取第2組數據索引 plt.title("moons data") # 設置可視化標題 plt.scatter(X[arg, 0], X[arg, 1], s=100, c='b', marker='+', label='data1') # 顯示第一組數據索引 plt.scatter(X[arg2, 0], X[arg2, 1], s=40, c='r', marker='o', label='data2') # 顯示第二組數據索引 plt.legend() # 顯示圖例 plt.show()# 搭建網絡模型 model = LogicNet(inputdim=2,hiddendim=3,outputdim=2) #實例化模型 輸入數據的維度、隱藏節點的數量、模型最終結果的分類數 optimizer = torch.optim.Adam(model.parameters(),lr=0.01) # 定義優化器 在反向傳播時使用# 訓練模型 xt = torch.from_numpy(X).type(torch.FloatTensor) #將數據轉化為張量形式 yt = torch.from_numpy(Y).type(torch.LongTensor) epochs = 1000 #訓練次數 losses = [] # 損失值列表:用來接受每一步的損失值 lr_list = [] # 學習率列表:用來接受每一步的學習率 for i in range(epochs):loss = model.getloss(xt,yt)losses.append(loss.item()) # 保存中間狀態的損失值optimizer.zero_grad() # 清空之前的梯度loss.backward() # 反向傳播損失值optimizer.step() # 更新參數if i % 50 == 0: # 每五十步將學習率 lr X 0.99for p in optimizer.param_groups:p['lr'] = p['lr'] * 0.99lr_list.append(optimizer.state_dict()['param_groups'][0]['lr']) # 學習率可視化 plt.plot(range(epochs),lr_list,color='r') plt.show()3.2 使用lr_scheduler接口實現退化學習率
在Ptorch的optim模塊中,將退化學習率的多種實現方法封裝到lr_scheduler接口中
3.2.1?使用lr_scheduler接口實現退化學習率 代碼實現
import sklearn.datasets import torch import numpy as np import matplotlib.pyplot as plt from LogicNet_fun import LogicNet, plot_losses, predict, plot_decision_boundary# 準備數據 np.random.seed(0) # 設置隨機種子 X, Y = sklearn.datasets.make_moons(200, noise=0.2) # 生成兩組半圓形數據 arg = np.squeeze(np.argwhere(Y == 0), axis=1) # 獲取第1組數據索引 arg2 = np.squeeze(np.argwhere(Y == 1), axis=1) # 獲取第2組數據索引 plt.title("moons data") # 設置可視化標題 plt.scatter(X[arg, 0], X[arg, 1], s=100, c='b', marker='+', label='data1') # 顯示第一組數據索引 plt.scatter(X[arg2, 0], X[arg2, 1], s=40, c='r', marker='o', label='data2') # 顯示第二組數據索引 plt.legend() # 顯示圖例 plt.show()# 搭建網絡模型 model = LogicNet(inputdim=2,hiddendim=3,outputdim=2) #實例化模型 輸入數據的維度、隱藏節點的數量、模型最終結果的分類數 optimizer = torch.optim.Adam(model.parameters(),lr=0.01) # 定義優化器 在反向傳播時使用# 訓練模型 xt = torch.from_numpy(X).type(torch.FloatTensor) #將數據轉化為張量形式 yt = torch.from_numpy(Y).type(torch.LongTensor) epochs = 1000 #訓練次數 losses = [] # 損失值列表:用來接受每一步的損失值 lr_list = [] # 學習率列表:用來接受每一步的學習率 scheduler = torch.optim.lr_scheduler.StepLR(optimizer,step_size=50,gamma=0.99) # 設置退化學習率,每50步乘以0.99 for i in range(epochs):loss = model.getloss(xt,yt)losses.append(loss.item()) # 保存中間狀態的損失值optimizer.zero_grad() # 清空之前的梯度loss.backward() # 反向傳播損失值optimizer.step() # 更新參數scheduler.step() # 調用退化學習率對象lr_list.append(optimizer.state_dict()['param_groups'][0]['lr']) # 學習率可視化 plt.plot(range(epochs),lr_list,color='r') plt.show()?3.2.2 lr_scheduler接口中的退化學習率種類
- 等間隔調整學習率StepLR():每訓練指定步數,學習率調整為 lr = lr×gamma (gamma為手動設置的退化率參數)。
- 多間隔調整學習率MultiStepLR():按照指定的步數來調整學習率。調整方式也是lr= lr x gamma。
- 指數衰減調整學習率ExponentialLR():每訓練一步,學習率呈指數型衰減,即學習率調整為lr=lr ? gamma^epoch (step為訓練步數)。
- 余弦退火函數調整學習率CosineAnnealingLR():余弦退火指的就是按照弦函數的曲線進行衰減,每訓練一步,學習率呈余弦函數型衰減。 torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max, eta_min=0, last_epoch=-1) # 參數: ## T_max(int) – 一次學習率周期的迭代次數,即 T_max 個 epoch 之后重新設置學習率。 ## eta_min(float) – 最小學習率,即在一個周期中,學習率最小會下降到 eta_min,默認值為 0。
- 根據指標調整學習率ReduceLROnPlateau:當某指標(loss或accuracy)在最近幾次訓練中均沒有變化(下降或升高超過給定閾值)時,調整學習率。
- 自定義調整學習率LambdaLR:將每個參數組的學習速率設置為初始的lr乘以一個給定的函數。
3.2.3 多種學習率衰減總結
LambdaLR最為靈活,可以根據需求指定任何策略的學習率變化。它在fne-tune(微調模型的一種方法)中特別有用,不但可以為不同層設置不同的學習率,而且可以為不同層設置不同的學習率調整策略。
3.3 使用lr_scheduler接口實現多種退化學習率
MultiStepLR():在論文中使用較多,簡單可控。
ReducelROnPlateau():自動化程度高,參數多。
3.3.1?使用lr_scheduler接口實現MultiStepLR
import sklearn.datasets import torch import numpy as np import matplotlib.pyplot as plt from LogicNet_fun import LogicNet, plot_losses, predict, plot_decision_boundary# 準備數據 np.random.seed(0) # 設置隨機種子 X, Y = sklearn.datasets.make_moons(200, noise=0.2) # 生成兩組半圓形數據 arg = np.squeeze(np.argwhere(Y == 0), axis=1) # 獲取第1組數據索引 arg2 = np.squeeze(np.argwhere(Y == 1), axis=1) # 獲取第2組數據索引 plt.title("moons data") # 設置可視化標題 plt.scatter(X[arg, 0], X[arg, 1], s=100, c='b', marker='+', label='data1') # 顯示第一組數據索引 plt.scatter(X[arg2, 0], X[arg2, 1], s=40, c='r', marker='o', label='data2') # 顯示第二組數據索引 plt.legend() # 顯示圖例 plt.show()# 搭建網絡模型 model = LogicNet(inputdim=2,hiddendim=3,outputdim=2) #實例化模型 輸入數據的維度、隱藏節點的數量、模型最終結果的分類數 optimizer = torch.optim.Adam(model.parameters(),lr=0.01) # 定義優化器 在反向傳播時使用# 訓練模型 xt = torch.from_numpy(X).type(torch.FloatTensor) #將數據轉化為張量形式 yt = torch.from_numpy(Y).type(torch.LongTensor) epochs = 1000 #訓練次數 losses = [] # 損失值列表:用來接受每一步的損失值 lr_list = [] # 學習率列表:用來接受每一步的學習率 scheduler = torch.optim.lr_scheduler.MultiStepLR(optimizer,milestones=[200,700,900],gamma=0.99) #在100 700 900 次時,調整學習率for i in range(epochs):loss = model.getloss(xt,yt)losses.append(loss.item()) # 保存中間狀態的損失值optimizer.zero_grad() # 清空之前的梯度loss.backward() # 反向傳播損失值optimizer.step() # 更新參數scheduler.step() # 調用退化學習率對象lr_list.append(optimizer.state_dict()['param_groups'][0]['lr']) # 學習率可視化 plt.plot(range(epochs),lr_list,color='r') plt.show()3.3.2?使用lr_scheduler接口實現ReduceLROnPlateau
import sklearn.datasets import torch import numpy as np import matplotlib.pyplot as plt from LogicNet_fun import LogicNet, plot_losses, predict, plot_decision_boundary# 準備數據 np.random.seed(0) # 設置隨機種子 X, Y = sklearn.datasets.make_moons(200, noise=0.2) # 生成兩組半圓形數據 arg = np.squeeze(np.argwhere(Y == 0), axis=1) # 獲取第1組數據索引 arg2 = np.squeeze(np.argwhere(Y == 1), axis=1) # 獲取第2組數據索引 plt.title("moons data") # 設置可視化標題 plt.scatter(X[arg, 0], X[arg, 1], s=100, c='b', marker='+', label='data1') # 顯示第一組數據索引 plt.scatter(X[arg2, 0], X[arg2, 1], s=40, c='r', marker='o', label='data2') # 顯示第二組數據索引 plt.legend() # 顯示圖例 plt.show()# 搭建網絡模型 model = LogicNet(inputdim=2,hiddendim=3,outputdim=2) #實例化模型 輸入數據的維度、隱藏節點的數量、模型最終結果的分類數 optimizer = torch.optim.Adam(model.parameters(),lr=0.01) # 定義優化器 在反向傳播時使用# 訓練模型 xt = torch.from_numpy(X).type(torch.FloatTensor) #將數據轉化為張量形式 yt = torch.from_numpy(Y).type(torch.LongTensor) epochs = 1000 #訓練次數 losses = [] # 損失值列表:用來接受每一步的損失值 lr_list = [] # 學習率列表:用來接受每一步的學習率 scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer,mode='min', # 要監控模型的最大值or最小值factor= 0.5, # 退化學習率參數 gammapatience=5, # 不再減少/增加的累計次數verbose=True, # 觸發規則時是否打印信息threshold=0.001, # 監控值觸發規則的閾值threshold_mode='abs', # 計算觸發條件的規則cooldown=0, # 觸發規則后的停止監控步數,避免lr下降過快min_lr=0, # 允許的最小退化學習率eps=1e-08 # 當退化學習率小于該值時,停止調整 )for i in range(epochs):loss = model.getloss(xt,yt)losses.append(loss.item()) # 保存中間狀態的損失值scheduler.step(loss.item()) # 調用退化學習率對象,需要傳入被監控的值,否則代碼出錯 【ReduceLROnPlateau()特別的地方】optimizer.zero_grad() # 清空之前的梯度loss.backward() # 反向傳播損失值optimizer.step() # 更新參數lr_list.append(optimizer.state_dict()['param_groups'][0]['lr']) # 學習率可視化 plt.plot(range(epochs),lr_list,color='r') plt.show()上述代碼 參數Threshold_mode有兩種取值:
'rel':在參數mode為max時,如果監控值超過best(1+threshold),則觸發規則;在參數mode為min時,如果監控值低于best(1 - threshold),則觸發規則。【best為訓練過程中的歷史最好值】
'abs':在參數mode為max時,如果監控值超過best + threshold,則觸發規則;在參數mode為min時,如果監控值低于best - threshold,則觸發規則。【best為訓練過程中的歷史最好值】
總結
以上是生活随笔為你收集整理的【Pytorch神经网络理论篇】 10 优化器模块+退化学习率的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python局域网大文件_[源码]Pyt
- 下一篇: PackagesNotFoundErro