網站首頁 編程語言 正文
一、CNN簡介
1. 神經網絡基礎
輸入層(Input layer),眾多神經元(Neuron)接受大量非線形輸入訊息。輸入的訊息稱為輸入向量。
輸出層(Output layer),訊息在神經元鏈接中傳輸、分析、權衡,形成輸出結果。輸出的訊息稱為輸出向量。
隱藏層(Hidden layer),簡稱“隱層”,是輸入層和輸出層之間眾多神經元和鏈接組成的各個層面。如果有多個隱藏層,則意味著多個激活函數。
2. 卷積一下哦
卷積神經網絡(Convolutional Neural Network,CNN)針對全連接網絡的局限做出了修正,加入了卷積層(Convolution層)和池化層(Pooling層)。通常情況下,卷積神經網絡由若干個卷積層(Convolutional Layer)、激活層(Activation Layer)、池化層(Pooling Layer)及全連接層(Fully Connected Layer)組成。
下面看怎么卷積的
1.如圖,可以看到:
(1)兩個神經元,即depth=2,意味著有兩個濾波器。
(2)數據窗口每次移動兩個步長取3*3的局部數據,即stride=2。
(3)邊緣填充,zero-padding=1,主要為了防止遺漏邊緣的像素信息。
然后分別以兩個濾波器filter為軸滑動數組進行卷積計算,得到兩組不同的結果。
2.如果初看上圖,可能不一定能立馬理解啥意思,但結合上文的內容后,理解這個動圖已經不是很困難的事情:
(1)左邊是輸入(7*7*3中,7*7代表圖像的像素/長寬,3代表R、G、B 三個顏色通道)
(2)中間部分是兩個不同的濾波器Filter w0、Filter w1
(3)最右邊則是兩個不同的輸出
(4)隨著左邊數據窗口的平移滑動,濾波器Filter w0 / Filter w1對不同的局部數據進行卷積計算。
局部感知:左邊數據在變化,每次濾波器都是針對某一局部的數據窗口進行卷積,這就是所謂的CNN中的局部感知機制。打個比方,濾波器就像一雙眼睛,人類視角有限,一眼望去,只能看到這世界的局部。如果一眼就看到全世界,你會累死,而且一下子接受全世界所有信息,你大腦接收不過來。當然,即便是看局部,針對局部里的信息人類雙眼也是有偏重、偏好的。比如看美女,對臉、胸、腿是重點關注,所以這3個輸入的權重相對較大。
參數共享:數據窗口滑動,導致輸入在變化,但中間濾波器Filter w0的權重(即每個神經元連接數據窗口的權重)是固定不變的,這個權重不變即所謂的CNN中的參數(權重)共享機制。
3. 卷積計算
圖中最左邊的三個輸入矩陣就是我們的相當于輸入d=3時有三個通道圖,每個通道圖都有一個屬于自己通道的卷積核,我們可以看到輸出(output)的只有兩個特征圖意味著我們設置的輸出的d=2,有幾個輸出通道就有幾層卷積核(比如圖中就有FilterW0和FilterW1),這意味著我們的卷積核數量就是輸入d的個數乘以輸出d的個數(圖中就是2*3=6個),其中每一層通道圖的計算與上文中提到的一層計算相同,再把每一個通道輸出的輸出再加起來就是綠色的輸出數字啦!
舉例:
綠色輸出的第一個特征圖的第一個值:
1通道x[ : :0] 1*1+1*0 = 1 (0像素點省略)
2通道x[ : :1] 1*0+1*(-1)+2*0 = -1
3通道x[ : :2] 2*0 = 0
b = 1
輸出:1+(-1)+ 0 + 1(這個是b)= 1
綠色輸出的第二個特征圖的第一個值:
1通道x[ : :0] 1*0+1*0 = 0 (0像素點省略)
2通道x[ : :1] 1*0+1*(-1)+2*0 = -1
3通道x[ : :2] 2*0 = 0
b = 0
輸出:0+(-1)+ 0 + 1(這個是b)= 0
二、CNN實例代碼
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
模型訓練超參數設置,構建訓練數據:如果你沒有源數據,那么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
)
數據下載后是不可以直接看的,查看第一張圖片數據:
print(train_data.data.size())
print(train_data.targets.size())
print(train_data.data[0])
結果:60000張圖片數據,維度都是28*28,單通道
畫一個圖片顯示出來
# 畫一個圖片顯示出來
plt.imshow(train_data.data[0].numpy(),cmap='gray')
plt.title('%i'%train_data.targets[0])
plt.show()
結果:
訓練和測試數據準備,數據導入:
#訓練和測試數據準備
train_loader=Data.DataLoader(dataset=train_data, batch_size=BATCH_SIZE, shuffle=True)
test_data=torchvision.datasets.MNIST(
root='./mnist',
train=False,
)
#這里只取前3千個數據吧,差不多已經夠用了,然后將其歸一化。
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]
注意:這里的歸一化在此模型中區別不大
構建CNN模型:
'''開始建立CNN網絡'''
class CNN(nn.Module):
def __init__(self):
super(CNN,self).__init__()
'''
一般來說,卷積網絡包括以下內容:
1.卷積層
2.神經網絡
3.池化層
'''
self.conv1=nn.Sequential(
nn.Conv2d( #--> (1,28,28)
in_channels=1, #傳入的圖片是幾層的,灰色為1層,RGB為三層
out_channels=16, #輸出的圖片是幾層
kernel_size=5, #代表掃描的區域點為5*5
stride=1, #就是每隔多少步跳一下
padding=2, #邊框補全,其計算公式=(kernel_size-1)/2=(5-1)/2=2
), # 2d代表二維卷積 --> (16,28,28)
nn.ReLU(), #非線性激活層
nn.MaxPool2d(kernel_size=2), #設定這里的掃描區域為2*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, #代表掃描的區域點為5*5
stride=1, #就是每隔多少步跳一下
padding=2, #邊框補全,其計算公式=(kernel_size-1)/2=(5-1)/2=
), # --> (32,14,14)
nn.ReLU(),
nn.MaxPool2d(kernel_size=2), #設定這里的掃描區域為2*2,且取出該2*2中的最大值 --> (32,7,7),這里是三維數據
)
self.out=nn.Linear(32*7*7,10) #注意一下這里的數據是二維的數據
def forward(self,x):
x=self.conv1(x)
x=self.conv2(x) #(batch,32,7,7)
#然后接下來進行一下擴展展平的操作,將三維數據轉為二維的數據
x=x.view(x.size(0),-1) #(batch ,32 * 7 * 7)
output=self.out(x)
return output
把模型實例化打印一下:
cnn=CNN()
print(cnn)
結果:
開始訓練:
# 添加優化方法
optimizer=torch.optim.Adam(cnn.parameters(),lr=LR)
# 指定損失函數使用交叉信息熵
loss_fn=nn.CrossEntropyLoss()
'''
開始訓練我們的模型哦
'''
step=0
for epoch in range(EPOCH):
#加載訓練數據
for step,data in enumerate(train_loader):
x,y=data
#分別得到訓練數據的x和y的取值
b_x=Variable(x)
b_y=Variable(y)
output=cnn(b_x) #調用模型預測
loss=loss_fn(output,b_y)#計算損失值
optimizer.zero_grad() #每一次循環之前,將梯度清零
loss.backward() #反向傳播
optimizer.step() #梯度下降
#每執行50次,輸出一下當前epoch、loss、accuracy
if (step%50==0):
#計算一下模型預測正確率
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)
'''
打印十個測試集的結果
'''
test_output=cnn(test_x[:10])
y_pred=torch.max(test_output,1)[1].data.squeeze() #選取最大可能的數值所在的位置
print(y_pred.tolist(),'predecton Result')
print(test_y[:10].tolist(),'Real Result')
結果:
卷積層維度變化:
(1)輸入1*28*28,即1通道,28*28維;
(2)卷積層-01:16*28*28,即16個卷積核,卷積核維度5*5,步長1,邊緣填充2,維度計算公式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個類別的概率,那么首先對最后的池化層進行壓縮為二維(1,32*7*7),然后全連接層維度(32*7*7,10),最后(1,32*7*7)*(32*7*7,10)
原文鏈接:https://blog.csdn.net/L_goodboy/article/details/128079113
相關推薦
- 2023-03-21 Flutter?web?bridge?通信總結分析詳解_Android
- 2022-12-05 深入了解C++封閉類的定義與使用_C 語言
- 2022-04-19 C#中Task.ContinueWith連續任務使用實例_C#教程
- 2021-12-02 基于C語言掃雷游戲的設計與實現_C 語言
- 2022-03-22 .NET?6開發TodoList應用之實現查詢排序_實用技巧
- 2022-06-30 python數據操作之lambda表達式詳情_python
- 2021-12-15 Redis可視化工具Redis?Desktop?Manager的具體使用_Redis
- 2022-03-15 feign.RetryableException: Read timed out executing
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支