基于卷积神经网络(cnn)的手写数字识别(PyTorch)
目錄
1.1 卷積神經網絡簡介
1.2 神經網絡
1.2.1?神經元模型
?1.2.2 神經網絡模型
1.3 卷積神經網絡
1.3.1卷積的概念
1.3.2 卷積的計算過程
1.3.3?感受野
1.3.4?步長
1.3.5?輸出特征尺寸計算
?1.3.6?全零填充
1.3.7 標準化
1.3.7?池化層
?1.4 卷積神經網絡的全過程
?1.5?PyTorch的卷積神經網絡(cnn)手寫數字識別
1.5.1 代碼
1.1 卷積神經網絡簡介
卷積神經網絡(Convolutional Neural Networks,簡稱:CNN)是深度學習當中一個非常重要的神經網絡結構。它主要用于用在圖像圖片處理,視頻處理,音頻處理以及自然語言處理等等。
早在上世紀80年代左右,卷積神經網絡的概念就已經被提出來了。但其真正的崛起卻是在21世紀之后,21世紀之后,隨著深度學習理論的不斷完善,同時,由計算機硬件性能的提升,計算機算力的不斷發展,給卷積神經網絡這種算法提供了應用的空間。著名的AlphaGo,手機上的人臉識別,大多數都是采用卷積神經網絡。因此可以說,卷積神經網絡在如今的深度學習領域,有著舉足輕重的作用。
在了解卷積神經網絡之前,我們務必要知道:什么是神經網絡(Neural Networks),關于這個,我們已經在深度學習簡介的 第二部分有所介紹。這里就不贅述了。在了解了神經網絡的基礎上,我們再來探究:卷積神經網絡又是什么呢?當中的“卷積”這個詞,又意味著什么呢?
?
1.2 神經網絡
1.2.1?神經元模型
人工神神經網絡(neural networks)方面的研究很早就已出現,今天“神經網絡”?? ?已是一個相當大的、多學科交叉的學科領域.各相關學科對神經網絡的定義多種多樣。簡單單元組成的廣泛并行互連的網絡,它的組織能夠模擬生物神經系統對真實世界物體所作出的交互反應” 。
神經網絡中最基本的成分是神經元(neuron)模型,即上述定義中的“簡單單元”,在生物神經網絡中,每個神經元與其他神經元相連,當它“興奮”時,就會向相連的神經元發送化學物質,從而改變這些神經元內的電位;如果某神經元的電位超過了一個“閾值”(threshold),那么它就會被激活,即“興奮”起來,向其他神經元發送化學物質。在這個模型中,神經元接收到來自n個其他神經元傳遞過來的輸入信號,這些輸入信號通過帶權重的連接(connection)進行傳遞,神經元接收到的總輸入值將與神經元的間值進行比較,然后通過激活函數處理,產生神經元輸出。
?
?1.2.2 神經網絡模型
?神經網絡是一種運算模型,由大量的節點(或稱神經元)之間相互聯接構成。每個節點代表一種特定的輸出函數,稱為激勵函數(activation function)。每兩個節點間的連接都代表一個對于通過該連接信號的加權值,稱之為權重,這相當于人工神經網絡的記憶。網絡的輸出則依網絡的連接方式,權重值和激勵函數的不同而不同。而網絡自身通常都是對自然界某種算法或者函數的逼近,也可能是對一種邏輯策略的表達。
?
1.3 卷積神經網絡
1.3.1卷積的概念
卷積神經網絡與普通神經網絡的區別在于,卷積神經網絡包含了一個由卷積層和子采樣層(池化層)構成的特征抽取器。在卷積神經網絡的卷積層中,一個神經元只與部分鄰層神經元連接。在CNN的一個卷積層中,通常包含若干個特征圖(featureMap),每個特征圖由一些矩形排列的的神經元組成,同一特征圖的神經元共享權值,這里共享的權值就是卷積核。卷積核一般以隨機小數矩陣的形式初始化,在網絡的訓練過程中卷積核將學習得到合理的權值。共享權值(卷積核)帶來的直接好處是減少網絡各層之間的連接,同時又降低了過擬合的風險。子采樣也叫做池化(pooling),通常有均值子采樣(mean pooling)和最大值子采樣(max pooling)兩種形式。子采樣可以看作一種特殊的卷積過程。卷積和子采樣大大簡化了模型復雜度,減少了模型的參數。
1.3.2 卷積的計算過程
假設我們輸入的是5*5*1的圖像,中間的那個3*3*1是我們定義的一個卷積核(簡單來說可以看做一個矩陣形式運算器),通過原始輸入圖像和卷積核做運算可以得到綠色部分的結果,怎么樣的運算呢?實際很簡單就是我們看左圖中深色部分,處于中間的數字是圖像的像素,處于右下角的數字是我們卷積核的數字,只要對應相乘再相加就可以得到結果。例如圖中‘3*0+1*1+2*2+2*2+0*2+0*0+2*0+0*1+0*2=9’
計算過程如下動圖:
圖中最左邊的三個輸入矩陣就是我們的相當于輸入d=3時有三個通道圖,每個通道圖都有一個屬于自己通道的卷積核,我們可以看到輸出(output)的只有兩個特征圖意味著我們設置的輸出d=2,有幾個輸出通道就有幾層卷積核(比如圖中就有FilterW0和FilterW1),這意味著我們的卷積核數量就是輸入d的個數乘以輸出d的個數(圖中就是2*3=6個),其中每一層通道圖的計算與上文中提到的一層計算相同,再把每一個通道輸出的輸出再加起來就是綠色的輸出數字。
1.3.3?感受野
感受野(Receptive Field):卷積神經網絡各輸出層每個像素點在原始圖像上的映射區域大小。
下圖為感受野示意圖:
?當我們采用尺寸不同的卷積核時,最大的區別就是感受野的大小不同,所以經常會采用多層小卷積核來替換一層大卷積核,在保持感受野相同的情況下減少參數量和計算量。
例如十分常見的用2層3 * 3卷積核來替換1層5 * 5卷積核的方法,如下圖所示。
1.3.4?步長
每次卷積核移動的大小。
1.3.5?輸出特征尺寸計算
輸出特征尺寸計算:在了解神經網絡中卷積計算的整個過程后,就可以對輸出特征圖的尺寸進行計算。如下圖所示,5×5的圖像經過3×3大小的卷積核做卷積計算后輸出特征尺寸為3×3
?1.3.6?全零填充
當卷積核尺寸大于 1 時,輸出特征圖的尺寸會小于輸入圖片尺寸。如果經過多次卷積,輸出圖片尺寸會不斷減小。為了避免卷積之后圖片尺寸變小,通常會在圖片的外圍進行填充(padding),如下圖所示
全零填充(padding):為了保持輸出圖像尺寸與輸入圖像一致,經常會在輸入圖像周圍進行全零填充,如下所示,在5×5的輸入圖像周圍填0,則輸出特征尺寸同為5×5。
當padding=1和paadding=2時,如下圖所示:
1.3.7 標準化
使數據符合0均值,1為標準差的分布。
批標準化(Batch Normalization):對一小批數據(batch),做標準化處理。
?Batch Normalization將神經網絡每層的輸入都調整到均值為0,方差為1的標準正態分布,其目的是解決神經網絡中梯度消失的問題.
BN操作的另一個重要步驟是縮放和偏移,值得注意的是,縮放因子γ以及偏移因子β都是可訓練參數。?
1.3.7?池化層
池化(Pooling)用于減少特征數據量。
最大值池化可提取圖片紋理,均值池化可保留背景特征
?1.4 卷積神經網絡的全過程
?1.5?PyTorch的卷積神經網絡(cnn)手寫數字識別
使用的框架為pytorch。
數據集:MNIST數據集,60000張訓練圖像,每張圖像size為28*28。
可在http://yann.lecun.com/exdb/mnist/中獲取
1.5.1 代碼
import torch import torch.nn as nn import torchvision.datasets as dataset import torchvision.transforms as transforms import torch.utils.data as data_utils#獲取數據集 train_data=dataset.MNIST(root="D",train=True,transform=transforms.ToTensor(),download=True) test_data=dataset.MNIST(root="D",train=False,transform=transforms.ToTensor(),download=False) train_loader=data_utils.DataLoader(dataset=train_data, batch_size=100, shuffle=True) test_loader=data_utils.DataLoader(dataset=test_data, batch_size=100, shuffle=True)#創建網絡 class Net(torch.nn.Module):def __init__(self):super().__init__()self.conv=nn.Conv2d(1, 32, kernel_size=5, padding=2)self.bat2d=nn.BatchNorm2d(32)self.relu=nn.ReLU()self.pool=nn.MaxPool2d(2)self.linear=nn.Linear(14 * 14 * 32, 70)self.tanh=nn.Tanh()self.linear1=nn.Linear(70,30)self.linear2=nn.Linear(30, 10)def forward(self,x):y=self.conv(x)y=self.bat2d(y)y=self.relu(y)y=self.pool(y)y=y.view(y.size()[0],-1)y=self.linear(y)y=self.tanh(y)y=self.linear1(y)y=self.tanh(y)y=self.linear2(y)return y cnn=Net() cnn=cnn.cuda()#損失函數 los=torch.nn.CrossEntropyLoss()#優化函數 optime=torch.optim.Adam(cnn.parameters(), lr=0.01)#訓練模型 for epo in range(10):for i, (images,lab) in enumerate(train_loader):images=images.cuda()lab=lab.cuda()out = cnn(images)loss=los(out,lab)optime.zero_grad()loss.backward()optime.step()print("epo:{},i:{},loss:{}".format(epo+1,i,loss))#測試模型 loss_test=0 accuracy=0 with torch.no_grad():for j, (images_test,lab_test) in enumerate(test_loader):images_test = images_test.cuda()lab_test=lab_test.cuda()out1 = cnn(images_test)loss_test+=los(out1,lab_test)loss_test=loss_test/(len(test_data)//100)_,p=out1.max(1)accuracy += (p==lab_test).sum().item()accuracy=accuracy/len(test_data)print("loss_test:{},accuracy:{}".format(loss_test,accuracy))總結
以上是生活随笔為你收集整理的基于卷积神经网络(cnn)的手写数字识别(PyTorch)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 逻辑复制mysql_物理复制 vs 逻辑
- 下一篇: 陈志武《金融的逻辑2》笔记