摘要:在模型的開發過程中,精度達不到預期常常讓人頭疼。為了幫助使用者解決模型除錯調優的問題,我們為MindSpore量身定做了視覺化除錯調優元件:MindInsight。
本文分享自華為雲社群《技術乾貨 | 模型優化精度、速度我全都要!MindSpore模型精度調優實戰(二)》,原文作者:HWCloudAI 。
引言:
在模型的開發過程中,精度達不到預期常常讓人頭疼。為了幫助使用者解決模型除錯調優的問題,我們為MindSpore量身定做了視覺化除錯調優元件:MindInsight。我們還梳理了針對常見精度問題的除錯調優指南,將以“MindSpore模型精度調優實戰”系列文章的形式分享出來,希望能幫助使用者輕鬆定位精度問題,快速優化模型精度。
回顧MindSpore模型精度調優實戰系列點選跳轉連結→技術乾貨 | 更快定位精度問題!MindSpore模型精度調優實戰(一)。
本文是系列分享的第二篇,將給出常用的精度除錯調優思路。本系列分享假設您的指令碼已經能夠執行並算出loss值。如果指令碼還不能執行,請先參考相關報錯提示進行修改。
遇到精度問題時,常用除錯調優思路如下:
1. 檢查程式碼和超參
2. 檢查模型結構
3. 檢查輸入資料
4. 檢查loss曲線
5. 檢查精度是否達到預期
程式碼是精度問題的重要源頭,檢查程式碼重在對指令碼和程式碼做檢查,力爭在源頭發現問題(第2節);模型結構體現了MindSpore對程式碼的理解,檢查模型結構重在檢查MindSpore的理解和演算法工程師的設計是否一致(第3節);有的問題要到動態的訓練過程中才會發現,檢查輸入資料(第4節)和loss曲線(第5節)正是將程式碼和動態訓練現象結合進行檢查;檢查精度是否達到預期則是對整體精度調優過程重新審視,並考慮調整超參、解釋模型、優化演算法等調優手段(第6節)。此外,熟悉模型和工具也是很重要的(第1節)。下面將分別介紹這些思路。
01精度調優準備
1.1 回顧演算法設計,全面熟悉模型
精度調優前,要先對演算法設計做回顧,確保演算法設計明確。如果參考論文實現模型,則應回顧論文中的全部設計細節和超參選擇情況;如果參考其它框架指令碼實現模型,則應確保有一個唯一的、精度能夠達標的標杆指令碼;如果是新開發的演算法,也應將重要的設計細節和超參選擇明確出來。這些資訊是後面檢查指令碼步驟的重要依據。
精度調優前,還要全面熟悉模型。只有熟悉了模型,才能準確理解MindInsight提供的資訊,判斷是否存在問題,查詢問題源頭。因此,花時間理解模型演算法和結構、理解模型中運算元的作用和引數的含義、理解模型所用優化器的特性等模型要素是很重要的。動手分析精度問題細節前,建議先帶著問題加深對這些模型要素的瞭解。
前,要先對演算法設計做回顧,確保演算法設計明確。如果參考論文實現模型,則應回顧論文中的全部設計細節和超參選擇情況;如果參考其它框架指令碼實現模型,則應確保有一個唯一的、精度能夠達標的標杆指令碼;如果是新開發的演算法,也應將重要的設計細節和超參選擇明確出來。這些資訊是後面檢查指令碼步驟的重要依據。
精度調優前,還要全面熟悉模型。只有熟悉了模型,才能準確理解MindInsight提供的資訊,判斷是否存在問題,查詢問題源頭。因此,花時間理解模型演算法和結構、理解模型中運算元的作用和引數的含義、理解模型所用優化器的特性等模型要素是很重要的。動手分析精度問題細節前,建議先帶著問題加深對這些模型要素的瞭解。
1.2 熟悉工具
MindInsight功能豐富,建議使用者簡單閱讀MindInsight教程(https://www.mindspore.cn/tutorial/training/zh-CN/master/advanced_use/visualization_tutorials.html),瞭解主要功能。定位精度問題時,建議使能summary訓練資訊收集功能,在指令碼中加入SummaryCollector,並使用訓練看板檢視訓練過程資料,如下圖所示。Summary功能的使用指南請見 (https://www.mindspore.cn/tutorial/training/zh-CN/master/advanced_use/summary_record.html),訓練可視功能的使用指南請見(https://www.mindspore.cn/tutorial/training/zh-CN/master/advanced_use/dashboard.html) 。
當您需要線上除錯模型時,請參考此連結使能偵錯程式功能:https://www.mindspore.cn/tutorial/training/zh-CN/master/advanced_use/debugger.html
02檢查程式碼和超參
程式碼是精度問題的重要源頭,超參問題、模型結構問題、資料問題、演算法設計和實現問題會體現在指令碼中,對指令碼做檢查是定位精度問題很有效率的手段。檢查程式碼主要依賴程式碼走讀,建議使用小黃鴨除錯法:在程式碼走讀的過程中,耐心地向沒有經驗的“小黃鴨”解釋每一行程式碼的作用,從而激發靈感,發現程式碼問題。檢查指令碼時,要注意檢查指令碼實現(包括資料處理、模型結構、loss函式、優化器等實現)同設計是否一致,如果參考了其它指令碼,要重點檢查指令碼實現同其它指令碼是否一致,所有不一致的地方都應該有充分合理的理由,否則就應修改。
檢查指令碼時,也要關注超參的情況,超參問題主要體現為超參取值不合理,例如
1. 學習率設定不合理;
2. loss_scale引數不合理;
3. 權重初始化引數不合理等。
MindInsight可以輔助使用者對超參做檢查,大多數情況下,SummaryCollector會自動記錄常見超參,您可以通過MindInsight的訓練引數詳情功能(如下圖)和溯源分析功能檢視超參。結合MindInsight模型溯源分析模組和指令碼中的程式碼,可以確認超參的取值,識別明顯不合理的超參。如果有標杆指令碼,建議同標杆指令碼一一比對超參取值,如果有預設引數值,則預設值也應一併比對,以避免不同框架的引數預設值不同導致精度下降或者訓練錯誤。
03檢查模型結構
在模型結構方面,常見的問題有:
1. 運算元使用錯誤(使用的運算元不適用於目標場景,如應該使用浮點除,錯誤地使用了整數除);
2. 權重共享錯誤(共享了不應共享的權重);
3. 權重凍結錯誤(凍結了不應凍結的權重);
4. 節點連線錯誤(應該連線到計算圖中的block未連線);
5. loss函式錯誤;
6. 優化器演算法錯誤(如果自行實現了優化器)等。
建議通過檢查模型程式碼的方式對模型結構進行檢查。此外,MindInsight也可以輔助使用者對模型結構進行檢查。大多數情況下,SummaryCollector會自動記錄計算圖,通過MindInsight,使用者可以方便地對計算圖進行檢視。模型指令碼執行後,建議使用MindInsight計算圖可視模組檢視模型結構,加深對計算圖的理解,確認模型結構符合預期。若有標杆指令碼,還可以同標杆指令碼對照檢視計算圖,檢查當前指令碼和標杆指令碼的計算圖是否存在重要的差異。
考慮到模型結構一般都很複雜,期望在這一步就能發現所有的模型結構問題是不現實的。只要通過視覺化的模型結構加深對計算圖的理解,發現明顯的結構問題即可。後面的步驟中,發現了更明確的精度問題現象後,我們還會回到這一步重新檢查確認。
注1:MindInsight支援檢視SummaryCollector記錄的計算圖和MindSpore context的save_graphs引數匯出的pb檔案計算圖。請參考我們教程中的“計算圖視覺化”部分了解更多資訊(https://www.mindspore.cn/tutorial/training/zh-CN/master/advanced_use/dashboard.html)。
注2:指令碼遷移工具可以將PyTorch、TensorFlow框架下編寫的模型轉換為MindSpore指令碼,請訪問教程(https://www.mindspore.cn/tutorial/training/zh-CN/master/advanced_use/migrate_3rd_scripts_mindconverter.html) 以瞭解更多資訊。
04檢查輸入資料
通過檢查輸入模型的資料,可以結合指令碼判斷資料處理流水線和資料集是否存在問題。輸入資料的常見問題有:
1. 資料缺失值過多;
2. 每個類別中的樣本數目不均衡;
3. 資料中存在異常值;
4. 資料標籤錯誤;
5. 訓練樣本不足;
6. 未對資料進行標準化,輸入模型的資料不在正確的範圍內;
7. finetune和pretrain的資料處理方式不同;
8. 訓練階段和推理階段的資料處理方式不同;
9. 資料處理引數不正確等。
MindInsight可以輔助使用者對輸入資料、資料處理流水線進行檢查。大多數情況下,SummaryCollector會自動記錄輸入模型的資料(資料處理後的資料)和資料處理流水線引數。輸入模型的資料會展示在“資料抽樣”模組,資料處理流水線引數會展示在“資料圖”模組和“資料溯源”模組。通過MindInsight的資料抽樣模組,可以檢查輸入模型的(資料處理流水線處理後的)資料。若資料明顯不符合預期(例如資料被裁剪的範圍過大,資料旋轉的角度過大等),可以判斷輸入資料出現了一定的問題。通過MindInsight的資料圖和資料溯源模組,可以檢查資料處理流水線的資料處理過程和具體引數取值,從而發現不合理的資料處理方法。
如果有標杆指令碼,還可以同標杆指令碼對照,檢查資料處理流水線輸出的資料是否和當前指令碼的資料相同。例如,將資料處理流水線輸出的資料儲存為npy檔案,然後使用numpy.allclose()方法對標杆指令碼和當前指令碼的資料進行對比。如果發現不同,則資料處理階段可能存在精度問題。
若資料處理流水線未發現問題,可以手動檢查資料集是否存在分類不均衡、標籤匹配錯誤、缺失值過多、訓練樣本不足等問題。
05檢查loss曲線
很多精度問題會在網路訓練過程中發現,常見的問題或現象有:
1. 權重初始化不合理(例如初始值為0,初始值範圍不合理等);
2. 權重中存在過大、過小值;
3. 權重變化過大;
4. 權重凍結不正確;
5. 權重共享不正確;
6. 啟用值飽和或過弱(例如Sigmoid的輸出接近1,Relu的輸出全為0);
7. 梯度爆炸、消失;
8. 訓練epoch不足;
9. 運算元計算結果存在NAN、INF;
10. 運算元計算過程溢位(計算過程中的溢位不一定都是有害的)等。
上述這些問題或現象,有的可以通過loss表現出來,有的則難以觀察。MindInsight提供了針對性的功能,可以觀察上述現象、自動檢查問題,幫助您更快定位問題根因。例如:
- MindInsight的引數分佈圖模組可以展示模型權重隨訓練過程的變化趨勢;
- MindInsight的張量可視模組可以展示張量的具體取值,對不同張量進行對比;
- MindInsight偵錯程式內建了種類豐富,功能強大的檢查能力,可以檢查權重問題(例如權重不更新、權重更新過大、權重值過大/過小)、梯度問題(例如梯度消失、梯度爆炸)、啟用值問題(例如啟用值飽和或過弱)、張量全為0、NAN/INF、運算元計算過程溢位等問題。
偵錯程式使用教程:
https://www.mindspore.cn/tutorial/training/zh-CN/master/advanced_use/debugger.html
大多數情況下,SummaryCollector會自動記錄模型的loss曲線,可以通過MindInsight的標量可視模組檢視。loss曲線能夠反映網路訓練的動態趨勢,通過觀察loss曲線,可以得到模型是否收斂、是否過擬合等資訊。
大多數情況下,SummaryCollector會自動記錄模型引數變化情況(預設記錄5個引數),可以通過MindInsight的引數分佈圖模組檢視。如果想要記錄更多引數的引數分佈圖,請參考SummaryCollector的histogram_regular引數(https://www.mindspore.cn/doc/api_python/zh-CN/master/mindspore/mindspore.train.html#mindspore.train.callback.SummaryCollector),或參考HistogramSummary運算元(https://www.mindspore.cn/tutorial/training/zh-CN/master/advanced_use/summary_record.html#summarysummarycollector)。
張量不會被自動記錄,如果想要通過MindInsight檢視張量的具體取值,請使用TensorSummary運算元 (https://www.mindspore.cn/tutorial/training/zh-CN/master/advanced_use/summary_record.html#summarysummarycollector)。
下面結合loss曲線的常見現象介紹使用MindInsight進行精度問題定位的思路。
5.1 loss跑飛
loss跑飛是指loss中出現了NAN、+/-INF或者特別大的值。loss跑飛一般意味著演算法設計或實現存在問題。定位思路如下:
1. 回顧指令碼、模型結構和資料,
1)檢查超參是否有不合理的特別大/特別小的取值,
2)檢查模型結構是否實現正確,特別是檢查loss函式是否實現正確,
3)檢查輸入資料中是否有缺失值、是否有特別大/特別小的取值。
2. 觀察訓練看板中的引數分佈圖,檢查引數更新是否有明顯的異常。若發現引數更新異常,可以結合偵錯程式定位引數更新異常的原因。3. 使用偵錯程式模組對訓練現場進行檢查。
1)若loss值出現NAN、+/-INF,可使用“檢查張量溢位”條件新增全域性監測點,定位首先出現NAN、+/-INF的運算元節點,檢查運算元的輸入資料是否會導致計算異常(例如除零)。若是運算元輸入資料的問題,則可以針對性地加入小數值epsilon避免計算異常。
2)若loss值出現特別大的值,可使用“檢查過大張量”條件新增全域性監測點,定位首先出現大值的運算元節點,檢查運算元的輸入資料是否會導致計算異常。若輸入資料本身存在異常,則可以繼續向上追蹤產生該輸入資料的運算元,直到定位出具體原因。
3)若懷疑引數更新、梯度等方面存在異常,可使用“檢查權重變化過大”、“檢查梯度消失”、“檢查梯度過大”等條件設定監測點,定位到異常的權重或梯度,然後結合張量檢查檢視,逐層向上對可疑的正向運算元、反向運算元、優化器運算元等進行檢查。
5.2 loss收斂慢
loss收斂慢是指loss震盪、收斂速度慢,經過很長時間才能達到預期值,或者最終也無法收斂到預期值。相較於loss跑飛,loss收斂慢的數值特徵不明顯,更難定位。定位思路如下:1. 回顧指令碼、模型結構和資料,
1)檢查超參是否有不合理的特別大/特別小的取值,特別是檢查學習率是否設定過小或過大,學習率設定過小會導致收斂速度慢,學習率設定過大會導致loss震盪、不下降;
2)檢查模型結構是否實現正確,特別是檢查loss函式、優化器是否實現正確;
3)檢查輸入資料的範圍是否正常,特別是輸入資料的值是否過小
2. 觀察訓練看板中的引數分佈圖,檢查引數更新是否有明顯的異常。若發現引數更新異常,可以結合偵錯程式定位引數更新異常的原因。3. 使用偵錯程式模組對訓練現場程式檢查。
1)可使用“檢查權重變化過小”、“檢查未變化權重”條件對可訓練(未固定)的權重進行監測,檢查權重是否變化過小。若發現權重變化過小,可進一步檢查學習率取值是否過小、優化器演算法是否正確實現、梯度是否消失,並做針對性的修復。
2)可使用“檢查梯度消失”條件對梯度進行監測,檢查是否存在梯度消失的現象。若發現梯度消失,可進一步向上檢查導致梯度消失的原因。例如,可以通過“檢查啟用值範圍”條件檢查是否出現了啟用值飽和、Relu輸出為0等問題。
5.3 其它loss現象
若訓練集上loss為0,一般說明模型出現了過擬合,請嘗試增大訓練集大小。
06檢查精度是否達到預期
MindInsight可以為使用者記錄每次訓練的精度結果。在model.train和model.eval中使用同一個SummaryCollector例項時,會自動記錄模型評估(metrics)資訊。訓練結束後,可以通過MindInsight的模型溯源模組檢查訓練結果精度是否達標。
6.1 檢查訓練集上的精度
若訓練集上模型的loss值、metric值未達到預期,可以參考以下思路進行定位和優化:
1. 回顧程式碼、模型結構、輸入資料和loss曲線,
1)檢查指令碼,檢查超參是否有不合理的值
2)檢查模型結構是否實現正確
3)檢查輸入資料是否正確
4)檢查loss曲線的收斂結果和收斂趨勢是否存在異常
2. 嘗試使用MindInsight溯源分析功能優化超參。溯源分析頁面會對超參的重要性進行分析,使用者應優先考慮調整重要性高的超參,從散點圖中可以觀察出超參和優化目標的關係,從而針對性地調整超參取值。
3. 嘗試使用MindInsight調參器優化超參。請注意,調參器通過執行多次完整訓練的方式進行超參搜尋,消耗的時間為網路一次訓練用時的若干倍,如果網路一次訓練耗時較長,則超參搜尋將需要很長的時間。調參器使用教程:https://www.mindspore.cn/tutorial/training/zh-CN/master/advanced_use/hyper_parameters_auto_tuning.html
4. 嘗試使用MindInsight模型解釋功能優化模型和資料集。模型解釋功能可以通過顯著圖視覺化展示對分類結果最重要的區域,還可以通過評分體系提示應該對哪類標籤進行優化。
模型解釋使用教程:https://www.mindspore.cn/tutorial/training/zh-CN/master/advanced_use/model_explaination.html
5. 嘗試優化模型結構/演算法。
6.2 檢查驗證集上的精度
若訓練集精度和驗證集精度都未達到預期,則應首先參考上一節檢查訓練集精度。若訓練集精度已達到預期,但是驗證集精度未達到預期,大概率是模型出現了過擬合,處理思路如下:
1. 檢查驗證集評估指令碼的評估邏輯有無錯誤。特別是資料處理方式是否與訓練集一致,推理演算法有誤錯誤,是否載入了正確的模型checkpoint。2. 增加資料量。包括增加樣本量,進行資料增強和擾動等。3. 正則化。常見的技術如引數範數懲罰(例如向目標函式中新增一個正則項 ),引數共享(強迫模型的兩個元件共享相同的引數值),提前中止訓練等。4. 適當降低模型的規模。例如減少卷積層數等。
6.3 檢查測試集上的精度
若驗證集和測試集精度都未達到預期,則應首先參考上一節檢查驗證集精度。若驗證集精度已達到預期,但是測試集精度未達到預期,考慮到測試集的資料是模型從未見過的新資料,原因一般是測試集的資料分佈和訓練集的資料分佈不一致。處理思路如下:
1. 檢查測試集評估指令碼的評估邏輯有誤錯誤。特別是資料處理方式是否與訓練集一致,推理演算法有誤錯誤,是否載入了正確的模型checkpoint。
2. 檢查測試集中的資料質量,例如資料的分佈範圍是否明顯同訓練集不同,資料是否存在大量的噪聲、缺失值或異常值。
07小結
由於相同的現象存在多個可能原因,精度問題的定位非常依賴專家經驗。希望上述定位方法和功能能夠起到良好的引導的作用,幫助你不斷積累成功經驗,成為精度調優大師。