實操教程 | Pytorch Debug指南:15條重要建議

作者 | Coggle
來源 | Coggle數(shù)據(jù)科學(xué)
編輯 | 極市平臺
極市導(dǎo)讀
在使用Pytorch時你或多或少會遇到各種bug,為了緩解你的痛苦??,本文將對常見的錯誤進行解釋,并說清楚來龍去脈 >>加入極市CV技術(shù)交流群,走在計算機視覺的最前沿
在使用Pytorch時你或多或少會遇到各種bug,為了緩解你的痛苦??,本文將對常見的錯誤進行解釋,并說清楚來龍去脈。
細節(jié)就是魔鬼,雖然代碼不報錯但還是可能會對精度帶來影響。如果本文對你有幫助,請收藏&轉(zhuǎn)發(fā)!
CrossEntropyLoss和NLLLoss
最常見的錯誤是損失函數(shù)和輸出激活函數(shù)之間的不匹配。nn.CrossEntropyLossPyTorch中的損失模塊執(zhí)行兩個操作:nn.LogSoftmax和nn.NLLLoss。
因此nn.CrossEntropyLossPyTorch的輸入應(yīng)該是最后一個線性層的輸出。不要在nn.CrossEntropyLossPyTorch之前應(yīng)用Softmax。 否則將對Softmax輸出計算log-softmax,將會降低模型精度。
如果使用nn.NLLLoss模塊,則需要自己應(yīng)用log-softmax。nn.NLLLoss需要對數(shù)概率,而不是普通概率。因此確保應(yīng)用nn.LogSoftmaxor nn.functional.log_softmax,而不是nn.Softmax。
Softmax的計算維度
注意Softmax的計算維度。通常是輸出張量的最后一個維度,例如nn.Softmax(dim=-1)。如果混淆了維度,模型最終會得到隨機預(yù)測。
類別數(shù)據(jù)與嵌入操作
對于類別數(shù)據(jù),常見的做法是進行數(shù)值編碼。但對于深度學(xué)習(xí)而言,這并不是一個很好的操作,數(shù)值會帶來大小關(guān)系,且會丟失很多信息。因此對于類別數(shù)據(jù)建議使用one-hot或Embedding操作,對于nn.Embedding模塊,你需要設(shè)置的參數(shù)包括:
num_embeddings:數(shù)據(jù)類別的數(shù)量embedding_dim:每個類別的嵌入維度padding_idx:填充符號的索引
嵌入特征向量從隨機初始化,不要用 Kaiming、Xavier初始化方法。因為標準差為1,初始化、激活函數(shù)等被設(shè)計為輸入標準差為 1。nn.Embedding模塊的示例用法:
import torch
import torch.nn as nn
# Create 5 embedding vectors each with 32 features
embedding = nn.Embedding(num_embeddings=5,
embedding_dim=32)
# Example integer input
input_tensor = torch.LongTensor([[0, 4], [2, 3], [0, 1]])
# Get embeddings
embed_vectors = embedding(input_tensor)
print("Input shape:", input_tensor.shape)
print("Output shape:", embed_vectors.shape)
print("Example features:\n", embed_vectors[:,:,:2])
nn.LSTM 中 數(shù)據(jù)維度
默認情況下,PyTorch的nn.LSTM模塊假定輸入維度為[seq_len, batch_size, input_size],所以確保不要混淆序列長度和批大小的次數(shù)。如果混淆LSTM仍然可以正常運行,但會給出錯誤的結(jié)果。
維度不匹配
如果Pytorch執(zhí)行矩陣乘法,并兩個矩陣出現(xiàn)維度不匹配,PyTorch會報錯并拋出錯誤。但是也存在PyTorch不會拋出錯誤的情況,此時未對齊的維度具有相同的大小。建議使用多個不同的批量大小測試您的代碼,以防止維度不對齊。
訓(xùn)練和評估模式
在PyTorch中,神經(jīng)網(wǎng)絡(luò)有兩種模式:train和train。您可以使用model.eval()和model.train()對模型時進行切換。不同的模式?jīng)Q定是否使用dropout,以及如何處理Batch Normalization。常見的錯誤是在eval后忘記將模型設(shè)置回train模式,確定模型在預(yù)測階段為eval模式。
參數(shù)繼承
PyTorch支持nn.Modules,一個模塊可以包含另一個模塊,另一個模塊又可以包含一個模塊,依此類推。
當調(diào)用.parameters()時,PyTorch會查找該模塊內(nèi)的所有模塊,并將它們的參數(shù)添加到最高級別模塊的參數(shù)中。
但是PyTorch不會檢測列表、字典或類似結(jié)構(gòu)中模塊的參數(shù)。如果有一個模塊列表,請確保將它們放入一個nn.ModuleList或nn.Sequential對象中。
參數(shù)初始化
正確初始化模型的參數(shù)非常重要。用標準正態(tài)分布初始化參數(shù)不是好的選擇,推薦的方法有Kaiming或Xavier。
zero_grad()
請記住在執(zhí)行loss.backward()之前調(diào)用optimizer.zero_grad()。如果在執(zhí)行反向傳播之前沒有重置所有參數(shù)的梯度,梯度將被添加到上一批的梯度中。
指標計算邏輯
在懷疑自己或模型之前,請經(jīng)常檢查您的指標計算邏輯計算兩次或更多次。像準確性這樣的指標很容易計算,但在代碼中添加錯誤也很容易。例如,檢查您是否對批次維度進行了平均,而不是意外對類維度或任何其他維度進行平均。
設(shè)備不匹配
如果使用GPU可能會看到一個錯誤,例如:
Runtime Error: Input type (torch.FloatTensor) dand weigh type (torch.cuda.FloatTensor) should be on the same device.
此錯誤表示輸入數(shù)據(jù)在CPU上,而權(quán)重在GPU上。確保所有數(shù)據(jù)都在同一設(shè)備上。這通常是GPU,因為它支持訓(xùn)練和測試加速。
nn.Sequential和nn.ModuleList
如果模型有很多層,推薦將它們匯總為一個nn.Sequential或nn.ModuleList對象。在前向傳遞中,只需要調(diào)用sequential,或者遍歷模塊列表。
class MLP(nn.Module):
def __init__(self, input_dims=64, hidden_dims=[128,256], output_dims=10):
super().__init__()
hidden_dims = [input_dims] + hidden_dims
layers = []
for idx in range(len(hidden_dims)-1):
layers += [
nn.Linear(hidden_dims[i], hidden_dims[i+1]),
nn.ReLU(inplace=True)
]
self.layers = nn.Sequential(*layers)
def forward(self, x):
return self.layers(x)
參數(shù)重復(fù)計算
在深度神經(jīng)網(wǎng)絡(luò)中,通常會有重復(fù)添加到模型中的塊。如果這些塊需要比更復(fù)雜的前向函數(shù),建議在單獨的模塊中實現(xiàn)它們。例如,一個 ResNet 由多個具有殘差連接的ResNet塊組成。ResNet模塊應(yīng)用一個小型神經(jīng)網(wǎng)絡(luò),并將輸出添加回輸入。最好在單獨的類中實現(xiàn)這種動態(tài),以保持主模型類小而清晰。
輸入相同的維度
如果您有多個具有相同輸入的線性層或卷積,則可以將它們堆疊在一起以提高效率。假設(shè)我們有:
雖然可以通過兩個線性層來實現(xiàn)它,但您可以通過將兩層堆疊為一層來獲得完全相同的神經(jīng)網(wǎng)絡(luò)。單層效率更高,因為這代表單個矩陣運算,而不是GPU的兩個矩陣運算,因此我們可以并行化計算。
x = torch.randn(2, 10)
# Implementation of separate layers:
y1_layer = nn.Linear(10, 20)
y2_layer = nn.Linear(10, 30)
y1 = y1_layer(x)
y2 = y2_layer(x)
# Implementation of a stacked layer:
y_layer = nn.Linear(10, 50)
y = y_layer(x)
y1, y2 = y[:,:20], y[:,20:50]
使用帶logits的損失函數(shù)
分類損失函數(shù)(例如二元交叉熵)在PyTorch中有兩個版本:nn.BCELoss和nn.BCEWithLogitsLoss,建議和推薦的做法是使用后者。這因為它在數(shù)值上更穩(wěn)定,并在您的模型預(yù)測非常錯誤時防止出現(xiàn)任何不穩(wěn)定性。
如果您不使用logit損失函數(shù),則當模型預(yù)測不正確的非常高或非常低的值時,您可能會遇到問題。
如果覺得有用,就請分享到朋友圈吧!
公眾號后臺回復(fù)“CVPR21檢測”獲取CVPR2021目標檢測論文下載~

# CV技術(shù)社群邀請函 #

備注:姓名-學(xué)校/公司-研究方向-城市(如:小極-北大-目標檢測-深圳)
即可申請加入極市目標檢測/圖像分割/工業(yè)檢測/人臉/醫(yī)學(xué)影像/3D/SLAM/自動駕駛/超分辨率/姿態(tài)估計/ReID/GAN/圖像增強/OCR/視頻理解等技術(shù)交流群
每月大咖直播分享、真實項目需求對接、求職內(nèi)推、算法競賽、干貨資訊匯總、與 10000+來自港科大、北大、清華、中科院、CMU、騰訊、百度等名校名企視覺開發(fā)者互動交流~

