關於PyTorch的一些小細節的紀錄(基於PyTorch 0.4.0)

長期更新...

 

1. nn.Module.cuda() 和 Tensor.cuda() 的作用效果差異

無論是對於模型還是數據,cuda()函數都能實現從CPU到GPU的內存遷移,但是他們的作用效果有所不同。

對於nn.Module:

model = model.cuda() 
model.cuda() 

上面兩句能夠達到一樣的效果,即對model自身進行的內存遷移。

對於Tensor:

和nn.Module不同,調用tensor.cuda()只是返回這個tensor對象在GPU內存上的拷貝,而不會對自身進行改變。因此必須對tensor進行重新賦值,即tensor=tensor.cuda().

例子:

model = create_a_model()
tensor = torch.zeros([2,3,10,10])
model.cuda()
tensor.cuda()
model(tensor)    # 會報錯
tensor = tensor.cuda()
model(tensor)    # 正常運行

 

2. PyTorch 0.4 計算累積損失的不同

以廣泛使用的模式total_loss += loss.data[0]爲例。Python0.4.0之前,loss是一個封裝了(1,)張量的Variable,但Python0.4.0的loss現在是一個零維的標量。對標量進行索引是沒有意義的(似乎會報 invalid index to scalar variable 的錯誤)。使用loss.item()可以從標量中獲取Python數字。所以改爲:

total_loss += loss.item()

如果在累加損失時未將其轉換爲Python數字,則可能出現程序內存使用量增加的情況。這是因爲上面表達式的右側原本是一個Python浮點數,而它現在是一個零維張量。因此,總損失累加了張量和它們的梯度歷史,這可能會產生很大的autograd 圖,耗費內存和計算資源。

 

3. PyTorch 0.4 編寫不限制設備的代碼

# torch.device object used throughout this script
device = torch.device("cuda" if use_cuda else "cpu")
model = MyRNN().to(device)

# train
total_loss= 0
for input, target in train_loader:
    input, target = input.to(device), target.to(device)
    hidden = input.new_zeros(*h_shape)       # has the same device & dtype as `input`
    ...                                                               # get loss and optimize
    total_loss += loss.item()

# test
with torch.no_grad():                                    # operations inside don't track history
    for input, targetin test_loader:
        ...

 

4. torch.Tensor.detach()的使用

detach()的官方說明如下:

Returns a new Tensor, detached from the current graph.
    The result will never require gradient.

假設有模型A和模型B,我們需要將A的輸出作爲B的輸入,但訓練時我們只訓練模型B. 那麼可以這樣做:

input_B = output_A.detach()

它可以使兩個計算圖的梯度傳遞斷開,從而實現我們所需的功能。

 

5. ERROR: Unexpected bus error encountered in worker. This might be caused by insufficient shared memory (shm)

出現這個錯誤的情況是,在服務器上的docker中運行訓練代碼時,batch size設置得過大,shared memory不夠(因爲docker限制了shm).解決方法是,將Dataloader的num_workers設置爲0.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章