import torch
from torch import nn#定義張量x,它的尺寸是5x1x28x28
#表示了5個單通道28x28大小的數據
x=torch.zeros([5,1,28,28])#定義一個輸入通道是1,輸出通道是6,卷積核大小是5x5的卷積層
conv=nn.Conv2d(in_channels=1,out_channels=6,kernel_size=5)#將x,輸入至conv,計算出結果
c=conv(x)
#經過conv計算,得到5x6x24x24大小的輸出張量,經過卷積層的處理后得到6x24x24大小的特征圖print(c.shape)#程序輸出:torch.Size([5,6,24,24])#繼續輸入至池化層,計算后會得到6x12x12大小的特征圖
pool=nn.MaxPool2d(2)#定義最大池化層
s=pool(c) 將卷積層計算得到的整整圖c,輸入至pool#接下來繼續到第2個卷積層,計算出16個8x8的輸出特征圖
#再輸入到第2個池化層,計算得到16個4x4大小的特征圖
#池化層輸出后,將特征圖進行展平:16個4x4 -> 1x256的向量
#展平flatten:將每個圖片中的每個像素放成一排,就是256維度的一維向量
#后面是全連接層 最后3個全連接層的大小為,256×120、120×84、84×10。
#經過這三個全連接層后:會計算出1×120、1×84、1×10的向量。1×10的向量,就對應了最終的10個分類結果。
LeNet5網絡實現:
import torch
from torch.nn import Module
from torch import nnclass LeNet5(Module):def _init_(self):#說明了這個網絡中有什么,定義網絡結構super(LeNet5, self)._init_()#第1個卷積塊self.convl = nn.Sequential(nn.Conv2d(1,6,5),nn.ReLU(),nn.MaxPool2d(2))#第2個卷積塊self.conv2= nn.Sequential(nn.Conv2d(6, 16, 5),nn.ReLU(),nn.MaxPool2d(2))#全連接層1self.fcl = nn.Sequential(nn.Linear(256,120),#線性層nn.ReLU())#全連接層2self.fc2 = nn.Sequential(nn.Linear(120,84),nn.ReLU())#全連接層3self.fc3= nn.Linear(84,10) def forward(self,x):#輸入張量x 進入到神經網絡后,它尺寸會如何變化。#說明了,這個網絡“如何算”!#最初輸入的x是nx1x28x28大小的,其中n是數據數量x = self.convl(x)# [n, 6, 12,12]x = self.conv2(x)# [n, 16, 4, 4]#在x輸入至全連接層前#需要使用view函數,將張量的維度從n×16x4x4展平為nx256x= x.view(-1,256)# [n,256]x = self.fcl(x)# [n,120]X = self.fc2(x)# [n,84]x = self.fc3(x)# [n,10]return x"""在函數中,輸入張量x會按照順序,進入conv1、conv2、fc1、fc2、fc3,進行計算。在旁邊注釋中,標記了張量x,經過每一層計算后,變化的尺寸。例如,最初輸入的x是n×1×28×28大小的。這里n表示了數據的數量。因此,x經過conv1,就會計算得到n×6×12×12大小的張量。接著,x經過conv2,會計算出n×16×4×4的張量。備注:這里的conv1和conv2中,包含了池化層,所以特征圖尺寸會減半。然后,在x輸入至全連接層前,需要使用view函數:將張量的維度從n×16×4×4展平為n×256。接著再按照順序,將x輸入至全連接層fc1、fc2、fc3計算。最終函數返回一個n×10大小的結果。"""
訓練:
for epoch in range(10):#外層循環,代表了整個訓練數據集的遍歷次數#內層循環使用train_loader,進行小批量的數據讀取for batch_idx, (data, label) in enumerate(train_loader):#每次內層循環,都會進行一次梯度下降算法#梯度下降算法,包括了5個步驟:output=model(data)#1.計算神經網絡的前向傳播結果loss=criterion(output,label)#2.計算output和標簽label之間的損失lossloss.backward() #3.使用backward計算梯度#每次內層循環,都會進行一次梯度下降算法。optimizer.step()#4.使用optimizer.step更新參數optimizer.zero_grad() # 5.將梯度清零#每迭代100個小批量,就打印一次模型的損失,觀察訓練的過程if batch_idx100 =0:print(f"Epoch (epoch + 1)/10 "f"| Batch (batch_idx)/(len(train_loader)}"f"i Loss: (loss.item():.4f)")
torch.save(model.state_dict(),'mnist_lenet5.pth')