用pytorch實現LeNet-5網路

靡非斯特發表於2024-08-17

 上篇講述了LeNet-5網路的理論,本篇就試著搭建LeNet-5網路。但是搭建完成的網路還存在著問題,主要是訓練的準確率太低,還有待進一步探究問題所在。是超引數的調節有問題?還是網路的結構有問題?還是哪裡搞錯了什麼

1.庫的匯入

  • dataset: datasets.MNIST()函式,該函式作用是匯入MNIST資料庫,以供後續使用。
  • torch.nn.functional() 主要是用到了F.relu(),relu啟用函式。
  • nn.Linear() , nn.MaxPool2d() , nn.Conv2d(),起到構建卷積神經網路各隱藏層的函式。
  • optim:模組扮演著最佳化演算法的角色,它提供了多種最佳化演算法的實現,用於更新和調整模型中的引數(即權重和偏置),以最小化或最大化某個損失函式(通常是最小化)。這些最佳化演算法是深度學習訓練過程中不可或缺的一部分,因為它們決定了模型如何根據損失函式的梯度來更新其引數,從而逐步改進模型的效能。
    optim.Adam() :一種基於梯度下降的最佳化演算法,結合了AdaGrad和RMSProp兩種最佳化演算法的思想,具有計算高效、記憶體需求小、適合解決大規模和高維空間最佳化問題的優點。
  • no_grad: no_grade()關閉自動向求導,主要是在對網路進行測試時,起到加快模型速度和減小記憶體的作用。
  • DataLoader:起到對資料集進行分組的作用,在訓練模型時,並不是把訓練集中的所有樣本載入到X中去,而是把樣本分批次進行計算,在多批次後完成對訓練集中樣本的遍歷,也叫做一個週期。
  • TensorDataset:起到將張量Tensor組成pytorch能夠處理的資料組,因為pytorch能夠處理的資料組都要繼承nn.model()
  • trange:整體類似於range(),但不同之處在於每次epoch時會有一個進度條

2.程式的整體框架

 程式由以下三部分組成:

  • 資料集的構建
  • 模型的構建
  • 模型的使用

3.資料集的建構


 函式datasets.MNIST()起到下載資料集的作用。第一個形式引數是確定下載的資料存放的根檔案,第二個形式引數download作用是判斷是否需要從目標源下載資料,若download=True則代表若程式在目標資料夾沒有找到MNIST資料集則會從目標源上下載資料集,若download=False則不會下載。第三個引數判斷下載的是訓練集還是驗證集。若train=True代表下載的是訓練集,若train=False則代表下載的是訓練集。
 程式碼x_train = train.data.unsqueeze(1)/255.0實現的功能是給資料集增加一個維度。具體來說該步將原本的資料集樣式:樣本數x資料高度x資料寬度轉變為樣本數x資料通道數x資料高度x資料寬度。而/255.0實現的是將資料歸一化的操作。
x_trainy_train格式為torch.tensor
dataset_train = DataLoader(TensorDataset(x_train,y_train),batch_size=256,shuffle=True)該程式碼由兩個函式巢狀而成,第一個為 TensorDataset(x_train,y_train) 該函式的作用為將兩個張量合成一個資料集,直接用TensorDataset()是一種簡單的方法。還有一種方法是構建資料類,繼承於Dataset資料基類。第二個為DataLoader()該函式的作用為將一個大的訓練集拆分成若干小的訓練集,再逐個進行訓練。batch_size=256引數確定了劃分的小樣本集的規模為256個樣本,shuffle=True作用是在樣本選擇時採用隨機取樣的方式。


3.模型的構建


 在pytorch中,建構一個模型,需要建立一個繼承nn.Module類的子類,並且要對子類中的兩個函式__init__()forward()進行重寫。在LeNet_5Model的模型定義中,初始化函式定義了卷積層,池化層和線性層,在前向傳播函式中定義了網路的結構。x.view()方法和numpy中的reshape類似,都是改變資料型別的內部結構。
nn.Conv2d(1,6,5)其中第一個引數是輸入的通道數;第二個引數是輸出通道數;第三個引數是卷積核的規模。


4.模型的使用


首先實現的是模型、最佳化器、損失函式的例項化,最佳化器採用的是Adam(),損失函式採用的是交叉熵函式。
with no_grad():實現關閉模型自動求導功能,不僅降低了模型的運算時間,而且減少了記憶體消耗。
acc_train = (train_preds.argmax(dim=1) == y_train).float().mean().item()

  • train_preds:這是一個張量(Tensor),包含了模型對訓練集樣本的預測結果。假設這是一個分類問題,train_preds的形狀可能是[batch_size, num_classes],其中batch_size是批次大小,num_classes是類別的數量。每個樣本的預測結果是一個長度為num_classes的向量,向量中的每個元素代表該樣本屬於對應類別的機率(儘管這裡可能不是直接的機率值,而是某種形式的得分,如未經過softmax歸一化的logits)。
  • train_preds.argmax(dim=1):這個操作沿著dim=1(即類別的維度)查詢每個樣本預測機率最高的類別的索引。argmax函式會返回每個樣本預測機率最高的類別的索引,因此結果是一個形狀為[batch_size]的張量,包含了每個樣本預測類別的索引。
  • == y_train:這裡將預測類別的索引與真實的標籤y_train進行比較。y_train是一個形狀為[batch_size]的張量,包含了每個樣本的真實類別索引。比較的結果是一個布林張量,其中的每個元素都是True(如果預測正確)或False(如果預測錯誤)。
  • .float():將布林張量轉換為浮點張量,這樣True會被轉換為1.0,False會被轉換為0.0。
  • .mean():計算張量中所有元素的平均值。由於張量中的元素是0.0或1.0,這個平均值實際上就是準確率:正確預測的樣本數除以總樣本數。
  • .item():將得到的平均值(一個標量Tensor)轉換為Python的數值型別(通常是float),以便在Python程式碼中使用。
    綜上所述,acc_train = (train_preds.argmax(dim=1) == y_train).float().mean().item()這行程式碼計算了模型在訓練集上的準確率,並將結果儲存在變數acc_train中。

相關文章