中文字幕在线观看,亚洲а∨天堂久久精品9966,亚洲成a人片在线观看你懂的,亚洲av成人片无码网站,亚洲国产精品无码久久久五月天

PyTorch經(jīng)驗指南:技巧與陷阱

2018-07-31    來源:raincent

容器云強勢上線!快速搭建集群,上萬Linux鏡像隨意使用
PyTorch 的構建者表明,PyTorch 的哲學是解決當務之急,也就是說即時構建和運行計算圖。目前,PyTorch 也已經(jīng)借助這種即時運行的概念成為最受歡迎的框架之一,開發(fā)者能快速構建模型與驗證想法,并通過神經(jīng)網(wǎng)絡交換格式 ONNX 在多個框架之間快速遷移。本文從基本概念開始介紹了 PyTorch 的使用方法、訓練經(jīng)驗與技巧,并展示了可能出現(xiàn)的問題與解決方案。

項目地址:https://github.com/Kaixhin/grokking-pytorch

PyTorch 是一種靈活的深度學習框架,它允許通過動態(tài)神經(jīng)網(wǎng)絡(例如利用動態(tài)控流——如 if 語句或 while 循環(huán)的網(wǎng)絡)進行自動微分。它還支持 GPU 加速、分布式訓練以及各類優(yōu)化任務,同時還擁有許多更簡潔的特性。以下是作者關于如何利用 PyTorch 的一些說明,里面雖然沒有包含該庫的所有細節(jié)或最優(yōu)方法,但可能會對大家有所幫助。

神經(jīng)網(wǎng)絡是計算圖的一個子類。計算圖接收輸入數(shù)據(jù),數(shù)據(jù)被路由到對數(shù)據(jù)執(zhí)行處理的節(jié)點,并可能被這些節(jié)點轉換。在深度學習中,神經(jīng)網(wǎng)絡中的神經(jīng)元(節(jié)點)通常利用參數(shù)或可微函數(shù)轉換數(shù)據(jù),這樣可以優(yōu)化參數(shù)以通過梯度下降將損失最小化。更廣泛地說,函數(shù)是隨機的,圖結構可以是動態(tài)的。所以說,雖然神經(jīng)網(wǎng)絡可能非常適合數(shù)據(jù)流式編程,但 PyTorch 的 API 卻更關注命令式編程——一種編程更?紤]的形式。這令讀取代碼和推斷復雜程序變得簡單,而無需損耗不必要的性能;PyTorch 速度很快,且擁有大量優(yōu)化,作為終端用戶你毫無后顧之憂。

本文其余部分寫的是關于 grokking PyTorch 的內容,都是基于 MINIST 官網(wǎng)實例,應該要在學習完官網(wǎng)初學者教程后再查看。為便于閱讀,代碼以塊狀形式呈現(xiàn),并帶有注釋,因此不會像純模塊化代碼一樣被分割成不同的函數(shù)或文件。

Pytorch 基礎

PyTorch 使用一種稱之為 imperative / eager 的范式,即每一行代碼都要求構建一個圖,以定義完整計算圖的一個部分。即使完整的計算圖還沒有構建好,我們也可以獨立地執(zhí)行這些作為組件的小計算圖,這種動態(tài)計算圖被稱為「define-by-run」方法。

 

 

PyTorch 張量

正如 PyTorch 文檔所說,如果我們熟悉 NumPy 的多維數(shù)組,那么 Torch 張量的很多操作我們能輕易地掌握。PyTorch 提供了 CPU 張量和 GPU 張量,并且極大地加速了計算的速度。

從張量的構建與運行就能體會,相比 TensorFLow,在 PyTorch 中聲明張量、初始化張量要簡潔地多。例如,使用 torch.Tensor(5, 3) 語句就能隨機初始化一個 5×3 的二維張量,因為 PyTorch 是一種動態(tài)圖,所以它聲明和真實賦值是同時進行的。

在 PyTorch 中,torch.Tensor 是一種多維矩陣,其中每個元素都是單一的數(shù)據(jù)類型,且該構造函數(shù)默認為 torch.FloatTensor。以下是具體的張量類型:

 

 

除了直接定義維度,一般我們還可以從 Python 列表或 NumPy 數(shù)組中創(chuàng)建張量。而且根據(jù)使用 Python 列表和元組等數(shù)據(jù)結構的習慣,我們可以使用相似的索引方式進行取值或賦值。PyTorch 同樣支持廣播(Broadcasting)操作,一般它會隱式地把一個數(shù)組的異常維度調整到與另一個算子相匹配的維度,以實現(xiàn)維度兼容。

自動微分模塊

TensorFlow、Caffe 和 CNTK 等大多數(shù)框架都使用靜態(tài)計算圖,開發(fā)者必須建立或定義一個神經(jīng)網(wǎng)絡,并重復使用相同的結構來執(zhí)行模型訓練。改變網(wǎng)絡的模式就意味著我們必須從頭開始設計并定義相關的模塊。

但 PyTorch 使用的技術為自動微分(automatic differentiation)。在這種機制下,系統(tǒng)會有一個 Recorder 來記錄我們執(zhí)行的運算,然后再反向計算對應的梯度。這種技術在構建神經(jīng)網(wǎng)絡的過程中十分強大,因為我們可以通過計算前向傳播過程中參數(shù)的微分來節(jié)省時間。

從概念上來說,Autograd 會維護一個圖并記錄對變量執(zhí)行的所有運算。這會產(chǎn)生一個有向無環(huán)圖,其中葉結點為輸入向量,根結點為輸出向量。通過從根結點到葉結點追蹤圖的路徑,我們可以輕易地使用鏈式法則自動計算梯度。

 

 

在內部,Autograd 將這個圖表征為 Function 對象的圖,并且可以應用 apply() 計算評估圖的結果。在計算前向傳播中,當 Autograd 在執(zhí)行請求的計算時,它還會同時構建一個表征梯度計算的圖,且每個 Variable 的 .grad_fn 屬性就是這個圖的輸入單元。在前向傳播完成后,我們可以在后向傳播中根據(jù)這個動態(tài)圖來計算梯度。

PyTorch 還有很多基礎的模塊,例如控制學習過程的最優(yōu)化器、搭建深度模型的神經(jīng)網(wǎng)絡模塊和數(shù)據(jù)加載與處理等。這一節(jié)展示的張量與自動微分模塊是 PyTorch 最為核心的概念之一,讀者可查閱 PyTorch 文檔了解更詳細的內容。

下面作者以 MNIST 為例從數(shù)據(jù)加載到模型測試具體討論了 PyTorch 的使用、思考技巧與陷阱。

PyTorch 實用指南

導入

 

 

除了用于計算機視覺問題的 torchvision 模塊外,這些都是標準化導入。

設置

 

 

argparse 是在 Python 中處理命令行參數(shù)的一種標準方式。

編寫與設備無關的代碼(可用時受益于 GPU 加速,不可用時會倒退回 CPU)時,選擇并保存適當?shù)?torch.device, 不失為一種好方法,它可用于確定存儲張量的位置。關于與設備無關代碼的更多內容請參閱官網(wǎng)文件。PyTorch 的方法是使用戶能控制設備,這對簡單示例來說有些麻煩,但是可以更容易地找出張量所在的位置——這對于 a)調試很有用,并且 b)可有效地使用手動化設備。

對于可重復實驗,有必要為使用隨機數(shù)生成的任何數(shù)據(jù)設置隨機種子(如果也使用隨機數(shù),則包括隨機或 numpy)。要注意,cuDNN 用的是非確定算法,可以通過語句 torch.backends.cudnn.enabled = False 將其禁用。

數(shù)據(jù)

 

 

torchvision.transforms 對于單張圖像有非常多便利的轉換工具,例如裁剪和歸一化等。

DataLoader 包含非常多的參數(shù),除了 batch_size 和 shuffle,num_workers 和 pin_memory 對于高效加載數(shù)據(jù)同樣非常重要。例如配置 num_workers > 0 將使用子進程異步加載數(shù)據(jù),而不是使用一個主進程塊加載數(shù)據(jù)。參數(shù) pin_memory 使用固定 RAM 以加速 RAM 到 GPU 的轉換,且在僅使用 CPU 時不會做任何運算。

模型

 

 

神經(jīng)網(wǎng)絡初始化一般包括變量、包含可訓練參數(shù)的層級、可能獨立的可訓練參數(shù)和不可訓練的緩存器。隨后前向傳播將這些初始化參數(shù)與 F 中的函數(shù)結合,其中該函數(shù)為不包含參數(shù)的純函數(shù)。有些開發(fā)者喜歡使用完全函數(shù)化的網(wǎng)絡(如保持所有參數(shù)獨立,使用 F.conv2d 而不是 nn.Conv2d),或者完全由 layers 函數(shù)構成的網(wǎng)絡(如使用 nn.ReLU 而不是 F.relu)。

在將 device 設置為 GPU 時,.to(device) 是一種將設備參數(shù)(和緩存器)發(fā)送到 GPU 的便捷方式,且在將 device 設置為 CPU 時不會做任何處理。在將網(wǎng)絡參數(shù)傳遞給優(yōu)化器之前,把它們傳遞給適當?shù)脑O備非常重要,不然的話優(yōu)化器不能正確地追蹤參數(shù)。

神經(jīng)網(wǎng)絡(nn.Module)和優(yōu)化器(optim.Optimizer)都能保存和加載它們的內部狀態(tài),而.load_state_dict(state_dict) 是完成這一操作的推薦方法,我們可以從以前保存的狀態(tài)字典中加載兩者的狀態(tài)并恢復訓練。此外,保存整個對象可能會出錯。

這里沒討論的一些注意事項即前向傳播可以使用控制流,例如一個成員變量或數(shù)據(jù)本身能決定 if 語句的執(zhí)行。此外,在前向傳播的過程中打印張量也是可行的,這令 debug 更加簡單。最后,前向傳播可以使用多個參數(shù)。以下使用間斷的代碼塊展示這一點:

 

 

訓練

 

 

網(wǎng)絡模塊默認設置為訓練模式,這影響了某些模塊的工作方式,最明顯的是 dropout 和批歸一化。最好用.train() 對其進行手動設置,這樣可以把訓練標記向下傳播到所有子模塊。

在使用 loss.backward() 收集一系列新的梯度以及用 optimiser.step() 做反向傳播之前,有必要手動地將由 optimiser.zero_grad() 優(yōu)化的參數(shù)梯度歸零。默認情況下,PyTorch 會累加梯度,在單次迭代中沒有足夠資源來計算所有需要的梯度時,這種做法非常便利。

PyTorch 使用一種基于 tape 的自動化梯度(autograd)系統(tǒng),它收集按順序在張量上執(zhí)行的運算,然后反向重放它們來執(zhí)行反向模式微分。這正是為什么 PyTorch 如此靈活并允許執(zhí)行任意計算圖的原因。如果沒有張量需要做梯度更新(當你需要為該過程構建一個張量時,你必須設置 requires_grad=True),則不需要保存任何圖。然而,網(wǎng)絡傾向于包含需要梯度更新的參數(shù),因此任何網(wǎng)絡輸出過程中執(zhí)行的計算都將保存在圖中。因此如果想保存在該過程中得到的數(shù)據(jù),你將需要手動禁止梯度更新,或者,更常見的做法是將其保存為一個 Python 數(shù)(通過一個 Python 標量上的.item())或者 NumPy 數(shù)組。更多關于 autograd 的細節(jié)詳見官網(wǎng)文件。

截取計算圖的一種方式是使用.detach(),當通過沿時間的截斷反向傳播訓練 RNN 時,數(shù)據(jù)流傳遞到一個隱藏狀態(tài)可能會應用這個函數(shù)。當對損失函數(shù)求微分(其中一個成分是另一個網(wǎng)絡的輸出)時,也會很方便。但另一個網(wǎng)絡不應該用「loss - examples」的模式進行優(yōu)化,包括在 GAN 訓練中從生成器的輸出訓練判別器,或使用價值函數(shù)作為基線(例如 A2C)訓練 actor-critic 算法的策略。另一種在 GAN 訓練(從判別器訓練生成器)中能高效阻止梯度計算的方法是在整個網(wǎng)絡參數(shù)上建立循環(huán),并設置 param.requires_grad=False,這在微調中也很常用。

除了在控制臺/日志文件里記錄結果以外,檢查模型參數(shù)(以及優(yōu)化器狀態(tài))也是很重要的。你還可以使用 torch.save() 來保存一般的 Python 對象,但其它標準選擇還包括內建的 pickle。

測試

 

 

為了早點響應.train(),應利用.eval() 將網(wǎng)絡明確地設置為評估模式。

正如前文所述,計算圖通常會在使用網(wǎng)絡時生成。通過 with torch.no_grad() 使用 no_grad 上下文管理器,可以防止這種情況發(fā)生。

其它

內存有問題?可以查看官網(wǎng)文件獲取幫助。

CUDA 出錯?它們很難調試,而且通常是一個邏輯問題,會在 CPU 上產(chǎn)生更易理解的錯誤信息。如果你計劃使用 GPU,那最好能夠在 CPU 和 GPU 之間輕松切換。更普遍的開發(fā)技巧是設置代碼,以便在啟動合適的項目(例如準備一個較小/合成的數(shù)據(jù)集、運行一個 train + test epoch 等)之前快速運行所有邏輯來檢查它。如果這是一個 CUDA 錯誤,或者你沒法切換到 CPU,設置 CUDA_LAUNCH_BLOCKING=1 將使 CUDA 內核同步啟動,從而提供更詳細的錯誤信息。

torch.multiprocessing,甚至只是一次運行多個 PyTorch 腳本的注意事項。因為 PyTorch 使用多線程 BLAS 庫來加速 CPU 上的線性代數(shù)計算,所以它通常需要使用多個內核。如果你想一次運行多個任務,在具有多進程或多個腳本的情況下,通過將環(huán)境變量 OMP_NUM_THREADS 設置為 1 或另一個較小的數(shù)字來手動減少線程,這樣做減少了 CPU thrashing 的可能性。官網(wǎng)文件還有一些其它注意事項,尤其是關于多進程。

標簽: 代碼 腳本 開發(fā)者 網(wǎng)絡

版權申明:本站文章部分自網(wǎng)絡,如有侵權,請聯(lián)系:west999com@outlook.com
特別注意:本站所有轉載文章言論不代表本站觀點!
本站所提供的圖片等素材,版權歸原作者所有,如需使用,請與原作者聯(lián)系。

上一篇:當 AI 掌握「讀心術」:DeepMind AI 已經(jīng)學會相互理解

下一篇:從技術到人才,清華-中國工程院知識智能聯(lián)合實驗室發(fā)布「2018自然語言處理研究報告」