使用PyTorch進行深度學習任務的主要流程


引入

完成一項機器學習任務時的步驟:

  1. 數據准備(可以導入、也可以通過爬蟲爬取)。
  2. 數據預處理(數據格式的統一、必要的數據轉換),並划分訓練集和測試集。
  3. 選擇模型,並設定損失函數和優化函數以及對應的超參數。
  4. 用模型擬合訓練集數據,在驗證集/測試集上計算模型表現。
  5. 利用可視化,對訓練結果進行評價。

深度學習和機器學習的差異:

  1. 代碼實現上,深度學習樣本量大;batch訓練策略需要在訓練時每次讀取固定數量的樣本。
  2. 模型訓練上,深度神經網絡層數較多,有一些用於實現特定功能的層(如卷積層、池化層、批正則化層、LSTM層等),需要進行定制化。
  3. 訓練時,深度學習需要“放入”GPU進行訓練,將損失函數反向傳播回網絡最前面的層,同時使用優化器調整網絡參數。后續計算一些指標還需要把數據“放回”CPU。

深度學習任務步驟:

1.基本配置

導入必須的包

import os
import numpy as np
import torch
import torch.nn as nn
from torch.utils.data import Dataset, DataLoader
import torch.optim as optimizer

設置超參數

batch_size = 16 # batch中的樣本數
lr = 1e-4 # 初始學習率
max_epochs = 100 # 訓練次數

配置GPU

# 方案一:使用x,這種情況如果使用GPU不需要設置
os.environ['CUDA_VISIBLE_DEVICES'] = '1' # Only device 1 will be seen
os.environ['CUDA_VISIBLE_DEVICES'] = '0,1' # Devices 0 and 1 will be visible

# 方案二:使用“device”,后續對要使用GPU的變量用.to(device)即可
device = torch.device("cuda:1" if torch.cuda.is_available() else "cpu")

2.數據讀入

構建Dataset

1.直接使用PyTorch倉庫中准備好的數據

FashionMNIST 是一個替代 MNIST 手寫數字 的圖像數據集

training_data = datasets.FashionMNIST(
    root="data",
    train=True,
    download=True,
    transform=ToTensor()
)
  • root :訓練/測試數據的存儲路徑
  • train :強調是訓練集還是測試集
  • download=True :如果根路徑的數據不可用,就從互聯網下載數據
  • transform and target_transform :指定特征和標簽的轉換

2.自定義dataset類進行數據的讀取以及初始化

  • __init__: 用於向類中傳入外部參數,同時定義樣本集
  • __getitem__: 用於逐個讀取樣本集合中的元素,可以進行一定的變換,並將返回訓練/驗證所需的數據
  • __len__: 用於返回數據集的樣本數

使用DataLoader按批次讀入數據

DataLoader使用iterative的方式不斷讀入批次數據

train_loader = torch.utils.data.DataLoader(train_data, batch_size=batch_size, num_workers=4, shuffle=True, drop_last=True)
  • batch_size:樣本是按“批”讀入的,batch_size就是每次讀入的樣本數
  • num_workers:有多少個進程用於讀取數據
  • shuffle:是否將讀入的數據打亂
  • drop_last:對於樣本最后一部分沒有達到批次數的樣本,不再參與訓練

3.模型構建

神經網絡的構造

PyTorch中神經網絡構造一般是基於 Module 類的模型來完成的,它讓模型構造更加靈活。

Module 類是 nn 模塊里提供的一個模型構造類,是所有神經網絡模塊的基類,我們可以繼承它來定義我們想要的模型。

下面為繼承 Module 類構造多層感知機的示例。這里定義的 MLP 類重載了 Module 類的 init 函數和 forward 函數。它們分別用於創建模型參數和定義前向計算(正向傳播)。

import torch
from torch import nn

class MLP(nn.Module):
  # 聲明帶有模型參數的層,這里聲明了兩個全連接層
  def __init__(self, **kwargs):
    # 調用MLP父類Block的構造函數來進行必要的初始化。這樣在構造實例例時還可以指定其他函數
    super(MLP, self).__init__(**kwargs)
    self.hidden = nn.Linear(784, 256)
    self.act = nn.ReLU()
    self.output = nn.Linear(256,10)
    
   # 定義模型的前向計算,即如何根據輸入x計算返回所需要的模型輸出
  def forward(self, x):
    o = self.act(self.hidden(x))
    return self.output(o)   

神經網絡中常見的層

深度學習的一個魅力在於神經網絡中各式各樣的層,例如全連接層、卷積層、池化層與循環層等等。雖然PyTorch提供了大量常用的層,但有時候我們依然希望自定義層。

下面是使用 Module 來自定義層,從而可以被反復調用的示例:

  • 不含模型參數的層

    import torch
    from torch import nn
    
    class MyLayer(nn.Module):
        def __init__(self, **kwargs):
            super(MyLayer, self).__init__(**kwargs)
        def forward(self, x):
            return x - x.mean()  
    
  • 含模型參數的層

    Parameter 類其實是 Tensor 的子類,如果一 個 Tensor 是 Parameter,那么它會自動被添加到模型的參數列表里。所以在自定義含模型參數的層時,我們應該將參數定義成 Parameter,除了直接定義成 Parameter 類外,還可以使用ParameterList 和 ParameterDict 分別定義參數的列表和字典。

    class MyListDense(nn.Module):
        def __init__(self):
            super(MyListDense, self).__init__()
            self.params = nn.ParameterList([nn.Parameter(torch.randn(4, 4)) for i in range(3)])
            self.params.append(nn.Parameter(torch.randn(4, 1)))
    
        def forward(self, x):
            for i in range(len(self.params)):
                x = torch.mm(x, self.params[i])
            return x
    net = MyListDense()
    print(net)
    
  • 二維卷積層

    二維卷積層將輸入和卷積核做互相關運算,並加上一個標量偏差來得到輸出。卷積層的模型參數包括了卷積核和標量偏差。在訓練模型的時候,通常我們先對卷積核隨機初始化,然后不不斷迭代卷積核和偏差。

  • 池化層

    池化層每次對輸入數據的一個固定形狀窗口(又稱池化窗口)中的元素計算輸出。不同於卷積層里計算輸入和核的互相關性,池化層直接計算池化窗口內元素的最大值或者平均值。

4.損失函數

損失函數 功能 代碼
二分類交叉熵損失函數 計算二分類任務時的交叉熵(Cross Entropy)函數。 torch.nn.BCELoss()
交叉熵損失函數 計算交叉熵的函數。 torch.nn.CrossEntropyLoss()
L1損失函數 計算輸出y和真實標簽target之間的差值的絕對值。 torch.nn.L1Loss()
MSE損失函數 計算輸出y和真實標簽target之差的平方。 torch.nn.MSELoss()
平滑L1 (Smooth L1)損失函數 L1的平滑輸出,其功能是減輕離群點帶來的影響。 torch.nn.SmoothL1Loss()
目標泊松分布的負對數似然損失函數 泊松分布的負對數似然損失函數。 torch.nn.PoissonNLLLoss()
KL散度 計算相對熵。用於連續分布的距離度量,並且對離散采用的連續輸出空間分布進行回歸通常很有用。 torch.nn.KLDivLoss()
MarginRankingLoss 計算兩個向量之間的相似度,用於排序任務。該方法計算兩組數據之間的差異。 torch.nn.MarginRankingLoss()
多標簽邊界損失函數 對於多標簽分類問題計算損失函數。 torch.nn.MultiLabelMarginLoss()
二分類損失函數 計算二分類的 logistic 損失。 torch.nn.SoftMarginLoss()
多分類的折頁損失 計算多分類的折頁損失。 torch.nn.MultiMarginLoss()
三元組損失 計算三元組損失。 torch.nn.TripletMarginLoss()
HingEmbeddingLoss 對輸出的embedding結果做Hing損失計算。 torch.nn.HingeEmbeddingLoss()
余弦相似度 對於兩個向量做余弦相似度損失計算。 torch.nn.CosineEmbeddingLoss()
CTC損失函數 用於解決時序類數據的分類。計算連續時間序列和目標序列之間的損失。 torch.nn.CTCLoss()

5.優化器

優化器就是根據網絡反向傳播的梯度信息來更新網絡的參數,以起到降低loss函數計算值,使得模型輸出更加接近真實標簽。

Pytorch提供的優化器庫torch.optim:

  • torch.optim.ASGD

  • torch.optim.Adadelta

  • torch.optim.Adagrad

  • torch.optim.Adam

  • torch.optim.AdamW

  • torch.optim.Adamax

  • torch.optim.LBFGS

  • torch.optim.RMSprop

  • torch.optim.Rprop

  • torch.optim.SGD

  • torch.optim.SparseAdam

    優化器的選擇是需要根據模型進行改變的,不存在絕對的好壞之分,需要多進行一些測試。

6.訓練與評估

在PyTorch中設置模型狀態:

  • 訓練狀態,模型的參數支持反向傳播的修改;
  • 驗證/測試狀態,則不能修改模型參數。
model.train()   # 訓練狀態
model.eval()   # 驗證/測試狀態

用for循環讀取DataLoader中的全部數據。

for data, label in train_loader:

之后將數據放到GPU上用於后續計算,此處以.cuda()為例

data, label = data.cuda(), label.cuda()

開始用當前批次數據做訓練時,應當先將優化器的梯度置零:

optimizer.zero_grad()

之后將data送入模型中訓練:

output = model(data)

根據預先定義的criterion計算損失函數:

loss = criterion(output, label)

將loss反向傳播回網絡:

loss.backward()

使用優化器更新模型參數:

optimizer.step()

這樣一個訓練過程就完成了,后續還可以計算模型准確率等指標。

驗證/測試的流程基本與訓練過程一致,不同點在於:

  • 需要預先設置torch.no_grad,以及將model調至eval模式
  • 不需要將優化器的梯度置零
  • 不需要將loss反向回傳到網絡
  • 不需要更新模型參數

7.可視化

某些任務在訓練完成后,需要對一些必要的內容進行可視化,比如分類的ROC曲線,卷積網絡中的卷積核,以及訓練/驗證過程的損失函數曲線等。

參考鏈接:

  1. Datawhale深入淺出PyTorch第三章:https://github.com/datawhalechina/thorough-pytorch/tree/main/%E7%AC%AC%E4%B8%89%E7%AB%A0%20PyTorch%E7%9A%84%E4%B8%BB%E8%A6%81%E7%BB%84%E6%88%90%E6%A8%A1%E5%9D%97
  2. PyTorch官方文檔:https://pytorch.org/tutorials/beginner/basics/data_tutorial.html#:~:text=PyTorch%20provides%20two%20data%20primitives%3A%20torch.utils.data.DataLoader%20and%20torch.utils.data.Dataset,Dataset%20to%20enable%20easy%20access%20to%20the%20samples.
  3. Dataset類的使用:https://www.jianshu.com/p/4818a1a4b5bd


免責聲明!

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



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