【PyTorch基礎教學19】Debug指南(學不會來打我啊)

2021-12-13 11:00:02

學習總結

一、ipdb介紹

程式碼量少時debug:使用printlog偵錯程式碼;
better做法:一遍執行一遍檢查裡面的變數和方法。

pdb是python互動式的偵錯工具,其作用:

  • 根據需求跳轉到任意的python程式碼斷點
  • 檢視任意變數、單步執行程式碼
  • 甚至修改變數的值,不必重新啟動程式

ipdb是增強版的pdb,提供了偵錯模式下的程式碼自動補全,有更好的語法高亮和程式碼溯源,與pdb介面完全相容。

二、小栗子

結合pytorch和ipdb進行偵錯。
要使用ipdb,在需要偵錯的地方插入ipdb.set_trace即可(還有在程式碼開頭加上try和except兩行)。

現在有栗子如下,sum和mul函數分別計算列表x中的元素的累加和累乘:

# -*- coding: utf-8 -*-
"""
Created on Sun Dec 12 16:33:07 2021

@author: 86493
"""
try:
    import ipdb
except:
    import pdb as ipdb
    
def sum(x):
    r = 0
    for i in x:
        r += i
    return r

def mul(x):
    r = 1
    for i in x:
        r *= i
    return r

ipdb.set_trace()
x = [1, 2, 3, 4, 5]
r = sum(x)
r = mul(x)

程式執行到ipdb.set_trace()後自動進行debug模式:

ipdb> list 7,27 # 檢視第7到27行程式碼
      7 try:
      8     import ipdb
      9 except:
     10     import pdb as ipdb
     11 
     12 def sum(x):
     13     r = 0
     14     for i in x:
     15         r += i
     16     return r
     17 
     18 def mul(x):
     19     r = 1
     20     for i in x:
     21         r *= i
     22     return r
     23 
     24 ipdb.set_trace()
---> 25 x = [1, 2, 3, 4, 5]
     26 r = sum(x)
     27 r = mul(x)

ipdb> n # next執行下一步
> d:\桌面檔案\ipdb.py(26)<module>()

ipdb> s # step的縮寫,此處進入sum函數內部
--Call--
> d:\桌面檔案\ipdb.py(12)sum()

ipdb> u # up的縮寫,調回上一層的呼叫
> d:\桌面檔案\cs224\ipdb.py(26)<module>()

ipdb> down # down的縮寫,跳到呼叫的下一層
> d:\桌面檔案\cs224\ipdb.py(15)sum()


ipdb> return # 繼續執行到函數返回,返回15即為sum的結果 
--Return--
15

同時也可以檢視或者修改變數,再繼續執行程式碼也是按照修改後的變數運算,如果要退出debug模式則是q(debug的縮寫)。

ipdb的小技巧:

  • <tab>鍵能自動補齊,和IPyhton中類似
  • j(ump)<lineno>能夠跳過中間某些行程式碼的執行
  • 可以直接在ipdb中改變變數值
  • h(elp)能夠檢視偵錯命令的用法,如h h檢視help命令的用法等。

三、在pytorch中debug

pytorch可以執行計算的同時定義計算圖(該定義過程是用python完成的,雖然底層是用C++完成)。

3.1 pytorch和ipdb結合的好處

1)通過debug暫停程式:當程式進入debug模式之後,將不再執行GPU和CPU運算,但是記憶體和視訊記憶體集相應的堆疊空間不會釋放

2)通過debug分析程式,檢視每個層的輸出,檢視網路的引數情況:通過u\d\s等命令,能夠進入指定的程式碼,通過n可以進行單步執行,從而可以看見每一層的運算結果,便於分析網路的數值分佈等資訊

3)作為動態圖框架,pytorch擁有python動態語言解釋執行的優點,我們能夠在執行程式時,通過ipdb修改某些變數的值或屬性,這些修改能夠立即生效。例如可以在訓練開始不久後根據損失函數調整學習率,不必重新啟動程式

4)如果在IPython中通過%run魔法方法執行程式,那麼在程式異常退出時,可以使用%debug命令,直接進入debug模式,通過u和d調到報錯的地方,檢視對應的變數。然後找出原因後修改相應的程式碼即可。

因為有時模型訓練好幾個小時後,卻在要儲存模型之前,因為一個小小的拼寫錯誤異常退出。這時候最好的辦法就是利用%debug進入偵錯模式,在偵錯模式中直接執行model.save()儲存模型

在ipython中,%pdb魔術方法能夠使得程式出現問題後,不用手動輸入%debug而自動進入偵錯模式,建議使用

pytorch呼叫cuDNN報錯時,報錯資訊諸如CUDNN_STATUS_BAD_PARAM,從這些報錯資訊內容很難得到有用的幫助資訊,最好先利用CPU執行程式碼,此時一般會得到相對友好的報錯資訊。

3.2 常見的錯誤有如下幾種:

1)型別不匹配問題:如CrossEntropyLoss的輸入target應該是一個LongTensor,而很多人輸入FloatTensor

2)部分資料忘記從CPU轉到GPU:例如當model存放與GPU時,輸入input耶需要轉移到GPU才能輸入到model中

還有可能是把多個model存放在一個list物件,而在執行model.cuda()時,這個list中的物件是不會被轉移到CUDA上的,正確的用法是使用ModuleList替代

3)Tensor形狀不匹配:此類問題一般是輸入資料形狀不對,或是網路結構設計有問題,一般通過u命令跳到指定程式碼,檢視輸入和模型引數的形狀即可得知

Reference

(1)pytorch官網
(2)https://www.cnblogs.com/wanghui-garcia/p/10648849.html
(3)《深度學習框架pytorch入門與實踐》