Python?LeNet網(wǎng)絡(luò)詳解及pytorch實現(xiàn)
1.LeNet介紹
LeNet神經(jīng)網(wǎng)絡(luò)由深度學習三巨頭之一的Yan LeCun提出,他同時也是卷積神經(jīng)網(wǎng)絡(luò) (CNN,Convolutional Neural Networks)之父。LeNet主要用來進行手寫字符的識別與分類,并在美國的銀行中投入了使用。LeNet的實現(xiàn)確立了CNN的結(jié)構(gòu),現(xiàn)在神經(jīng)網(wǎng)絡(luò)中的許多內(nèi)容在LeNet的網(wǎng)絡(luò)結(jié)構(gòu)中都能看到,例如卷積層,Pooling層,ReLU層。雖然LeNet早在20世紀90年代就已經(jīng)提出了,但由于當時缺乏大規(guī)模的訓練數(shù)據(jù),計算機硬件的性能也較低,因此LeNet神經(jīng)網(wǎng)絡(luò)在處理復(fù)雜問題時效果并不理想。雖然LeNet網(wǎng)絡(luò)結(jié)構(gòu)比較簡單,但是剛好適合神經(jīng)網(wǎng)絡(luò)的入門學習。
2.LetNet網(wǎng)絡(luò)模型
LeNet網(wǎng)絡(luò)模型一般指LeNet-5,相信大家學習這個模型的時候一定都見過這張圖片吧

這張圖也是原論文中的一張模型圖,這樣子看可能會覺得有點不習慣,下面這張圖是本人在drawio軟件上制作的網(wǎng)絡(luò)模型圖,如下:

糾正一下,上圖中第二個Conv2d層后面的計算結(jié)果應(yīng)該為10,寫成了5
相信學習了卷積神經(jīng)網(wǎng)絡(luò)基礎(chǔ)的朋友們應(yīng)該能很清晰的看懂這張圖吧,對于右邊的計算在圖的左上角也給出了公式,上圖中每一層的輸入形狀以及輸出形狀我都詳細的為大家寫出來了,對于計算公式和模型大致的結(jié)構(gòu),看下面這張圖也可以(建議對應(yīng)上下圖一起看更容易理解)

LeNet-5網(wǎng)絡(luò)模型簡單的就包含了卷積層,最大池化層,全連接層以及relu,softmax激活函數(shù),模型中的輸入圖片大小以及每一層的卷積核個數(shù),步長都是模型制定好的,一般不要隨意修改,能改的是最后的輸出結(jié)果,即分類數(shù)量(num_classes)。flatten操作也叫扁平化操作,我們都知道輸入到全連接層中的是一個個的特征,及一維向量,但是卷積網(wǎng)絡(luò)特征提取出來的特征矩陣并非一維,要送入全連接層,所以需要flatten操作將它展平成一維。
3.pytorch實現(xiàn)LeNet
python代碼如下
from torch import nn
import torch
import torch.nn.functional as F
'''
說明:
1.LeNet是5層網(wǎng)絡(luò)
2.nn.ReLU(inplace=True) 參數(shù)為True是為了從上層網(wǎng)絡(luò)Conv2d中傳遞下來的tensor直接進行修改,這樣能夠節(jié)省運算內(nèi)存,不用多存儲其他變量
3.本模型的維度注釋均省略了N(batch_size)的大小,即input(3, 32, 32)-->input(N, 3, 32, 32)
4.nn.init.xavier_uniform_(m.weight)
用一個均勻分布生成值,填充輸入的張量或變量,結(jié)果張量中的值采樣自U(-a, a),
其中a = gain * sqrt( 2/(fan_in + fan_out))* sqrt(3),
gain是可選的縮放因子,默認為1
'fan_in'保留前向傳播時權(quán)值方差的量級,'fan_out'保留反向傳播時的量級
5.nn.init.constant_(m.bias, 0)
為所有維度tensor填充一個常量0
'''
class LeNet(nn.Module):
def __init__(self, num_classes=10, init_weights=False):
super(LeNet, self).__init__()
self.conv1 = nn.Conv2d(in_channels=3, out_channels=16, kernel_size=5, stride=1)
self.maxpool1 = nn.MaxPool2d(kernel_size=2, stride=2)
self.relu = nn.ReLU(True)
self.conv2 = nn.Conv2d(in_channels=16, out_channels=32, kernel_size=5, stride=1)
self.maxpool2 = nn.MaxPool2d(kernel_size=2, stride=2)
self.fc1 = nn.Linear(32 * 5 * 5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, num_classes)
if init_weights:
self._initialize_weights()
def forward(self, x):
x = self.conv1(x) # input(3, 32, 32) output(16, 28, 28)
x = self.relu(x) # 激活函數(shù)
x = self.maxpool1(x) # output(16, 14, 14)
x = self.conv2(x) # output(32, 10, 10)
x = self.relu(x) # 激活函數(shù)
x = self.maxpool2(x) # output(32, 5, 5)
x = torch.flatten(x, start_dim=1) # output(32*5*5) N代表batch_size
x = self.fc1(x) # output(120)
x = self.relu(x) # 激活函數(shù)
x = self.fc2(x) # output(84)
x = self.relu(x) # 激活函數(shù)
x = self.fc3(x) # output(num_classes)
return x
def _initialize_weights(self):
for m in self.modules():
if isinstance(m, nn.Conv2d):
nn.init.xavier_uniform_(m.weight)
if m.bias is not None:
nn.init.constant_(m.bias, 0)
elif isinstance(m, nn.Linear):
nn.init.xavier_uniform_(m.weight)
nn.init.constant_(m.bias, 0)
或者
下面這一種沒有自己初始化權(quán)重和偏置,就會使用默認的初始化方式
import torch.nn as nn
import torch.nn.functional as F
import torch
class LeNet(nn.Module):
def __init__(self):
super(LeNet, self).__init__()
self.conv1 = nn.Conv2d(3, 16, 5)
self.pool1 = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(16, 32, 5)
self.pool2 = nn.MaxPool2d(2, 2)
self.fc1 = nn.Linear(32*5*5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
x = F.relu(self.conv1(x)) # output(16, 28, 28)
x = self.pool1(x) # output(16, 14, 14)
x = F.relu(self.conv2(x)) # output(32, 10, 10)
x = self.pool2(x) # output(32, 5, 5)
x = x.view(x.size(0), -1) # output(32*5*5)
x = F.relu(self.fc1(x)) # output(120)
x = F.relu(self.fc2(x)) # output(84)
x = self.fc3(x) # output(10)
return x
nn.Linear就是全連接層,除了最后一個全連接層,其它均需要relu激活,默認無padding操作
nn.Conv2d對應(yīng)的參數(shù)順序一定要記住:
1.in_channels:輸入的通道數(shù)或者深度
2.out_channels:輸出的通道數(shù)或者深度
3.kernel_size:卷積核的大小
4.stride:步長大小,默認1
5.padding:padding的大小,默認0
6.dilation:膨脹大小,默認1,暫時用不到
7.group:分組組數(shù),默認1
8.bias:默認True,布爾值,是否用偏置值
9.padding_mode:默認用0填充
記不住參數(shù)順序也沒關(guān)系,但需要記住參數(shù)名稱
參考文章:pytorch實現(xiàn)LeNet網(wǎng)絡(luò)模型的訓練及預(yù)測
以上就是Python LeNet網(wǎng)絡(luò)詳解及pytorch實現(xiàn)的詳細內(nèi)容,更多關(guān)于Python LeNet網(wǎng)絡(luò)實現(xiàn)的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
關(guān)于Python函數(shù)對象的名稱空間和作用域
這篇文章主要介紹了關(guān)于Python函數(shù)對象的名稱空間和作用域,數(shù)據(jù)的名稱是儲存到棧區(qū),而數(shù)據(jù)的內(nèi)容是儲存到堆區(qū),當我們要去使用數(shù)據(jù)的內(nèi)容時,我們可以通過數(shù)據(jù)的名稱來直接去表示數(shù)據(jù)的內(nèi)容,需要的朋友可以參考下2023-04-04
三步解決python PermissionError: [WinError 5]拒絕訪問的情況
這篇文章主要介紹了三步解決python PermissionError: [WinError 5]拒絕訪問的情況,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-04-04
解讀調(diào)用jupyter?notebook文件內(nèi)的函數(shù)一種簡單方法
這篇文章主要介紹了解讀調(diào)用jupyter?notebook文件內(nèi)的函數(shù)一種簡單方法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-01-01
使用Python實現(xiàn)為PDF文檔設(shè)置和移除密碼
在數(shù)字化時代,文檔的安全性變得越來越重要,特別是對于包含敏感信息的PDF文件,所以本文主要來和大家介紹一下如何使用Python實現(xiàn)為PDF文檔設(shè)置和移除密碼,需要的可以參考下2024-03-03
python數(shù)字圖像處理之高級形態(tài)學處理
這篇文章主要介紹了python數(shù)字圖像處理之高級形態(tài)學處理,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-04-04
Python?PaddleNLP開源實現(xiàn)快遞單信息抽取
這篇文章主要為大家介紹了Python?PaddleNLP開源項目實現(xiàn)對快遞單信息抽取,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-06-06

