pytorch模型訓練加速tricks


1、學習率設置策略

Pytorch 已經實現了兩種方法:「torch.optim.lr_scheduler.CyclicLR」和「torch.optim.lr_scheduler.OneCycleLR」。
參考文檔:https://pytorch.org/docs/stable/optim.html

2、dataloader中使用多個worker和頁鎖定內存

當使用 torch.utils.data.DataLoader 時 num_workers > 0 pin_memory=True

worker 數量的經驗法則是將其設置為可用 GPU 數量的四倍,大於或小於這個數都會降低訓練速度。請注意,增加 num_workers 將增加 CPU 內存消耗。

參考文檔:https://pytorch.org/docs/stable/data.html

3、增大batch

 batch 調到最大是一個頗有爭議的觀點。一般來說,如果在 GPU 內存允許的范圍內將 batch 調到最大,你的訓練速度會更快。

但是,你也必須調整其他超參數,比如學習率。一個比較好用的經驗是,batch 大小加倍時,學習率也要加倍。

4、換一種優化器

AdamW 是由 fast.ai 推廣的一種具有權重衰減(而不是 L2 正則化)的 Adam,在 PyTorch 中以 torch.optim.AdamW 實現。AdamW 似乎在誤差和訓練時間上都一直優於 Adam。
Adam 和 AdamW 都能與上面提到的 1Cycle 策略很好地搭配。

5、cudnn基准

如果你的模型架構保持不變、輸入大小保持不變,設置 torch.backends.cudnn.benchmark = True

6、小心CPU和GPU之間數據的傳輸

當頻繁地使用 tensor.cpu() 將張量從 GPU 轉到 CPU(或使用 tensor.cuda() 將張量從 CPU 轉到 GPU)時,代價是非常昂貴的。item() 和 .numpy() 也是一樣可以使用. detach() 代替。
如果你創建了一個新的張量,可以使用關鍵字參數 device=torch.device('cuda:0') 將其分配給 GPU。
如果你需要傳輸數據,可以使用. to(non_blocking=True),只要在傳輸之后沒有同步點。

7、使用梯度積累

增加 batch 大小的另一種方法是在調用 optimizer.step() 之前在多個. backward() 傳遞中累積梯度。

Hugging Face 的 Thomas Wolf 的文章《Training Neural Nets on Larger Batches: Practical Tips for 1-GPU, Multi-GPU & Distributed setups》介紹了如何使用梯度累積。梯度累積可以通過如下方式實現:

model.zero_grad()                                   
# Reset gradients tensors
for i, (inputs, labels) in enumerate(training_set): predictions = model(inputs)
# Forward pass
loss = loss_function(predictions, labels)
# Compute loss function
loss = loss / accumulation_steps
# Normalize our loss (if averaged)
loss.backward()
# Backward pass
if (i+1) % accumulation_steps == 0:
# Wait for several backward steps
optimizer.step()
# Now we can do an optimizer step
model.zero_grad()
# Reset gradients tensors
if (i+1) % evaluation_steps == 0:
# Evaluate the model when we...
            evaluate_model()                        
# ...have no gradients accumulate

這個方法主要是為了規避 GPU 內存的限制而開發的。

8、分布式數據並行進行多GPU訓練

加速分布式訓練可能有很多方法,但是簡單的方法是使用 torch.nn.DistributedDataParallel 而不是 torch.nn.DataParallel。

這樣一來,每個 GPU 將由一個專用的 CPU 核心驅動,避免了 DataParallel 的 GIL 問題。

分布式訓練文檔地址:https://pytorch.org/tutorials/beginner/dist_overview.html

9、設置梯度為None,而不是0

梯度設置為. zero_grad(set_to_none=True) 而不是 .zero_grad()。

這樣做可以讓內存分配器處理梯度,而不是將它們設置為 0。

正如文檔中所說,將梯度設置為 None 會產生適度的加速,但不要期待奇跡出現。

注意,這樣做也有缺點,詳細信息請查看文檔。

文檔地址:https://pytorch.org/docs/stable/optim.html

10、使用.as_tensor() 而不是.tensor()

torch.tensor() 總是會復制數據。如果你要轉換一個 numpy 數組,使用 torch.as_tensor() 或 torch.from_numpy() 來避免復制數據。

11、驗證期間關閉梯度計算

設置:torch.no_grad()

12、使用輸入和batch歸一化


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM