Python?CNN卷積神經(jīng)網(wǎng)絡(luò)實(shí)戰(zhàn)教程深入講解
一、CNN簡(jiǎn)介
1. 神經(jīng)網(wǎng)絡(luò)基礎(chǔ)
輸入層(Input layer),眾多神經(jīng)元(Neuron)接受大量非線形輸入訊息。輸入的訊息稱為輸入向量。
輸出層(Output layer),訊息在神經(jīng)元鏈接中傳輸、分析、權(quán)衡,形成輸出結(jié)果。輸出的訊息稱為輸出向量。
隱藏層(Hidden layer),簡(jiǎn)稱“隱層”,是輸入層和輸出層之間眾多神經(jīng)元和鏈接組成的各個(gè)層面。如果有多個(gè)隱藏層,則意味著多個(gè)激活函數(shù)。
2. 卷積一下哦
卷積神經(jīng)網(wǎng)絡(luò)(Convolutional Neural Network,CNN)針對(duì)全連接網(wǎng)絡(luò)的局限做出了修正,加入了卷積層(Convolution層)和池化層(Pooling層)。通常情況下,卷積神經(jīng)網(wǎng)絡(luò)由若干個(gè)卷積層(Convolutional Layer)、激活層(Activation Layer)、池化層(Pooling Layer)及全連接層(Fully Connected Layer)組成。
下面看怎么卷積的
1.如圖,可以看到:
(1)兩個(gè)神經(jīng)元,即depth=2,意味著有兩個(gè)濾波器。
(2)數(shù)據(jù)窗口每次移動(dòng)兩個(gè)步長(zhǎng)取3*3的局部數(shù)據(jù),即stride=2。
(3)邊緣填充,zero-padding=1,主要為了防止遺漏邊緣的像素信息。
然后分別以兩個(gè)濾波器filter為軸滑動(dòng)數(shù)組進(jìn)行卷積計(jì)算,得到兩組不同的結(jié)果。
2.如果初看上圖,可能不一定能立馬理解啥意思,但結(jié)合上文的內(nèi)容后,理解這個(gè)動(dòng)圖已經(jīng)不是很困難的事情:
(1)左邊是輸入(7*7*3中,7*7代表圖像的像素/長(zhǎng)寬,3代表R、G、B 三個(gè)顏色通道)
(2)中間部分是兩個(gè)不同的濾波器Filter w0、Filter w1
(3)最右邊則是兩個(gè)不同的輸出
(4)隨著左邊數(shù)據(jù)窗口的平移滑動(dòng),濾波器Filter w0 / Filter w1對(duì)不同的局部數(shù)據(jù)進(jìn)行卷積計(jì)算。
局部感知:左邊數(shù)據(jù)在變化,每次濾波器都是針對(duì)某一局部的數(shù)據(jù)窗口進(jìn)行卷積,這就是所謂的CNN中的局部感知機(jī)制。打個(gè)比方,濾波器就像一雙眼睛,人類視角有限,一眼望去,只能看到這世界的局部。如果一眼就看到全世界,你會(huì)累死,而且一下子接受全世界所有信息,你大腦接收不過(guò)來(lái)。當(dāng)然,即便是看局部,針對(duì)局部里的信息人類雙眼也是有偏重、偏好的。比如看美女,對(duì)臉、胸、腿是重點(diǎn)關(guān)注,所以這3個(gè)輸入的權(quán)重相對(duì)較大。
參數(shù)共享:數(shù)據(jù)窗口滑動(dòng),導(dǎo)致輸入在變化,但中間濾波器Filter w0的權(quán)重(即每個(gè)神經(jīng)元連接數(shù)據(jù)窗口的權(quán)重)是固定不變的,這個(gè)權(quán)重不變即所謂的CNN中的參數(shù)(權(quán)重)共享機(jī)制。
3. 卷積計(jì)算
圖中最左邊的三個(gè)輸入矩陣就是我們的相當(dāng)于輸入d=3時(shí)有三個(gè)通道圖,每個(gè)通道圖都有一個(gè)屬于自己通道的卷積核,我們可以看到輸出(output)的只有兩個(gè)特征圖意味著我們?cè)O(shè)置的輸出的d=2,有幾個(gè)輸出通道就有幾層卷積核(比如圖中就有FilterW0和FilterW1),這意味著我們的卷積核數(shù)量就是輸入d的個(gè)數(shù)乘以輸出d的個(gè)數(shù)(圖中就是2*3=6個(gè)),其中每一層通道圖的計(jì)算與上文中提到的一層計(jì)算相同,再把每一個(gè)通道輸出的輸出再加起來(lái)就是綠色的輸出數(shù)字啦!
舉例:
綠色輸出的第一個(gè)特征圖的第一個(gè)值:
1通道x[ : :0] 1*1+1*0 = 1 (0像素點(diǎn)省略)
2通道x[ : :1] 1*0+1*(-1)+2*0 = -1
3通道x[ : :2] 2*0 = 0
b = 1
輸出:1+(-1)+ 0 + 1(這個(gè)是b)= 1
綠色輸出的第二個(gè)特征圖的第一個(gè)值:
1通道x[ : :0] 1*0+1*0 = 0 (0像素點(diǎn)省略)
2通道x[ : :1] 1*0+1*(-1)+2*0 = -1
3通道x[ : :2] 2*0 = 0
b = 0
輸出:0+(-1)+ 0 + 1(這個(gè)是b)= 0
二、CNN實(shí)例代碼
import torch import torch.nn as nn from torch.autograd import Variable import torch.utils.data as Data import torchvision import matplotlib.pyplot as plt
模型訓(xùn)練超參數(shù)設(shè)置,構(gòu)建訓(xùn)練數(shù)據(jù):如果你沒(méi)有源數(shù)據(jù),那么DOWNLOAD_MNIST=True
#Hyper prameters EPOCH = 2 BATCH_SIZE = 50 LR = 0.001 DOWNLOAD_MNIST = True train_data = torchvision.datasets.MNIST( root ='./mnist', train = True, download = DOWNLOAD_MNIST )
數(shù)據(jù)下載后是不可以直接看的,查看第一張圖片數(shù)據(jù):
print(train_data.data.size()) print(train_data.targets.size()) print(train_data.data[0])
結(jié)果:60000張圖片數(shù)據(jù),維度都是28*28,單通道
畫(huà)一個(gè)圖片顯示出來(lái)
# 畫(huà)一個(gè)圖片顯示出來(lái) plt.imshow(train_data.data[0].numpy(),cmap='gray') plt.title('%i'%train_data.targets[0]) plt.show()
結(jié)果:
訓(xùn)練和測(cè)試數(shù)據(jù)準(zhǔn)備,數(shù)據(jù)導(dǎo)入:
#訓(xùn)練和測(cè)試數(shù)據(jù)準(zhǔn)備 train_loader=Data.DataLoader(dataset=train_data, batch_size=BATCH_SIZE, shuffle=True) test_data=torchvision.datasets.MNIST( root='./mnist', train=False, ) #這里只取前3千個(gè)數(shù)據(jù)吧,差不多已經(jīng)夠用了,然后將其歸一化。 with torch.no_grad(): test_x=Variable(torch.unsqueeze(test_data.data, dim=1)).type(torch.FloatTensor)[:3000]/255 test_y=test_data.targets[:3000]
注意:這里的歸一化在此模型中區(qū)別不大
構(gòu)建CNN模型:
'''開(kāi)始建立CNN網(wǎng)絡(luò)''' class CNN(nn.Module): def __init__(self): super(CNN,self).__init__() ''' 一般來(lái)說(shuō),卷積網(wǎng)絡(luò)包括以下內(nèi)容: 1.卷積層 2.神經(jīng)網(wǎng)絡(luò) 3.池化層 ''' self.conv1=nn.Sequential( nn.Conv2d( #--> (1,28,28) in_channels=1, #傳入的圖片是幾層的,灰色為1層,RGB為三層 out_channels=16, #輸出的圖片是幾層 kernel_size=5, #代表掃描的區(qū)域點(diǎn)為5*5 stride=1, #就是每隔多少步跳一下 padding=2, #邊框補(bǔ)全,其計(jì)算公式=(kernel_size-1)/2=(5-1)/2=2 ), # 2d代表二維卷積 --> (16,28,28) nn.ReLU(), #非線性激活層 nn.MaxPool2d(kernel_size=2), #設(shè)定這里的掃描區(qū)域?yàn)?*2,且取出該2*2中的最大值 --> (16,14,14) ) self.conv2=nn.Sequential( nn.Conv2d( # --> (16,14,14) in_channels=16, #這里的輸入是上層的輸出為16層 out_channels=32, #在這里我們需要將其輸出為32層 kernel_size=5, #代表掃描的區(qū)域點(diǎn)為5*5 stride=1, #就是每隔多少步跳一下 padding=2, #邊框補(bǔ)全,其計(jì)算公式=(kernel_size-1)/2=(5-1)/2= ), # --> (32,14,14) nn.ReLU(), nn.MaxPool2d(kernel_size=2), #設(shè)定這里的掃描區(qū)域?yàn)?*2,且取出該2*2中的最大值 --> (32,7,7),這里是三維數(shù)據(jù) ) self.out=nn.Linear(32*7*7,10) #注意一下這里的數(shù)據(jù)是二維的數(shù)據(jù) def forward(self,x): x=self.conv1(x) x=self.conv2(x) #(batch,32,7,7) #然后接下來(lái)進(jìn)行一下擴(kuò)展展平的操作,將三維數(shù)據(jù)轉(zhuǎn)為二維的數(shù)據(jù) x=x.view(x.size(0),-1) #(batch ,32 * 7 * 7) output=self.out(x) return output
把模型實(shí)例化打印一下:
cnn=CNN() print(cnn)
結(jié)果:
開(kāi)始訓(xùn)練:
# 添加優(yōu)化方法 optimizer=torch.optim.Adam(cnn.parameters(),lr=LR) # 指定損失函數(shù)使用交叉信息熵 loss_fn=nn.CrossEntropyLoss() ''' 開(kāi)始訓(xùn)練我們的模型哦 ''' step=0 for epoch in range(EPOCH): #加載訓(xùn)練數(shù)據(jù) for step,data in enumerate(train_loader): x,y=data #分別得到訓(xùn)練數(shù)據(jù)的x和y的取值 b_x=Variable(x) b_y=Variable(y) output=cnn(b_x) #調(diào)用模型預(yù)測(cè) loss=loss_fn(output,b_y)#計(jì)算損失值 optimizer.zero_grad() #每一次循環(huán)之前,將梯度清零 loss.backward() #反向傳播 optimizer.step() #梯度下降 #每執(zhí)行50次,輸出一下當(dāng)前epoch、loss、accuracy if (step%50==0): #計(jì)算一下模型預(yù)測(cè)正確率 test_output=cnn(test_x) y_pred=torch.max(test_output,1)[1].data.squeeze() accuracy=sum(y_pred==test_y).item()/test_y.size(0) print('now epoch : ', epoch, ' | loss : %.4f ' % loss.item(), ' | accuracy : ' , accuracy) ''' 打印十個(gè)測(cè)試集的結(jié)果 ''' test_output=cnn(test_x[:10]) y_pred=torch.max(test_output,1)[1].data.squeeze() #選取最大可能的數(shù)值所在的位置 print(y_pred.tolist(),'predecton Result') print(test_y[:10].tolist(),'Real Result')
結(jié)果:
卷積層維度變化:
(1)輸入1*28*28,即1通道,28*28維;
(2)卷積層-01:16*28*28,即16個(gè)卷積核,卷積核維度5*5,步長(zhǎng)1,邊緣填充2,維度計(jì)算公式B = (A + 2*P - K) / S + 1,即(28+2*2-5)/1 +1 = 28
(3)池化層:池化層為2*2,所以輸出為16*14*14
(4)卷積層-02:32*14*14,即32卷積核,其它同卷積層-01
(5)池化層:池化層為2*2,所以輸出為32*7*7;
(6)fc層:由于輸出為1*10,即10個(gè)類別的概率,那么首先對(duì)最后的池化層進(jìn)行壓縮為二維(1,32*7*7),然后全連接層維度(32*7*7,10),最后(1,32*7*7)*(32*7*7,10)
到此這篇關(guān)于Python CNN卷積神經(jīng)網(wǎng)絡(luò)實(shí)戰(zhàn)教程深入講解的文章就介紹到這了,更多相關(guān)Python CNN內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Python實(shí)現(xiàn)用networkx繪制MultiDiGraph
- Python使用Networkx實(shí)現(xiàn)復(fù)雜的人物關(guān)系圖
- Python中的Networkx的基本使用
- Python中卷積神經(jīng)網(wǎng)絡(luò)(CNN)入門(mén)教程分分享
- python機(jī)器學(xué)習(xí)GCN圖卷積神經(jīng)網(wǎng)絡(luò)原理解析
- python人工智能tensorflow構(gòu)建卷積神經(jīng)網(wǎng)絡(luò)CNN
- Python卷積神經(jīng)網(wǎng)絡(luò)圖片分類框架詳解分析
- python如何實(shí)現(xiàn)convolution neural network卷積神經(jīng)網(wǎng)絡(luò)算法
相關(guān)文章
python實(shí)現(xiàn)淘寶購(gòu)物系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)簡(jiǎn)易的淘寶購(gòu)物系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-10-10OpenCV之理解KNN鄰近算法k-Nearest?Neighbour
這篇文章主要為大家介紹了OpenCV之理解KNN鄰近算法k-Nearest?Neighbour,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05Python之Numpy的超實(shí)用基礎(chǔ)詳細(xì)教程
這篇文章主要介紹了Python之Numpy的超實(shí)用基礎(chǔ)詳細(xì)教程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10python調(diào)用webservice接口的實(shí)現(xiàn)
這篇文章主要介紹了python調(diào)用webservice接口的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07python中pd.cut()與pd.qcut()的對(duì)比及示例
本文主要介紹了python中pd.cut()與pd.qcut()的對(duì)比及示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06Python用來(lái)做Web開(kāi)發(fā)的優(yōu)勢(shì)有哪些
這篇文章主要介紹了Python用來(lái)做Web開(kāi)發(fā)的優(yōu)勢(shì)有哪些,文中講解非常細(xì)致,幫助大家更好的理解和學(xué)習(xí)Python,感興趣的朋友可以了解下2020-08-08