成都做一個(gè)小企業(yè)網(wǎng)站需要多少錢2023網(wǎng)站分享
CNN
- 視覺處理三大任務(wù):分類、目標(biāo)檢測、圖像分割
- 上游:提取特征,CNN
- 下游:分類、目標(biāo)、分割等,具體的任務(wù)
概述
- 卷積神經(jīng)網(wǎng)絡(luò)是深度學(xué)習(xí)在計(jì)算機(jī)視覺領(lǐng)域的突破性成果。在計(jì)算機(jī)視覺領(lǐng)域, 往往我們輸入的圖像都很大,使用全連接網(wǎng)絡(luò)的話,計(jì)算的代價(jià)較高。另外圖像也很難保留原有的特征,導(dǎo)致圖像處理的準(zhǔn)確率不高。
- 卷積神經(jīng)網(wǎng)絡(luò)(Convolutional Neural Network,CNN)是一種專門用于處理具有網(wǎng)格狀結(jié)構(gòu)數(shù)據(jù)的深度學(xué)習(xí)模型。最初,CNN主要應(yīng)用于計(jì)算機(jī)視覺任務(wù),但它的成功啟發(fā)了在其他領(lǐng)域應(yīng)用,如自然語言處理等。
- 卷積神經(jīng)網(wǎng)絡(luò)(Convolutional Neural Network)是含有卷積層的神經(jīng)網(wǎng)絡(luò). 卷積層的作用就是用來自動(dòng)學(xué)習(xí)、提取圖像的特征。
CNN網(wǎng)絡(luò)主要有三部分構(gòu)成:卷積層、池化層和全連接層構(gòu)成,其中卷積層負(fù)責(zé)提取圖像中的局部特征;池化層用來大幅降低運(yùn)算量并特征增強(qiáng);全連接層類似神經(jīng)網(wǎng)絡(luò)的部分,用來輸出想要的結(jié)果。
全連接的局限性
- 全連接神經(jīng)網(wǎng)絡(luò)并不太適合處理圖像數(shù)據(jù)
參數(shù)量巨大
- 全連接結(jié)構(gòu)計(jì)算量非常大,假設(shè)我們有1000×1000的輸入,如果隱藏層也是1000×1000大小的神經(jīng)元,由于神經(jīng)元和圖像每一個(gè)像素連接,則參數(shù)量會(huì)達(dá)到驚人的1000×1000×1000×1000,僅僅一層網(wǎng)絡(luò)就已經(jīng)有
個(gè)參數(shù)。
表達(dá)能力太有限
- 全連接神經(jīng)網(wǎng)絡(luò)的角色只是一個(gè)分類器,如果將整個(gè)圖片直接輸入網(wǎng)絡(luò),不僅參數(shù)量大,也沒有利用好圖片中像素的空間特性,增加了學(xué)習(xí)難度,降低了學(xué)習(xí)效果。
卷積思想
- 卷:從左往右,從上往下
- 積:乘積,求和
概念
局部連接
- 局部連接可以更好地利用圖像中的結(jié)構(gòu)信息,空間距離越相近的像素其相互影響越大。
- 根據(jù)局部特征完成目標(biāo)的可辨識(shí)性。
權(quán)重共享
- 圖像從一個(gè)局部區(qū)域?qū)W習(xí)到的信息應(yīng)用到其他區(qū)域。
- 減少參數(shù),降低學(xué)習(xí)難度。
卷積層
卷積核
1.卷積核是卷積運(yùn)算過程中必不可少的一個(gè)“工具”,在卷積神經(jīng)網(wǎng)絡(luò)中,卷積核是非常重要的,它們被用來提取圖像中的特征。
2.卷積核其實(shí)是一個(gè)小矩陣,在定義時(shí)需要考慮以下幾方面的內(nèi)容:
- 卷積核的個(gè)數(shù):卷積核(過濾器)的個(gè)數(shù)決定了其輸出特征矩陣的通道數(shù)。
- 卷積核的值:卷積核的值是自定義的,根據(jù)想要提取的特征來進(jìn)行設(shè)置,后續(xù)進(jìn)行更新。
- 卷積核的大小:常見的卷積核有1×1、3×3、5×5等,一般都是奇數(shù) × 奇數(shù)。
3.下圖就是一個(gè)3×3的卷積核:
卷積計(jì)算
卷積計(jì)算過程
1.卷積的過程是將卷積核在圖像上進(jìn)行滑動(dòng)計(jì)算,每次滑動(dòng)到一個(gè)新的位置時(shí),卷積核和圖像進(jìn)行點(diǎn)對(duì)點(diǎn)的計(jì)算,并將其求和得到一個(gè)新的值,然后將這個(gè)新的值加入到特征圖中,最終得到一個(gè)新的特征圖。
- input 表示輸入的圖像
- filter 表示卷積核, 也叫做濾波器
- input 經(jīng)過 filter 的得到輸出為最右側(cè)的圖像,該圖叫做特征圖
- 左上角的點(diǎn)計(jì)算方法:
- 按照上面的計(jì)算方法可以得到最終的特征圖為:
2.卷積的重要性在于它可以將圖像中的特征與卷積核進(jìn)行卷積操作,從而提取出圖像中的特征。
3.可以通過不斷調(diào)整卷積核的大小、卷積核的值和卷積操作的步長,可以提取出不同尺度和位置的特征。
# 面相對(duì)象的模塊化編程
from matplotlib import pyplot as plt
import os
import torch.nn as nn
import torchdef test001():# __file__當(dāng)前文件current_path = os.path.dirname(__file__)print(current_path)img_path = os.path.join(current_path, '..\data','1.png')print("img_path:",img_path)# 轉(zhuǎn)換為相對(duì)路徑img_path = os.path.realpath(img_path)print("img_realpath:",img_path)# 使用plt讀取圖片img = plt.imread(img_path)print(img.shape)# 轉(zhuǎn)換為張量:HWC-->CHW-->NCHW 鏈?zhǔn)秸{(diào)用# 深拷貝原圖在進(jìn)行鏈?zhǔn)讲僮?#xff0c;返回一個(gè)新值img = torch.Tensor(img).permute(2,0,1).unsqueeze(0)# 創(chuàng)建卷積核conv = nn.Conv2d(in_channels=4,# 輸入通道數(shù)out_channels=1,# 輸出通道數(shù)# 如果要產(chǎn)出32個(gè)特征圖,那么就需要32個(gè)卷積核,每個(gè)卷積核的通道數(shù)為這個(gè)卷積核的通道數(shù)為4# out_channels=32,# 輸出通道數(shù)kernel_size=3,# 卷積核大小# kernel_size=(5,3),# 卷積核大小stride=1,# 步長padding=0 # 填充# bias=True
)# 使用卷積核,對(duì)圖像進(jìn)行卷積操作out = conv(img)# 把圖片顯示出來print(out.shape)# out[0][0]: 806, 574# out[0][0]:其中含有梯度等元素# detach葉子結(jié)點(diǎn),數(shù)據(jù)的引用,只指向源數(shù)據(jù),不包含梯度等其他元素plt.imshow(out[0][0].detach().numpy(), cmap='gray')# 取第32個(gè)卷積核的輸出顯示# plt.imshow(out[0][31].detach().numpy(), cmap='gray')plt.show()# 作為主機(jī)模塊執(zhí)行
if __name__ == '__main__':test001()
# 面相對(duì)象的模塊化編程
from matplotlib import pyplot as plt
import os
import torch.nn as nn
import torchdef test001():# __file__當(dāng)前文件current_path = os.path.dirname(__file__)print(current_path)img_path = os.path.join(current_path, '..\data','1.png')print("img_path:",img_path)# 轉(zhuǎn)換為相對(duì)路徑img_path = os.path.realpath(img_path)print("img_realpath:",img_path)# 使用plt讀取圖片img = plt.imread(img_path)print(img.shape)# 轉(zhuǎn)換為張量:HWC-->CHW-->NCHW 鏈?zhǔn)秸{(diào)用# 深拷貝原圖在進(jìn)行鏈?zhǔn)讲僮?#xff0c;返回一個(gè)新值img = torch.Tensor(img).permute(2,0,1).unsqueeze(0)# 創(chuàng)建卷積核conv = nn.Conv2d(in_channels=4,# 輸入通道數(shù)# 如果要產(chǎn)出32個(gè)特征圖,那么就需要32個(gè)卷積核,每個(gè)卷積核的通道數(shù)為這個(gè)卷積核的通道數(shù)為4out_channels=32,# 輸出通道數(shù)kernel_size=(5,3),# 卷積核大小stride=1,# 步長padding=0,# 填充bias=True
)# 使用卷積核,對(duì)圖像進(jìn)行卷積操作out = conv(img)# 輸出128個(gè)特征圖conv2 = nn.Conv2d(in_channels=32,# 輸入通道數(shù)out_channels=128,# 輸出通道數(shù)# 如果要產(chǎn)出32個(gè)特征圖,那么就需要32個(gè)卷積核,每個(gè)卷積核的通道數(shù)為這個(gè)卷積核的通道數(shù)為4kernel_size=(5,3),# 卷積核大小stride=1,# 步長padding=0,bias=True)out = conv2(out)# 把圖片顯示出來print(out.shape)# out[0][0]: 806, 574# out[0][0]:其中含有梯度等元素# detach葉子結(jié)點(diǎn),數(shù)據(jù)的引用,只指向源數(shù)據(jù),不包含梯度等其他元素# 取第32個(gè)卷積核的輸出顯示plt.imshow(out[0][31].detach().numpy(), cmap='gray')plt.show()# 作為主機(jī)模塊執(zhí)行
if __name__ == '__main__':test001()
卷積計(jì)算底層實(shí)現(xiàn)
- 并不是水平和垂直方向的循環(huán)。
- 下圖是卷積的基本運(yùn)算方式:
- 卷積真正的計(jì)算過程如下圖:
邊緣填充
Padding
- 通過上面的卷積計(jì)算,我們發(fā)現(xiàn)最終的特征圖比原始圖像要小,如果想要保持圖像大小不變, 可在原圖周圍添加padding來實(shí)現(xiàn),更重要的,邊緣填充還更好的保護(hù)了圖像邊緣數(shù)據(jù)的特征。
步長Stride
- 按照步長為1來移動(dòng)卷積核
- 如果我們把 Stride 增大為2
- stride太小:重復(fù)計(jì)算較多,計(jì)算量大,訓(xùn)練效率降低; stride太大:會(huì)造成信息遺漏,無法有效提煉數(shù)據(jù)背后的特征;
多通道卷積計(jì)算
數(shù)字圖像的標(biāo)識(shí)
- 圖像在計(jì)算機(jī)眼中是一個(gè)矩陣,通道越多,可以表達(dá)的特征就越豐富
具體計(jì)算實(shí)現(xiàn)
1.計(jì)算方法
- 當(dāng)輸入有多個(gè)通道(Channel), 例如RGB三通道, 此時(shí)要求卷積核需要有相同的通道數(shù)。
- 卷積核通道與對(duì)應(yīng)的輸入圖像通道進(jìn)行卷積。
- 將每個(gè)通道的卷積結(jié)果按位相加得到最終的特征圖。
多卷積核卷積計(jì)算
- 實(shí)際對(duì)圖像進(jìn)行特征提取時(shí), 我們需要使用多個(gè)卷積核進(jìn)行特征提取。這個(gè)多個(gè)卷積核可以理解為從不同到的視角、不同的角度對(duì)圖像特征進(jìn)行提取。所有卷積核輸出值決定了卷積和有幾個(gè)
特征圖大小
1.輸出特征圖的大小與以下參數(shù)息息相關(guān):
- size: 卷積核/過濾器大小,一般會(huì)選擇為奇數(shù),比如有 1×1, 3×3, 5×5
- Padding: 零填充的方式
- Stride: 步長
2.例:
- 輸入圖像大小: W x W
- 卷積核大小: F x F
- Stride: S
- Padding: P
- 輸出圖像大小: N x N
3.例:
- 圖像大小: 5 x 5
- 卷積核大小: 3 x 3
- Stride: 1
- Padding: 1
- (5 - 3 + 2) / 1 + 1 = 5, 即得到的特征圖大小為: 5 x 5
連續(xù)卷積
卷積參數(shù)共享
數(shù)據(jù)是32×32×3的圖像,用 10?個(gè) 5×5×3?的filter來進(jìn)行卷積操作,所需的權(quán)重參數(shù)有多少個(gè)呢?
- 5×5×3 = 75,表示每個(gè)卷積核只需要75個(gè)參數(shù)。
- 10個(gè)不同的卷積核,就需要10*75 = 750個(gè)卷積核參數(shù)。
- 如果還考慮偏置參數(shù)b,最終需要 750+10=760 個(gè)參數(shù)。
局部特征提取
- 通過卷積操作,CNN具有局部感知性,能夠捕捉輸入數(shù)據(jù)的局部特征,這在處理圖像等具有空間結(jié)構(gòu)的數(shù)據(jù)時(shí)非常有用。
PyTorch卷積層神經(jīng)網(wǎng)絡(luò)
import torch
import torch.nn.functional as Fclass MyNet(torch.nn.Module):def __init__(self):super(MyNet, self).__init__()# 第一層卷積:30 (W - K + 2P) /S + 1:輸出的寬高,因?yàn)榇藭r(shí)是矩陣就計(jì)算一個(gè)表就行self.conv1 = torch.nn.Conv2d(in_channels=1, # 輸入通道out_channels=32, # 輸出的通道kernel_size=3, # 卷積核大小padding= 0, # 填充stride=1, # 步長)# 第二層,輸出128個(gè)通道:28 (W - K + 2P) /S + 1self.conv2 = torch.nn.Conv2d(in_channels=32, # 輸入通道out_channels=128, # 輸出的通道kernel_size=3, # 卷積核大小padding= 0, # 填充stride=1, # 步長)# 第三個(gè)通道,輸出512個(gè)通道:26 (W - K + 2P) /S + 1self.conv3 = torch.nn.Conv2d(in_channels=128, # 輸入通道out_channels=512, # 輸出的通道kernel_size=3, # 卷積核大小padding= 0, # 填充stride=1, # 步長)# 線性層做分類判斷,10分類self.fc = torch.nn.Linear(512*26*26, 10)def forward(self, x):# 卷積層x = F.relu(self.conv1(x))print(x.shape)x = F.relu(self.conv2(x))x = F.relu(self.conv3(x))# 輸出NCHW,然后做全連接# x.size(0):輸出的有幾個(gè)Nx = x.view(x.size(0), -1)print(x.shape)# 輸入的數(shù)據(jù)有四條,每條數(shù)據(jù)10個(gè)輸出值x = self.fc(x)# 每條數(shù)據(jù)進(jìn)行激活,每條數(shù)據(jù)有10分類x = torch.nn.Softmax(dim=1)(x)return xif __name__ == '__main__':# N = 4 C=1 H=32 W=32input = torch.randn(4,1,32,32)model = MyNet()out = model(input)print(out)
池化層
概述
1.池化層 (Pooling) 降低維度, 縮減模型大小,提高計(jì)算速度. 即: 主要對(duì)卷積層學(xué)習(xí)到的特征圖進(jìn)行下采樣(SubSampling)處理。
2.池化層主要有兩種:
(1)最大池化 max pooling
- 最大池化是從每個(gè)局部區(qū)域中選擇最大值作為池化后的值,這樣可以保留局部區(qū)域中最顯著的特征。最大池化在提取圖像中的紋理、形狀等方面具有很好的效果。
(2)平均池化 avgPooling
- 平均池化是將局部區(qū)域中的值取平均作為池化后的值,這樣可以得到整體特征的平均值。平均池化在提取圖像中的整體特征、減少噪聲等方面具有較好的效果。
池化層計(jì)算
整體結(jié)構(gòu)
計(jì)算
步長Stride
- 計(jì)算方法和卷積核步長計(jì)算方法一致
邊緣填充Padding
多通道池化計(jì)算
- 在處理多通道輸入數(shù)據(jù)時(shí),池化層對(duì)每個(gè)輸入通道分別池化,而不是像卷積層那樣將各個(gè)通道的輸入相加。這意味著池化層的輸出和輸入的通道數(shù)是相等。
池化層的作用
1.池化操作的優(yōu)勢有:
- 通過降低特征圖的尺寸,池化層能夠減少計(jì)算量,從而提升模型的運(yùn)行效率。
- 池化操作可以帶來特征的平移、旋轉(zhuǎn)等不變性,這有助于提高模型對(duì)輸入數(shù)據(jù)的魯棒性。
- 池化層通常是非線性操作,例如最大值池化,這樣可以增強(qiáng)網(wǎng)絡(luò)的表達(dá)能力,進(jìn)一步提升模型的性能。
2.池化也有缺點(diǎn):
- 池化操作會(huì)丟失一些信息,這是它最大的缺點(diǎn);
池化API
API請(qǐng)參考具體官方文檔:torch.nn — PyTorch 2.5 documentationhttps://pytorch.org/docs/stable/nn.html#padding-layers
import torch
import torch.nn as nndef test01():torch.manual_seed(1)# 輸入的特征圖數(shù)據(jù)input = torch.randint(0, 255, (1, 64, 224, 224), dtype=torch.float)print(input[0][0][0:4,:5])# 池化核pool = nn.MaxPool2d(kernel_size=2, # 池化核大小stride=2, # 步長return_indices=True# 返回索引)# 對(duì)數(shù)據(jù)進(jìn)行池化操作out, indices = pool(input)print(indices)print(out.shape)if __name__ == '__main__':test01()
整體結(jié)構(gòu)
- 卷積池化全連接神經(jīng)網(wǎng)絡(luò)框架
import torch
import torch.nn as nnclass numberModel(nn.Module):def __init__(self):super(numberModel, self).__init__()# 卷積層self.C1 = nn.Sequential(nn.Conv2d(in_channels=1, # 輸入通道out_channels=6, # 輸出通道kernel_size=5, # 卷積核大小stride=1, # 步長padding=0 # 填充), nn.ReLU())# 池化層self.S2 = nn.MaxPool2d(kernel_size=2,stride=2,padding=0)# 卷積層self.C3 = nn.Sequential(nn.Conv2d(in_channels=6, # 輸入通道out_channels=16, # 輸出通道kernel_size=5, # 卷積核大小stride=1, # 步長padding=0 # 填充), nn.ReLU())# 全連接層self.FC1 = nn.Sequential(nn.Linear(16*5*5,120, bias=True), nn.ReLU())self.FC2 = nn.Sequential(nn.Linear(120,84, bias=True), nn.ReLU())self.out = nn.Sequential(nn.Linear(84,10, bias=True), nn.Softmax(dim=1))def forward(self, x):x = self.C1(x)x = self.S2(x)x = self.C3(x)x = self.S2(x)x = x.view(x.size()[0],-1) # 自動(dòng)計(jì)算的數(shù)量批次Batchx = self.FC1(x)x = self.FC2(x)x = self.out(x)return x
if __name__ == '__main__':torch.manual_seed(1)# 網(wǎng)絡(luò)model = numberModel()# 輸入數(shù)據(jù) NCHWinput = torch.randn(1, 1, 32, 32)# 輸出結(jié)果output = model(input)print(output)
"""
tensor([[0.1055, 0.0958, 0.1093, 0.0939, 0.0942, 0.0990, 0.1092, 0.0956, 0.0874,0.1102]], grad_fn=<SoftmaxBackward0>)
"""
特征圖變化
卷積知識(shí)擴(kuò)展
卷積結(jié)果
二維卷積
- 分單通道版本和多通道版本。
單通道版本
- 之前所講卷積相關(guān)內(nèi)容其實(shí)真正意義上叫做二維卷積(單通道卷積版本),即只有一個(gè)通道的卷積。
多通道版本
- 彩色圖像擁有R、G、B這三層通道,因此我們?cè)诰矸e時(shí)需要分別針對(duì)這三層進(jìn)行卷積
- 最后將三個(gè)通道的卷積結(jié)果進(jìn)行合并(元素相加),得到卷積結(jié)果
三維卷積(3D)
- 二維卷積是在單通道的一幀圖像上進(jìn)行滑窗操作,輸入是高度H寬度W的二維矩陣。
- 而如果涉及到視頻上的連續(xù)幀或者立體圖像中的不同切片,就需要引入深度通道,此時(shí)輸入就變?yōu)楦叨菻寬度W*深度C的三維矩陣。
- 不同于二維卷積核只在兩個(gè)方向上運(yùn)動(dòng),三維卷積的卷積核會(huì)在三個(gè)方向上運(yùn)動(dòng),因此需要有三個(gè)自由度。
- 這種特性使得三維卷積能夠有效地描述3D空間中的對(duì)象關(guān)系,它在一些應(yīng)用中具有顯著的優(yōu)勢,例如3D對(duì)象的分割以及醫(yī)學(xué)圖像的重構(gòu)等。
反卷積
- 卷積是對(duì)輸入圖像及進(jìn)行特征提取,這樣會(huì)導(dǎo)致尺寸會(huì)越變?cè)叫?/strong>,而反卷積是進(jìn)行相反操作。并不會(huì)完全還原到跟輸入圖一樣,只是保證了與輸入圖像尺寸一致,主要用于向上采樣。從數(shù)學(xué)上看,反卷積相當(dāng)于是將卷積核轉(zhuǎn)換為稀疏矩陣后進(jìn)行轉(zhuǎn)置計(jì)算。也被稱為轉(zhuǎn)置卷積。
反卷積計(jì)算過程
- 在2x2的輸入圖像上使用【步長1、邊界全0填充】的3x3卷積核,進(jìn)行轉(zhuǎn)置卷積(反卷積)計(jì)算,向上采樣后輸出的圖像大小為4x4。語義分割里面就需要反卷積還原到原始圖像大小。
反卷積底層計(jì)算
空洞卷積(膨脹卷積)
為擴(kuò)大感受野,在卷積核矩陣的元素之間插入空格“膨脹”內(nèi)核,形成“空洞卷積”(或稱膨脹卷積),并用膨脹率參dilationL
表示要擴(kuò)大內(nèi)核的范圍,即在內(nèi)核元素之間插入dilation-1
個(gè)空格。當(dāng)dilation=1
時(shí),則內(nèi)核元素之間沒有插入空格,變?yōu)闃?biāo)準(zhǔn)卷積。圖中是dilation=2
的空洞卷積。
- 代碼實(shí)現(xiàn)過程
import torch
import torch.nn as nndef test01():torch.manual_seed(1)#輸入數(shù)據(jù)x = torch.randn(1, 1, 7, 7)# 創(chuàng)建一個(gè)卷積核conv = nn.Conv2d(in_channels=1, # 輸入通道數(shù)out_channels=1, # 輸出通道數(shù)kernel_size=3, # 卷積核大小stride=1, # 步長padding=0, # 填充dilation=2 # 卷積核的步長)out = conv(x)print(out.shape)if __name__ == '__main__':test01()"""
torch.Size([1, 1, 3, 3])
"""
可分離卷積
空間可分離卷積
- 空間可分離卷積是將卷積核分解為兩項(xiàng)獨(dú)立的核分別進(jìn)行操作。在數(shù)學(xué)中我們可以將矩陣分解:
- 所以對(duì)3x3的卷積核,我們同樣可以拆分成 3x1 和 1x3 的兩個(gè)卷積核,對(duì)其進(jìn)行卷積,且采用可分離卷積的計(jì)算量比標(biāo)準(zhǔn)卷積要少。
- 代碼實(shí)現(xiàn)過程?
import torch
import torch.nn as nnclass nomalModel(nn.Module):def __init__(self):super(nomalModel, self).__init__()self.conv1 = nn.Conv2d(in_channels=1, # 輸入通道out_channels=1, # 輸出通道kernel_size=3, # 卷積核大小stride=1, # 步長padding=0,# 填充bias=False # 是否使用偏置)def forward(self, x):out = self.conv1(x)return outclass waveModel(nn.Module):def __init__(self):super(waveModel, self).__init__()self.conv1 = nn.Conv2d(in_channels=1, # 輸入通道out_channels=1, # 輸出通道kernel_size=(3,1), # 卷積核大小stride=1, # 步長padding=0,# 填充bias=False, # 是否使用偏置groups=1 # 分組卷積)self.conv2 = nn.Conv2d(in_channels=1, # 輸入通道out_channels=1, # 輸出通道kernel_size=(1,3), # 卷積核大小stride=1, # 步長padding=0,# 填充bias=False, # 是否使用偏置groups=1 # 分組卷積)def forward(self, x):out = self.conv1(x)out = self.conv2(out)return outif __name__ == '__main__':model1 = nomalModel()# 打印參數(shù)for name, param in model1.named_parameters():print(name, param.shape)print("======================")model2 = waveModel()for name, param in model2.named_parameters():print(name, param.shape)"""
conv1.weight torch.Size([1, 1, 3, 3]) 3*3
======================
conv1.weight torch.Size([1, 1, 3, 1])3
conv2.weight torch.Size([1, 1, 1, 3])3 ==>3+3
"""
深度可分離卷積
1.深度可分離卷積由兩部組成:深度卷積核1x1卷積
- 輸入圖的每一個(gè)通道,我們都使用了對(duì)應(yīng)的卷積核進(jìn)行卷積。 通道數(shù)量 = 卷積核個(gè)數(shù)
- 完成卷積后,對(duì)輸出內(nèi)容進(jìn)行
1x1
的卷積
- 代碼實(shí)現(xiàn)
import torch
import torch.nn as nnclass normalModel(nn.Module):def __init__(self):super(normalModel, self).__init__()self.conv1 = nn.Conv2d(in_channels=8, # 輸入通道out_channels=8,# 輸出通道kernel_size=3, # 卷積核大小stride=1, # 步長padding=0, # 填充bias=False # 是否使用偏置)def forward(self, x):out = self.conv1(x)return outclass deepModel(nn.Module):def __init__(self) -> None:super(deepModel, self).__init__()self.conv1 = nn.Conv2d(in_channels=8, # 輸入通道out_channels=8,# 輸出通道kernel_size=3, # 卷積核大小stride=1, # 步長padding=0, # 填充bias=False, # 是否使用偏置groups=8 # 分組卷積 卷積核數(shù)量等于輸入通道的數(shù)量8/8 = 1)self.conv2 = nn.Conv2d(in_channels=8, # 輸入通道out_channels=8,# 輸出通道kernel_size=1, # 卷積核大小stride=1, # 步長padding=0, # 填充bias=False # 是否使用偏置)def forward(self, x):x = self.conv1(x)out = self.conv2(out)return out
if __name__ == '__main__':conv1 = normalModel()for name, param in conv1.named_parameters():print(name, param.shape) # 576print("======================")conv2 = deepModel()for name, param in conv2.named_parameters():print(name, param.shape) # 136"""
conv1.weight torch.Size([8, 8, 3, 3])
======================
conv1.weight torch.Size([8, 1, 3, 3])
conv2.weight torch.Size([8, 8, 1, 1])
"""
扁平卷積
- 扁平卷積是將標(biāo)準(zhǔn)卷積拆分成為3個(gè)
1x1
的卷積核,然后再分別對(duì)輸入層進(jìn)行卷積計(jì)算。
- 標(biāo)準(zhǔn)卷積參數(shù)量XYC,計(jì)算量為MNCXY
- 拆分卷積參數(shù)量(X+Y+C),計(jì)算量為MN(C+X+Y)
分組卷積
- 2012年,AlexNet論文中最先提出來的概念,當(dāng)時(shí)主要為了解決GPU顯存不足問題,將卷積分組放到兩個(gè)GPU中并行執(zhí)行。
- 在分組卷積中,卷積核被分成不同的組,每組負(fù)責(zé)對(duì)相應(yīng)的輸入層進(jìn)行卷積計(jì)算,最后再進(jìn)行合并。
混洗分組卷積
- 分組卷積中最終結(jié)果會(huì)按照原先的順序進(jìn)行合并組合,阻礙了模型在訓(xùn)練時(shí)特征信息在通道間流動(dòng),削弱了特征表示?;煜捶纸M卷積,主要是將分組卷積后的計(jì)算結(jié)果混合交叉在一起輸出。
多通道卷積與偏執(zhí)
卷積核卷完之后,偏置矩陣就會(huì)與輸出特征矩陣相加,得到本次卷積的最終結(jié)果。
有兩個(gè)結(jié)論:
- 輸入特征的通道數(shù)決定了卷積核的通道數(shù)(卷積核通道個(gè)數(shù)=輸入特征通道個(gè)數(shù))。
- 卷積核的個(gè)數(shù)決定了輸出特征矩陣的通道數(shù)與偏置矩陣的通道數(shù)(卷積核個(gè)數(shù)=輸出特征通道數(shù)=偏置矩陣通道數(shù))。
感受野
理解感受野
- 字面意思是感受的視野范圍,如果堆疊3個(gè)3 x 3的卷積層,并且保持滑動(dòng)窗口步長為1,其感受野就是7×7的了, 這跟一個(gè)使用7x7卷積核的結(jié)果是一樣的
感受野的作用
- 假設(shè)輸入大小都是h × w × C,并且都使用C個(gè)卷積核(得到C個(gè)特征圖),可以來計(jì)算 一下其各自所需參數(shù)