日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

DeepLearning:CNN网络学习之LetNet-5解读(论文+分析+代码)

發布時間:2025/3/20 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 DeepLearning:CNN网络学习之LetNet-5解读(论文+分析+代码) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

LetNet-5

  • 【寫在前面】
    • 權值共享
    • 卷積原理
    • 池化原理
  • 【LetNet介紹】
    • 論文原文
    • 實現過程參數變化概覽
    • 詳細過程
  • 【代碼實現】
  • 【參考鏈接】

【寫在前面】

LetNet-5雖然簡單,但是包含了深度學習CNN模型的基本組成模塊,包含(卷積、池化、全連接等結構)為了幫助理解拿了一個最簡單的LetNet網絡做一個知識梳理幫助理解。
(閱讀本文章之前具體的卷積、池化原理大家已經深入理解)

權值共享

圖像識別的領域同時網絡的類型是基于BP的,因此針對這個領域先看看BP的缺點,我們知道BP網絡是全連接的,對于圖片的識別,我們不用提取特征,一般一層提取特征的效果并不是很好,因此我們需要很多層,如果按照BP進行全連接,會使得權值數量急劇增加,想要訓練這么多的權值,樣本必須足夠的才行,即使樣本數量夠,但是計算量也會急劇增加,而且還有面臨梯度消失的情況,因此需要改進連接的方式即采用局部連接和權值共享,如下圖:

假如一張圖片的像素點為4x4的,上圖的左邊圖W為全連接,一個神經元就有16個連接 ,每個連接的權值不同,因此如果有n個神經元則有16n個權值,左圖就是局部連接,此時加入四個像素點連接一個神經元,則需要四個,但是如果像素很多的情況下,權值還是很多,此時是按照每個神經元的連接權值如上圖的是其中一個神經元的是4個權值,所謂權值共享,就是其他神經元的權值也使用這四個值,此時的位置和數值都是這樣對應的,這里大家需要理解。即四個神經元只有四個不同的權值,現在我們來算算,按照右邊的計算:

全連接的權值數:4x4x4=64(前面兩是像素點,后面的4是神經元,這里先不考慮偏置值) ,
局部連接的權值:4x4=16(4個神經元,每個神經元4個權值)
局部連接和權值共享: 4

因此權值的數量就降低了,這就是通過局部連接和權值共享來解決BP的存在的問題,這里的理論依據就是根據上面說的感受野進行簡化的,但是按照上圖的局部連接存在一個問題就是邊緣過度不平滑,會出現邊緣效應,為了解決這個問題引入了采樣窗口法使其彼此重疊,因為這樣做和卷積很類似,因此采樣窗口就稱為卷積核了,我們看這個窗口是怎么重疊的;假如采樣窗口為3x3,所謂重疊,我們每次左移一個像素點送給神經元,往下移動時也是這樣的,這樣就避免了邊緣效應了具體效果如下圖所示;

卷積原理

簡要圖示:

池化原理

簡要圖示:

【LetNet介紹】


LetNet實現過程如上圖所示:
含輸入層總共8層網絡,分別為:
輸入層(INPUT)、
卷積層(Convolutions,C1)、
池化層(Subsampling,S2)、
卷積層(C3)、
池化層(Subsampling,S4)、
卷積層(C5)、
全連接層(F6)、
輸出層(徑向基層)

論文原文

論文原文:
輸入的二維圖像,先經過兩次卷積層到池化層,再經過全連接層,最后使用softmax分類作為輸出層。大致過程如下圖所示:

實現過程參數變化概覽

分為以下幾步:
1.INPUT層-輸入層:(輸入32x32大小的圖像)
2.C1層-卷積層
3.S2層-池化層(下采樣層)
4.C3層-卷積層
5.S4層-池化層(下采樣層)
6.C5層-卷積層
7.F6層-全連接層
8.Output層-全連接層
整個過程對應參數理解如下表所示:

各層之間的數據變化關系參考我的另外一個文章:https://blog.csdn.net/weixin_44322778/article/details/122563229

詳細過程

1.INPUT層-輸入層:(輸入32x32大小的圖像)
數據輸入 INPUT 輸入圖像的尺寸歸一化為32*32

2.C1層-卷積層
輸入圖片:3232
卷積核大小:55
卷積核種類:6
輸出featuremap大小:2828 (32-5+1)=28
神經元數量:28286
可訓練參數:(55+1) * 6(每個濾波器55=25個unit參數和一個bias參數,一共6個濾波器)
連接數:(55+1)628*28=122304

詳細說明:對輸入圖像進行第一次卷積運算(使用 6 個大小為 55 的卷積核),得到6個C1特征圖(6個大小為2828的 feature maps, 32-5+1=28)。我們再來看看需要多少個參數,卷積核的大小為55,總共就有6(55+1)=156個參數,其中+1是表示一個核有一個bias。對于卷積層C1,C1內的每個像素都與輸入圖像中的55個像素和1個bias有連接,所以總共有1562828=122304個連接(connection)。有122304個連接,但是我們只需要學習156個參數,主要是通過權值共享實現的。

上圖表示CNN中卷積操作。對卷積的要點解釋:
(1)紅色框內為22卷積核。
(2)藍色框內為34的輸入圖像。
(3)綠色框為3*3的特征圖。
注意:綠框中未包含偏置項。如加入偏置項則每個輸出多加上同一個偏置B,此時類似如:aw+bx+ey+fz+B bw+cx+fy+gz+B等。所謂的權值共享是每個卷積運算使用同一個卷積核,在上圖中使用的是同一個卷積核,即共享權值。

卷積的優勢:
(1) sparse interactions (2) parameter sharing (3) equivariant respections
sparse interactions:
下圖是效果圖。藍色框中是全連接神經網絡,紅色框是卷積網絡。

卷積相對于全連接是稀疏的。
優勢:1、參數更少 2、計算量降低。那么會不會導致提取的特征丟失了?

上圖是多層結構的聯系圖,所以可以通過增加網絡層數,保留全局的特征。
parameter sharing: 在上面已經分析完畢。優勢:同樣是減少了參數量。
equivariant respections: 當輸入圖像通過平移后,卷積的結果也會平移。
原文鏈接:https://blog.csdn.net/zhangjunhit/article/details/53536915

3.S2層-池化層(下采樣層)
輸入:2828
采樣區域:22
采樣方式:4個輸入相加,乘以一個可訓練參數,再加上一個可訓練偏置。結果通過sigmoid
采樣種類:6
輸出featureMap大小:1414(28/2)
神經元數量:14146
連接數:(22+1)614*14
S2中每個特征圖的大小是C1中特征圖大小的1/4。

詳細說明:第一次卷積之后緊接著就是池化運算,使用 22核 進行池化,于是得到了S2,6個1414的 特征圖(28/2=14)。S2這個pooling層是對C1中的2*2區域內的像素求和乘以一個權值系數再加上一個偏置,然后將這個結果再做一次映射。同時有5x14x14x6=5880個連接。

4.C3層-卷積層
輸入:S2中所有6個或者幾個特征map組合
卷積核大小:55
卷積核種類:16
輸出featureMap大小:1010 (14-5+1)=10
C3中的每個特征map是連接到S2中的所有6個或者幾個特征map的,表示本層的特征map是上一層提取到的特征map的不同組合
存在的一個方式是:C3的前6個特征圖以S2中3個相鄰的特征圖子集為輸入。接下來6個特征圖以S2中4個相鄰特征圖子集為輸入。然后的3個以不相鄰的4個特征圖子集為輸入。最后一個將S2中所有特征圖為輸入。
則:可訓練參數:6*(355+1)+6*(455+1)+3*(455+1)+1*(655+1)=1516
連接數:10101516=151600

詳細說明:第一次池化之后是第二次卷積,第二次卷積的輸出是C3,16個10x10的特征圖,卷積核大小是 55. 我們知道S2 有6個 1414 的特征圖,怎么從6 個特征圖得到 16個特征圖了? 這里是通過對S2 的特征圖特殊組合計算得到的16個特征圖。具體如下:

C3的前6個feature map(對應上圖第一個紅框的6列)與S2層相連的3個feature map相連接(上圖第一個紅框)
后面6個feature map與S2層相連的4個feature map相連接(上圖第二個紅框),
后面3個feature map與S2層部分不相連的4個feature map相連接,
最后一個與S2層的所有feature map相連。
卷積核大小依然為55,所以總共有6(355+1)+6*(455+1)+3*(455+1)+1*(655+1)=1516個參數。而圖像大小為1010,所以共有151600個連接。

C3與S2中前3個圖相連的卷積結構如下圖所示:

上圖對應的參數為 355+1,一共進行6次卷積得到6個特征圖,所以有6(355+1)參數。 為什么采用上述這樣的組合了?論文中說有兩個原因:1)減少參數,2)這種不對稱的組合連接的方式有利于提取多種組合特征。

5.S4層-池化層(下采樣層)
輸入:1010
采樣區域:22
采樣方式:4個輸入相加,乘以一個可訓練參數,再加上一個可訓練偏置。結果通過sigmoid
采樣種類:16
輸出featureMap大小:55(10/2)
神經元數量:5516=400
連接數:16(22+1)55=2000
S4中每個特征圖的大小是C3中特征圖大小的1/4
詳細說明:S4是pooling層,窗口大小仍然是22,共計16個feature map,C3層的16個10x10的圖分別進行以2x2為單位的池化得到16個5x5的特征圖。有5x5x5x16=2000個連接。連接的方式與S2層類似。

6.C5層-卷積層
輸入:S4層的全部16個單元特征map(與s4全相連)
卷積核大小:55
卷積核種類:120
輸出featureMap大小:11(5-5+1)
可訓練參數/連接:120*(1655+1)=48120
詳細說明:這一層還是卷積層,且這一層的特征平面有120個,每個特征平面是5x5的,而上一層的池化層S2只有16個平面且每個平面為5x5,本層使用的卷積核為5x5,因此和池化層正好匹配,那么怎么連接呢?很簡單就是這里每個特征平面連接池化層的所有的采樣層。這里稱呼特征平面已經不合適了,因為每個卷積核只對應一個神經元了,因此本層只有120個神經元并列排列,每個神經元連接池化層的所有層。C5層的每個神經元的連接數為5x5x16+1,因此總共的連接數為:(5x5x16+1)x120=48120,而這一層的權值和連接數一樣,因此也有48120個待訓練權值。
C5層的網絡結構如下:

7.F6層-全連接層
輸入:c5 120維向量
計算方式:計算輸入向量和權重向量之間的點積,再加上一個偏置,結果通過sigmoid函數輸出。
可訓練參數:84*(120+1)=10164
詳細說明:6層是全連接層。F6層有84個節點,對應于一個7x12的比特圖,-1表示白色,1表示黑色,這樣每個符號的比特圖的黑白色就對應于一個編碼。該層的訓練參數和連接數是(120 + 1)x84=10164。ASCII編碼圖如下:

F6層的連接方式如下:

8.Output層-全連接層
Output層也是全連接層,共有10個節點,分別代表數字0到9,且如果節點i的值為0,則網絡識別的結果是數字i。采用的是徑向基函數(RBF)的網絡連接方式。
本層的輸出有激活函數,激活函數為雙曲正切函數:

根據論文解釋:A的幅值,S是原點處的傾斜率,A的經驗值是1.7159,原因沒說。
下面我們看看他是和F6層是如何連接的,他不在是BP的神經輸出層,而是基于徑向基神經網絡的輸出層,這里使用的是更簡單的歐幾里得徑向基函數,如下:
假設x是上一層的輸入,y是RBF的輸出,則RBF輸出的計算方式是:

上式w_ij 的值由i的比特圖編碼確定,i從0到9,j取值從0到7*12-1。
公式含義:

徑向基神經網絡,他基于距離進行衡量兩個數據的相近程度的,RBF網最顯著的特點是隱節點采用輸人模式與中心向量的距離(如歐氏距離)作為函數的自變量,并使用徑向基函數(如函數)作為激活函數。徑向基函數關于N維空間的一個中心點具有徑向對稱性,而且神經元的輸人離該中心點越遠,神經元的激活程度就越低。
上式是基于歐幾里得距離,就是說F6層為84個輸入用表示,而輸出有10個用表示,而權值使用,上式說明所有輸入和權值的距離平方和為依據判斷,如果越相近距離越小,輸出越小則去哪個,如果我們存儲的到的值為標準的輸出,如標準的手寫體0,1,2,3等,那么最后一層就說明。F6層和標準的作比較,和標準的那個圖形越相似就說明就越是那個字符的可能性更大。
RBF輸出的值越接近于0,則越接近于i,即越接近于i的ASCII編碼圖,表示當前網絡輸入的識別結果是字符i。該層有84x10=840個參數和連接。
這里標準的每個字符都是像素都是12x7=84.這就是解釋了為什么F6層的神經元為84個,因為他要把所有像素點和標準的比較在進行判斷,因此從這里也可以看出,這里不僅僅可以訓練手寫體數字,也可以識別其他字符,取決于和網絡的設計,這些可以認為修改的。例如我們讓他識別可打印的ASCII碼,把小圖片添加到這里就可以了,同時增加輸出的神經元個數就可以完成了。再給出另外一個詳細的圖:

LeNet-5識別數字3的過程如下圖所示:

【代碼實現】

# -*- coding: UTF-8 -*- # 本代碼訓練的是28*28的數據集,對模型做了一些調整,大家按自己的需要進行取舍 # mnist神經網絡訓練,采用LeNet-5模型import os import cv2 import numpy as npfrom keras.datasets import mnist from keras.models import Sequential from keras.layers import Conv2D, MaxPooling2D, Flatten from keras.layers.core import Dense, Dropout, Activation, Flatten from keras.layers.advanced_activations import PReLU from keras.optimizers import SGD, Adadelta, Adagradfrom keras.utils import np_utils from keras.utils.vis_utils import plot_modelimport h5py from keras.models import model_from_jsondef loadData(path, number):data = np.empty((number, 1, 28, 28), dtype="float32") # empty與ones差不多原理,但是數值隨機,類型隨后面設定labels = np.empty((number,), dtype="uint8")listImg = os.listdir(path)count = 0for img in listImg:imgData = cv2.imread(path + '/' + img, 0) # 數據l = int(img.split('-')[0]) # 答案arr = np.asarray(imgData, dtype="float32") # 將img數據轉化為數組形式data[count, :, :, :] = arr # 將每個三維數組賦給datalabels[count] = l # 取該圖像的數值屬性作為標簽count = count + 1print(path, " loaded ", count)if count >= number:breakreturn data, labelsprint("step0:dataset preloading") # 從圖片文件加載數據 # the data, shuffled and split between train and test sets (trainData, trainLabels), (testData, testLabels) = mnist.load_data()# 訓練數據 60000張手寫圖片,28*28*1 # 測試數據 10000張手寫圖片,28*28*1trainData = trainData.reshape(60000, 784) testData = testData.reshape(10000, 784) print("step1:dataset classification") trainLabels = np_utils.to_categorical(trainLabels, 10) # label為0~9共10個類別,keras要求格式為binary class matrices,轉化一下,直接調用keras提供的這個函數 testLabels = np_utils.to_categorical(testLabels, 10)# tf或th為后端,采取不同參數順序 # th # if K.image_data_format() == 'channels_first': # -x_train.shape[0]=6000 # x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols) # -x_train.shape:(60000, 1, 28, 28) # x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols) # x_test.shape:(10000, 1, 28, 28) # 單通道灰度圖像,channel=1 # input_shape = (1, img_rows, img_cols) # else: #tf # x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1) # x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1) # input_shape = (img_rows, img_cols, 1) print("step2:build the model") # tensorflow后端 trainData = trainData.reshape(trainData.shape[0], 28, 28, 1) testData = testData.reshape(testData.shape[0], 28, 28, 1)# 建立一個Sequential模型 model = Sequential()# model.add(Conv2D(4, 5, 5, border_mode='valid',input_shape=(28,28,1))) # 第一個卷積層,4個卷積核,每個卷積核5*5,卷積后24*24,第一個卷積核要申明input_shape(通道,大小) ,激活函數采用“tanh” model.add(Conv2D(filters=4, kernel_size=(5, 5), padding='valid', input_shape=(28, 28, 1), activation='tanh'))# model.add(Conv2D(8, 3, 3, subsample=(2,2), border_mode='valid')) # 第二個卷積層,8個卷積核,不需要申明上一個卷積留下來的特征map,會自動識別,下采樣層為2*2,卷完且采樣后是11*11 model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Conv2D(filters=8, kernel_size=(3, 3), padding='valid', activation='tanh')) # model.add(Activation('tanh'))# model.add(Conv2D(16, 3, 3, subsample=(2,2), border_mode='valid')) # 第三個卷積層,16個卷積核,下采樣層為2*2,卷完采樣后是4*4 model.add(Conv2D(filters=16, kernel_size=(3, 3), padding='valid', activation='tanh')) model.add(MaxPooling2D(pool_size=(2, 2))) # model.add(Activation('tanh'))model.add(Flatten()) # 把多維的模型壓平為一維的,用在卷積層到全連接層的過度# model.add(Dense(128, input_dim=(16*4*4), init='normal')) # 全連接層,首層的需要指定輸入維度16*4*4,128是輸出維度,默認放第一位 model.add(Dense(128, activation='tanh'))# model.add(Activation('tanh'))# model.add(Dense(10, input_dim= 128, init='normal')) # 第二層全連接層,其實不需要指定輸入維度,輸出為10維,因為是10類 model.add(Dense(10, activation='softmax')) # model.add(Activation('softmax')) # 激活函數“softmax”,用于分類# 訓練CNN模型 print("step3:start train mode") sgd = SGD(lr=0.05, momentum=0.9, decay=1e-6, nesterov=True) # 采用隨機梯度下降法,學習率初始值0.05,動量參數為0.9,學習率衰減值為1e-6,確定使用Nesterov動量 model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy']) # 配置模型學習過程,目標函數為categorical_crossentropy:亦稱作多類的對數損失,注意使用該目標函數時,需要將標簽轉化為形如(nb_samples, nb_classes)的二值序列,第18行已轉化,優化器為sgdprint("step4:Model training method ") model.fit(trainData, trainLabels, batch_size=100, epochs=20, shuffle=True, verbose=1, validation_split=0.2) # 訓練模型,訓練nb_epoch次,bctch_size為梯度下降時每個batch包含的樣本數,驗證集比例0.2,verbose為顯示日志,shuffle是否打亂輸入樣本的順序# 輸出模型圖片 print("step5:model data layer change display") plot_model(model, to_file='model2.png', show_shapes=True, show_layer_names=False)print(model.metrics_names) # 對測試數據進行測試 print("step6:data test") print(model.evaluate(testData, testLabels,verbose=0,batch_size=500)) print("step7:model save") # 保存model json_string = model.to_json() open('my_model_architecture.json', 'w').write(json_string) model.save_weights('my_model_weights.h5')

各層之間數據展示如下圖所示:

各層之間的數據可視化展示使用的是Pydot,有關pydot的使用參考我的另外一個文章:https://blog.csdn.net/weixin_44322778/article/details/122563229

【參考鏈接】

網絡解析(一):LeNet-5詳解
LeNet-5
深度學習 — 卷積神經網絡CNN(LeNet-5網絡詳解)
論文筆記

總結

以上是生活随笔為你收集整理的DeepLearning:CNN网络学习之LetNet-5解读(论文+分析+代码)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。