1. 程式人生 > >PyTorch(BUG匯總)—PyTorch遇到令人迷人的BUG與記錄

PyTorch(BUG匯總)—PyTorch遇到令人迷人的BUG與記錄

叠代 fcm 通過 相加 network inpu HR cast bms

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與記錄