PyTorch 深度學習新手入門指南
- 2019 年 10 月 4 日
- 筆記
作 者 | Nikhila Munipalli
翻 譯 | 天字一號(鄭州大學)、Ryan(西安理工大學)、申影(山東大學)、鄴調(江蘇科技大學)、Loing(華中科技大學)
審 校 | 唐里、鳶尾、skura
歡迎深度學習的學習者,這篇文章是為想開始用pytorch來進行深度學習項目研究的人準備的。
預備知識:
為了更好的理解這些知識,你需要確定自己滿足下面的幾點要求:
1. 如果在領英上,你也許會說自己是一個深度學習的狂熱愛好者,但是你只會用 keras 搭建模型,那麼,這篇文章非常適合你。
2. 你可能對理解 tensorflow 中的會話,變數和類等有困擾,並且計劃轉向 pytorch,很好,你來對地方了。
3. 如果你能夠用 pytorch 構建重要、複雜的模型,並且現在正在找尋一些實現細節,不好意思,你可以直接跳到最後一部分。
讓我們開始吧!
既然都看到這裡了,說明你的確對深度學習有興趣!
老生常談的話題:
什麼是 pytorch,它和 keras 之間的區別是什麼?
初學者很容易通過以下兩行指令,通過添加dense層和一些dropouts層去建立一個神經網路:
from keras.models import Sequential from keras.layers import Dense, Dropout
就像這樣:
import Andrew as ng !
如果你需要處理 tensor,建立足夠複雜的模型,創建一些用戶損失函數,或者需要理解在每一層究竟發生了什麼,pytorch 這時候可以派上用場了,它是一個對n維數據處理來說絕好的工具,它不僅能夠載入大量有用的文檔,同時也具備 keras 的簡便性。
它對初學者非常友好!
pytorch 因其出色的調試能力,對多種平台的支援和容易上手而聞名,它並沒有涉及到類似keras中的大量計算。
開始設置
步驟1:硬體設置:深度學習模型總是伴隨著大量的數據。顯然,GPU是必須的。有關cuda和nvidia的設置:請查看:https://missinglink.ai/guides/deep-learning-frameworks/complete-guide-deep-learning-gpus/。
步驟2:安裝:Pytorch幾分鐘就裝好了,在他們的官方網站上有一行ctrl+C——ctrl+V。轉到他們的網站(https://pytorch.org/),向下滾動,選擇你的設置參數,複製該鏈接並粘貼到你的終端!搞定了!可以準備使用它啦!還可以安裝tensorboardX 來顯示結果。有關安裝的說明,請參閱此 GitHub repo(https://github.com/lanpa/tensorboardX)。
步驟3:基本步驟: 這有關於 udemy 的很好的課程,討論基本的語法,用法和功能。pytorch不需要那麼大的努力!它非常類似於Numpy,並且有許多預定義的函數。一旦你開始編碼,你就可以發現一些東西。
接下來是有趣的部分!
步驟4:引入必須庫:

這些是任何模式的深度學習所必需的庫。nn模組具有所有必要的損失函數、層數、時序模型、激活函數等。其餘部分將隨著你的進一步深入而進行討論。
第二個問題:
TorchTensor (張量)和 Variable(變數)之間有什麼區別?
你一定注意到我們從torch.autograd 導入了Variable庫。Tensors只是n維陣列。對於像反向傳播的功能,張量必須與它們的關聯梯度耦合。對一個 torch Variable 來說也是如此。它是一個具有相應梯度的張量,使得所有張量操作都非常簡單!有關詳細資訊,請查看此q&a(https://discuss.pytorch.org/t/what-is-the-difference-between-tensors-and-variables-in-pytorch/4914)。
在所有這些基礎上,我們可以開始構建我們的模型了!
模組 1:網路類
步驟1:繼承。要構建神經網路模型,必須創建繼承自 nn.module 的類,其中nn.module 給出了創建自己網路的結構。示例程式碼如下:
class Network(nn.Module): def __init__(self): super(Network, self).__init__()
步驟2:網路層。nn.module中定義有不同的網路層,如linear, LSTM, dropout等。如果你習慣Keras順序模型,nn.sequential就是這樣。就個人而言,我不建議使用nn.sequential ,因為它不能發揮出pytorch的真實意圖。向模型中添加層的更好方法是用nn創建一個層,並將其分配給網路類的私有成員。示例程式碼如下:
self.linear = nn.linear(input dim, output dim)
在網路類的init方法中將所有層聲明為類變數。
步驟3:前向傳播函數。這是網路的核心和靈魂。當你調用網路模型進行訓練或預測時,都會執行你在forward函數中編寫的步驟。因此,我們重寫nn.module類中的forward函數,確切地告訴網路模型要做什麼。如果forward函數使用了除類變數之外的參數,那每次調用模型時都必須給forward函數傳遞這些參數。
def forward(self,x): out = self.linear1(x) out = self.linear2(out) return out
創建了兩層的神經網路,傳遞張量或變數。
步驟4:附加函數:通過上述步驟,所有需要做的工作都已經完成了!有時,當模型具有 LSTM 層時,需要初始化隱藏圖層的功能。同樣,如果你嘗試構建玻爾茲曼機時,則需要對隱藏節點和可見節點進行取樣。因此,可以在我們的網路類里創建和使用新的成員函數。
步驟5:類的參數:使用類構建網路時,請確保使用的是最小值或沒有硬編碼值。初始化類時,可以忽略學習速率、隱藏圖層的大小。
如果你成功理解了上述所有步驟,並且能夠直觀地顯示網路,接下來,讓我們完成下一個小但重要的功能模組。
模組 2:自定義數據載入器
在你的數據上,你是否從頭做過訓練集、測試集的劃分,batch size的設置,shuffles等操作?Keras 具有參數" batchsize",用於處理不規則的batch大小。但是,如果你想在Pytorch中實現它,需要相當多的努力。
別擔心!自定義數據載入器在這裡!
DataLoader是一個術語,用於從給定數據中創建訓練、測試和驗證數據,具有自動批處理大小、隨機打亂順序等功能。
pytorch具有默認數據載入器類,可以使用 torch.utils.dataloader 導入該類。這樣,你可以直接使你的數據模型!
與使用默認數據載入程式相比,根據你的要求很容易構建自定義數據載入器。讓我們看看怎麼做!
你是否還記得importingdata from torch.utils?
構建自定義數據載入器非常簡單,只需執行以下步驟:
第1步:繼承 :類似於我們構建網路類是需要繼承 nn.Module的,同樣我們將繼承數據。DataLoader需要繼承Dataset類,但可以不必像以前那樣調用 init 構造函數,只需要這樣:
class dataset(data.Dataset):
步驟 2:sequences和labels:data.Dataset類具有稱為sequences的成員,這些成員 與X 數據或訓練數據相對應, labels 與y相對應。你可以創建名為partition的選項,根據該選項將返回其相應的數據。
例如:
class dataset(data.Dataset): def __init__(self, partition): if partition==』train』: self.sequences = X_train self.labels = y_train
步驟3:len 方法:_len_()是一個data.Dataset函數,需要重寫才能在我們dataloader中生效,返回的是sequences 的長度。
步驟4 :getitem 方法 :__getitem__ (self, index)是在給定索引處返回sequences 和 labels的方法。這個函數也必須重寫。
步驟5:generators 和 parameterdict:通過上述步驟,創建自定義數據載入器類完成。現在,可以使用它了!
數據,由dataloader發送,以generators的形式使用。因此,基於生產的數據,一個參數dict必須創建。包含鍵:batch_size、shuffle,num_workers。數據載入器類的對象將被實例化,並隨參數 dict 一起傳遞給生成器:
params= {『batch_size』 : 10, 『shuffle』 : True, 『num_workers』 : 20} training_set = dataset(X, y, 『train') training_generator = torch.utils.data.dataloader(training_set, **params)
在官方文件中可以了解更多參數(https://pytorch.org/docs/stable/_modules/torch/utils/data/dataloader.html)。
獲得數據是不是毫不費力?!如果是,現在,我們有了網路結構和數據,我們的模型已經準備好試驗!
因此,讓我們繼續我們的第三個模組!
模組 3:訓練函數
現在已經分別為網路結構和數據建立了兩個類,訓練函數的作用就是講這兩個類聯繫起來,讓模型能夠學習。
步驟1:Parameters(參數) :網路類是最重要的參數。然後才是訓練生成器和驗證生成器。設置這些必要的參數後,epoch、學習率、batch size、clip、loss等參數可以暫時略過。這些參數不要設置一個固定的值,而作為一個參數變數。
步驟2:Initialization (初始化):開始訓練需要對網路進行初始化,設置訓練模式,如下:
net.train()
損失函數和優化器必須使用nnmodule指定,例如
criterion = nn.MSELoss() optimizer = torch.optim.Adam(net.parameters(), lr=lr)
初始化值之後,模型就可以訓練了。
步驟3:the epoch loop (循環次數):開始進行訓練循環,該循環是將數據遍歷 n 次。在循環結束時,列印損耗(訓練和驗證)對應於那個epoch的值。
步驟4:TQDM循環:循環可能永遠運行!尤其是對於有大量數據的深度學習模型!很難弄清楚裡面發生了什麼,需要多少時間才能完成。TQDM在這裡!它是每個迭代的進度條。看看這裡的官方文件。迭代器必須分配給TQDM並在循環中使用。
對於每一個時代,我們的函數都在批量大小上迭代。這裡的迭代器是訓練生成器。
TQDM循環如下所示:
t = tqdm(iter(training_generator), leave=False, total=len(training_generator)) for i, batch in enumerate(t): x_batch, y_batch = next(iter(training_generator))
步驟5:GPU可用性:變數、對象等可以通過一個pytorch命令傳輸到GPU。
包括一行:
torch.cuda.set_ device(0)
在程式碼的開頭。0表示要使用的GPU編號。
當你覺得有必要把一些變數轉移到CUDA時,
do:x=x.cuda()。
但是,不管底層硬體如何,我們的程式碼都應該運行。如果GPU不存在,就不能將變數傳輸到CUDA。程式碼顯示該行中的錯誤。為了擺脫這些依賴關係,考慮一個變數,它保存了GPU可用性的布爾值。
你的程式碼可以調整成這樣:
if gpu_available: X= X.cuda()
步驟6: 訓練過程 :設置必要的東西之後,從網路的結構開始進行訓練:
output = net(x)
這裡傳遞的參數是forward 函數中提到的參數。
獲得輸出後,損失計算為 :
loss = criterion(output, targets)
反向傳播為:
loss.backward() optimizer.step()
Optimizer.step() 是用來更新參數(權重和偏置),這些參數是基於反向傳播的損失計算的。
通過tqdm 迭代器可以列印損失值:
t.set_postfix(loss=train_loss)
步驟7: 評估:訓練結束後需進行模型評估,模型首先應該設置成評估模式。
net.eval()
評估之後,確保模型再設置成訓練模式,利用net.train()設置。
步驟8: 保存模型和參數:成功訓練模型後,需要保存模型和參數以便以後使用,這裡有兩種方法可以使用。
1.torch.save(),用這種方法保存整個模型,包括它的目錄結構,使用下列語句
torch.save(net, path) #saving net = torch.load(path) #loading
2.model.state_dict():state_dict函數只保存了模型中的參數(權重和偏差等等),並沒有包含模型的結構。要使用這樣方法保存的參數,必須創建模型的結構,構建一個結構類的實例,並指定對於的參數。
torch.save(net.state_dict(), path) #saving net = Network(*args, **kwargs) #loading net.load_state_dict(torch.load(path))
第三個問題:
何時使用torch.save()以及何時使用model.state_dict()?
如上所述,torch.save保存整個模型。要載入它,不必實例化網路類。在模型應該在完全不同的平台上工作而不考慮底層程式碼的情況下,torch.save()是非常有利的。
相反,如果你正在執行實驗,state_dict()非常有利,因為它只保存模型的參數,並且對於任何進一步的修改都是靈活的。
查看這些StackOverflow答案了解更多詳細資訊。
恭喜!如果你做到這一步,你幾乎把你的模型建立到完美了!為了組織程式碼和執行實驗,我們來看一個最後的模組。
順便說一句,?這也是最後一個模組啦?!
最後:組織
在大量的實驗中,參數調整通常是在一個深度學習模型上進行的,將它們存儲在一個合適的目錄結構中是非常重要的。以下是需要遵循的幾個步驟:
步驟1:配置文件:學習速率、損失函數、周期數等參數都會發生變化。要跟蹤所有這些參數,請創建一個配置文件,並包含所有可以使用的參數。在實例化類或調用函數時,你可以將這些變數導入為:
from config import *
並且使用。當必須執行各種嘗試和錯誤方法時,更改配置文件就足夠了。
步驟2:TensorBoard:還記得從TensorBoardX導入SummaryWriter嗎?如前所述,可以用tensorboard 顯示損失、精度等。
在列車運行前,只需添加一行,即可包含tensorboard :
writer = SummaryWriter(path)
在每個epoch循環中,包括:
writer.add_scalar(『loss』, loss, epoch_number) writer.add_scalar('accuracy', accuracy, epoch_number)
你可以使用各種參數添加任意的多個圖。
在訓練函數的結尾,關閉writer
writer.close()
請記住更改後面tensorboard 寫入的路徑,因為圖可能被覆蓋或重寫。
步驟 3 :requirements 文件 : 這個東西可能太陳詞濫調了,但最好有一個 requirements 文件,其中包含所有庫及其版本使用。使用requirements 文件的好處是使用單個命令就可以處理所有依賴項。
查看此鏈接,了解如何凍結所有要求:https://stackoverflow.com/questions/31684375/automatically-create-requirements-txt。
第4步:一個readme:經過辛苦的工作之後,你完全有權利吹噓你的工作,並引導人們使用你的程式碼!readme 的功能就是這樣。通過添加定性和定量的readme來結束你的項目!
現在,所有的工作都完成了!!最後,祝賀你成功完成所有四個模組!
最後,讓我們快速地看一看項目架構:

希望你的項目架構和我們的一樣!
最後,休息一下,開始建一個網路吧!
P.S:感謝 A.ManojGhuhan和Niyati Chhaya的指導並糾正我的錯誤,使我在這個領域更自信!
via https://medium.com/@nikhilamunipalli/starter-pack-for-deep-learning-in-pytorch-for-extreme-beginners-by-a-beginner-330f3fdefcc4