PyTorch(BUG匯總)—PyTorch遇到令人迷人的BUG與記錄
BUG1
在使用NLLLoss()激活函數時,NLLLoss用來做n類分類的,一般最後一層網絡為LogSoftmax,如果其他的則需要使用CrossEntropyLoss。其使用格式為:loss(m(input), target),其中input為2DTensor大小為(minibatch,n),target為真實分類的標簽。
如果輸入的input類型為torch.cuda.FloatTensor,target類型為torch.cuda.IntTensor,則會出現如下錯誤:
因此需要保證target類型為torch.cuda.LongTensor,需要在數據讀取的叠代其中把target的類型轉換為int64位的:target = target.astype(np.int64),這樣,輸出的target類型為torch.cuda.LongTensor。(或者在使用前使用Tensor.type(torch.LongTensor)
為了說明pytorch中numpy和toch的轉換關系,測試如下:
首先輸入int32的numpy數組轉換為torch,得到的IntTensor類型
如果輸入的為int64的numpy,得到LongTensor類型:
如果把int32的數組轉換為LongTensor,則會出錯:
如果把int64的數組轉換為LongTensor,正常:
PS: 2017/8/8(奇怪,在使用binary_cross_entropy
進行分類時又要求類型為FloatTensor
類型,簡直夠了)
BUG2
同樣是NLLLoss()使用時的問題。網絡傳播都正常,但是在計算loss時出現如下錯誤:
RuntimeError: cuda runtime error (59) : device-side assert triggered at /home/loop/pytorch-master/torch/lib/THC/generic/THCTensorMath.cu:15
斷點調試發現數據類型出現如下變化:
我以為顯卡除了問題,最後在pytoch#1204中發現一個人的標簽中出現-1,發生了類似的錯誤:
而我的標簽為1~10,最後把標簽定義為1~9,解決這個問題。^_^!
BUG3
當使用torch.view()
時出現 RuntimeError: input is not contiguous at /home/loop/pytorch-master/torch/lib/TH/generic/THTensor.c:231
這個是由於淺拷貝出現的問題。
如下:定義初始化一個Tensor
值,並且對其進行維度交換,在進行Tensor.view()
操作時出現以上錯誤。
這是由於淺拷貝的原因,y
x
的指針,x
改變,y
也要隨之改變,如下:
可以使用tensor.contiguous()
解決:
BUG4
按照官網的方式編譯PyTorch源碼時出現:undefined reference to ... @GLIBCXX_3.4.21 (未定義的引用問題)
我的是出現在編譯90%左右的broadcast_test附近出現的。問題估計是GCC的版本造成的,雖然GCC -v
顯示的5.0,但是調用的庫不是,需要執行:
conda install libgcc
然後python setup.py clean
重新生成即可解決問題
BUG5
使用Cross_entropy
損失函數時出現 RuntimeError: multi-target not supported at …
仔細看其參數說明:
input has to be a 2D Tensor of size batch x n. This criterion expects a class index (0 tonClasses-1) as the target for each value
of a 1D tensor of size n
其標簽必須為0~n-1,而且必須為1維的,如果設置標簽為[nx1]的,則也會出現以上錯誤。
NOTE1 共享參數問題
在tensorflow中有variable_scope
方法實現參數共享,也就是說對於2張圖片,第二張訓練時的權重參數與第一張圖片所使用的相同,詳見tf.variable_scope. 同樣,在PyTorch則不存在這樣的問題,因為PyTorch中使用的卷積(或者其他)層首先需要初始化,也就是需要建立一個實例,然後使用實例搭建網絡,因此在多次使用這個實例時權重都是共享的。
NOTE2 torch.nn.Module.cuda 作用
之前看教程中在定義完網絡後會進行:
現在才發現這個的作用,官方文檔上寫的是:Moves all model parameters and buffers to the GPU.
也就是在定義時並沒有把weight
參數傳入gpu中,在調用網絡進行計算時,如果傳入的數據為GPU數據,則會出現:tensors are on different GPUs 錯誤,因此使用torch.nn.Module.cuda
可以把定義的網絡參數傳入gpu中。
NOTE3 對同一網絡連續兩次對同一梯度求解(backward)
如果使用一個Variable
數據傳入到網絡,通過backward
求解其梯度值,然後在使用另一個Variable
傳入網絡,再次求解梯度值,其最終結果會怎麽樣呢?正如你所想得樣,是兩次梯度之和。測試代碼如下:
定義一個一層的線性網絡,並且其權重(weight)和偏置(bias)都初始化為0,在每次求解梯度後輸出梯度值,其結果如下:
可以發現,在進行梯度求解前,沒有梯度,在第一次計算後梯度為-1,第二次計算後為-2,如果在第一次求解後初始化梯度net.zero_grad()
,則來嗯次都是-1,則連續多次求解梯度為多次梯度之和。
NOTE4 pytorch自定義權重初始化
在上面的NOTE3中使用自定意的權重參數初始化,使用toch.nn.Module.apply()
對定義的網絡參數進行初始化,首先定義一個權重初始化的函數,如果傳入的類是所定義的網絡,則對其權重進行in_place賦值。
如果對weight_init(m)
中的classname輸出,可以發現有多個類:(因此需要判斷是否為所定義的網絡)
NOTE5 pytorch權重的更新
關於網絡傳遞中網絡的定義、loss計算、backpropogate的計算,update weight在Neural Networks有簡單介紹,這裏測試下。只要定義一個優化器(optimizer),實現了常見的優化算法(optimization algorithms),然後使用優化器和計算的梯度進行權重的更新。
在NOTE3中的代碼後面增加如下(更新權重參數):
其運行結果為:
可見使用optimizer.step()
實現了網絡權重的更新。(而且可以選擇不同的更新方式,如:Adam、SGD等)
NOTE6 torch.autograd.backward()使用技巧
當計算多個梯度相加(相減)時,使用backward(torch.FloatTensor([-1]))
可以簡單實現。
NOTE7 監控內存使用,防止內存泄漏memory leak
http://www.aibbt.com/a/19351.html
代碼如下:
收 藏PyTorch(BUG匯總)—PyTorch遇到令人迷人的BUG與記錄