目錄
MobileNetV1原理
MobileNet V1的網(wǎng)絡(luò)結(jié)構(gòu)如下:
為什么要設(shè)計(jì)MobileNet:
MobileNetV1的主要特點(diǎn)如下:
MobileNetV1的創(chuàng)新點(diǎn):
MobileNetV1源碼(torch版)
訓(xùn)練10個(gè)epoch的效果
MobileNetV1原理
????????MobileNet V1是一種輕量級的卷積神經(jīng)網(wǎng)絡(luò),能夠在保持較高準(zhǔn)確率的情況下具有較少的參數(shù)量和計(jì)算時(shí)間。它是由Google的研究人員在2017年提出的,并成為當(dāng)時(shí)最流行的輕量級模型之一。
????????MobileNet V1的核心思想是通過深度分離卷積來減少模型的參數(shù)量和計(jì)算時(shí)間。與標(biāo)準(zhǔn)卷積不同,深度分離卷積將空間卷積和通道卷積分為兩個(gè)獨(dú)立的卷積層,這使得網(wǎng)絡(luò)更加高效。具體來說,在深度分離卷積中,首先使用一個(gè)空間卷積,然后使用一個(gè)通道卷積來提取特征。這與標(biāo)準(zhǔn)卷積相比可以減少參數(shù)數(shù)量并加速運(yùn)算。
MobileNet V1的網(wǎng)絡(luò)結(jié)構(gòu)如下:
????????MobileNet V1由序列卷積和1x1卷積兩個(gè)部分組成。序列卷積包括13個(gè)深度可分離卷積層,每個(gè)層都包括一個(gè)3x3的卷積和一個(gè)批量歸一化層(BN層),并且在卷積之后使用了ReLU6激活函數(shù)。最后,1x1卷積層用于生成最終的特征向量,并使用全局平均池化來縮小特征圖的大小。在最后一層之后,使用一個(gè)全連接層來進(jìn)行分類。MobileNet V1可以根據(jù)需要使用不同的輸入分辨率,其超參數(shù)取決于輸入分辨率和需要的精度。
為什么要設(shè)計(jì)MobileNet:
????????Mobilenetv1是一種輕量級的深度神經(jīng)網(wǎng)絡(luò)模型,設(shè)計(jì)的目的是在保持較高的精度的同時(shí)減小模型的大小和計(jì)算量,使其適合于移動(dòng)設(shè)備的推理任務(wù)。在過去,大部分深度神經(jīng)網(wǎng)絡(luò)模型都是基于卷積神經(jīng)網(wǎng)絡(luò)(CNN)進(jìn)行設(shè)計(jì)的,這些模型往往非常龐大(比如VGG16/VGG19),因此不能直接應(yīng)用于手機(jī)或其他嵌入式設(shè)備上。同時(shí),運(yùn)行這些大型模型所需要的計(jì)算資源也很昂貴。
????????為了解決這個(gè)問題,Google Brain團(tuán)隊(duì)提出了Mobilenetv1。Mobilenetv1是基于深度可分離卷積(depthwise separable convolution)的設(shè)計(jì),它將標(biāo)準(zhǔn)的卷積層分成深度卷積層和逐點(diǎn)卷積層兩個(gè)部分,用較少的參數(shù)和計(jì)算量達(dá)到了相當(dāng)不錯(cuò)的準(zhǔn)確率。具體來說,深度卷積層用于在每個(gè)通道上執(zhí)行空間卷積,而逐點(diǎn)卷積層(Pointwise Convolution)用于在不同通道之間執(zhí)行線性變換。這種設(shè)計(jì)可以減少計(jì)算量和模型大小,并使得Mobilenetv1在移動(dòng)設(shè)備上能夠運(yùn)行得更快。
????????除此之外,Mobilenetv1還使用了其他一些技巧來進(jìn)一步縮小模型。例如,通過擴(kuò)張系數(shù)(expansion factor)來控制輸出通道數(shù)和輸入通道數(shù)之間的關(guān)系,從而精細(xì)控制模型的大小和復(fù)雜度;通過殘差連接(Residual Connection)來提高信息流動(dòng),從而提高模型的準(zhǔn)確性和訓(xùn)練速度。
????????綜合來說,Mobilenetv1是一種非常出色的深度神經(jīng)網(wǎng)絡(luò)模型,它在保持較高精確度的同時(shí),大大減小了模型大小和計(jì)算量,使得它更容易嵌入到移動(dòng)和嵌入式設(shè)備中。
MobileNetV1的主要特點(diǎn)如下:
-
輕量級:MobileNetv1的模型參數(shù)量非常少,只有4.2M,比起其他深度神經(jīng)網(wǎng)絡(luò)模型如VGG16、ResNet等模型,模型大小大大減小,更適合移動(dòng)設(shè)備等資源受限環(huán)境下進(jìn)行應(yīng)用。
-
深度可分離卷積:MobileNetv1主要使用了深度可分離卷積,即將標(biāo)準(zhǔn)卷積分解成一個(gè)深度卷積和一個(gè)逐點(diǎn)卷積兩個(gè)部分,分離后分別進(jìn)行卷積操作,可以大大減少計(jì)算量和參數(shù)數(shù)量,從而實(shí)現(xiàn)輕量化的目的。
-
使用卷積核大小為1x1的卷積層和全局平均池化層:MobileNetv1使用了大量的1x1卷積層和全局平均池化層來代替?zhèn)鹘y(tǒng)的卷積層,可以減少特征圖的空間尺寸,從而減少計(jì)算量和參數(shù)數(shù)量。
-
加入線性層和ReLU6激活函數(shù):為了減少梯度消失的現(xiàn)象,MobileNetv1在每個(gè)深度可分離卷積結(jié)構(gòu)后加入一個(gè)線性層和ReLU6激活函數(shù),同時(shí)提高模型的非線性能力。
-
高性能:MobileNetv1在性能表現(xiàn)方面也做得很好,準(zhǔn)確率達(dá)到了當(dāng)時(shí)的state-of-the-art水平,同時(shí)模型具有高效率的特點(diǎn),能夠在較短的時(shí)間內(nèi)完成較為復(fù)雜的任務(wù)。
MobileNetV1的創(chuàng)新點(diǎn):
- Depthwise Separable Convolution(深度可分離卷積)
????????MobileNetV1使用Depthwise Separable Convolution代替了傳統(tǒng)的卷積操作。Depthwise Separable Convolution分為兩個(gè)步驟,首先進(jìn)行深度卷積,然后進(jìn)行點(diǎn)卷積。深度卷積可以在每個(gè)輸入通道上進(jìn)行濾波操作,而點(diǎn)卷積使用1×1卷積來對每個(gè)通道進(jìn)行線性組合。這樣可以減少運(yùn)算量以及減小模型的大小,同時(shí)也可以提高模型的精度和魯棒性。
? ? ?2. Width Multiplier(寬度乘法參數(shù))
????????MobileNetV1引入了width multiplier的概念,可以通過調(diào)整寬度乘數(shù)來控制模型的大小和計(jì)算量。寬度乘數(shù)是作用于每一層的通道數(shù)目,可以取0到1的任意值。當(dāng)寬度乘數(shù)為1時(shí),模型與原始模型一致,而當(dāng)寬度乘數(shù)小于1時(shí),模型會(huì)變得更輕巧。
? ? ?3. Global Depthwise Pooling(全局深度池化)
????????MobileNetV1使用Global Depthwise Pooling代替了全連接層。全局深度池化是在每個(gè)通道上進(jìn)行求和操作,并將結(jié)果作為輸出。這樣可以有效地減少模型的參數(shù)量和計(jì)算量,提高模型的速度和精度。
????????總的來說,MobileNetV1在模型輕量化方面具有顯著的創(chuàng)新,可以在計(jì)算資源有限的設(shè)備上進(jìn)行高效的推理操作,成為了移動(dòng)設(shè)備上的高效神經(jīng)網(wǎng)絡(luò)模型。
MobileNetV1源碼(torch版)
數(shù)據(jù)集運(yùn)行代碼時(shí)自動(dòng)下載,如果網(wǎng)絡(luò)比較慢,可以自行點(diǎn)擊我分享的鏈接下載cifar數(shù)據(jù)集。
鏈接:百度網(wǎng)盤
提取碼:kd9a?
# -*- coding: utf-8 -*-
import torch
import torch.nn as nn
from torch.utils.data import DataLoader
from torchvision.datasets import CIFAR10
from torchvision.transforms import transforms
from torch.autograd import Variable
class DepthwiseSeparableConv(nn.Module):
def __init__(self, in_channels, out_channels):
super(DepthwiseSeparableConv, self).__init__()
self.depthwise_conv = nn.Conv2d(in_channels, in_channels, kernel_size=3, padding=1, groups=in_channels)
self.pointwise_conv = nn.Conv2d(in_channels, out_channels, kernel_size=1)
self.relu = nn.ReLU(inplace=True)
def forward(self, x):
x = self.depthwise_conv(x)
x = self.pointwise_conv(x)
x = self.relu(x)
return x
class MobileNetV1(nn.Module):
def __init__(self, num_classes=1000):
super(MobileNetV1, self).__init__()
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=2, padding=1)
self.relu = nn.ReLU(inplace=True)
self.dw_separable_conv1 = DepthwiseSeparableConv(32, 64)
self.dw_separable_conv2 = DepthwiseSeparableConv(64, 128)
self.dw_separable_conv3 = DepthwiseSeparableConv(128, 128)
self.dw_separable_conv4 = DepthwiseSeparableConv(128, 256)
self.dw_separable_conv5 = DepthwiseSeparableConv(256, 256)
self.dw_separable_conv6 = DepthwiseSeparableConv(256, 512)
self.dw_separable_conv7 = DepthwiseSeparableConv(512, 512)
self.dw_separable_conv8 = DepthwiseSeparableConv(512, 512)
self.dw_separable_conv9 = DepthwiseSeparableConv(512, 512)
self.dw_separable_conv10 = DepthwiseSeparableConv(512, 512)
self.dw_separable_conv11 = DepthwiseSeparableConv(512, 512)
self.dw_separable_conv12 = DepthwiseSeparableConv(512, 1024)
self.dw_separable_conv13 = DepthwiseSeparableConv(1024, 1024)
self.avg_pool = nn.AdaptiveAvgPool2d((1, 1))
self.fc = nn.Linear(1024, num_classes)
def forward(self, x):
x = self.conv1(x)
x = self.relu(x)
x = self.dw_separable_conv1(x)
x = self.dw_separable_conv2(x)
x = self.dw_separable_conv3(x)
x = self.dw_separable_conv4(x)
x = self.dw_separable_conv5(x)
x = self.dw_separable_conv6(x)
x = self.dw_separable_conv7(x)
x = self.dw_separable_conv8(x)
x = self.dw_separable_conv9(x)
x = self.dw_separable_conv10(x)
x = self.dw_separable_conv11(x)
x = self.dw_separable_conv12(x)
x = self.dw_separable_conv13(x)
x = self.avg_pool(x)
x = torch.flatten(x, 1)
x = self.fc(x)
return x
def main():
train_data = CIFAR10('cifar',train=True,transform = transforms.ToTensor())
data = DataLoader(train_data,batch_size=128,shuffle=True)
device = torch.device("cuda")
net = MobileNetV1(num_classes=10).to(device)
print(net)
cross = nn.CrossEntropyLoss().to(device)
optimizer = torch.optim.Adam(net.parameters(),0.001)
for epoch in range(10):
for img,label in data:
img = Variable(img).to(device)
label = Variable(label).to(device)
output = net.forward(img)
loss = cross(output,label)
loss.backward()
optimizer.zero_grad()
optimizer.step()
pre = torch.argmax(output,1)
num = (pre == label).sum().item()
acc = num / img.shape[0]
print("epoch:",epoch + 1)
print("loss:",loss.item())
print("acc:",acc)
pass
if __name__ == '__main__':
main()
????????上述代碼中,我使用的是CIFAR-10數(shù)據(jù)集,通過訓(xùn)練MobileNet V1對圖像進(jìn)行分類。在訓(xùn)練過程中,我使用Adam優(yōu)化器和交叉熵?fù)p失函數(shù),并在訓(xùn)練后使用驗(yàn)證集評估模型的性能。
????????其中,模型中使用了Depthwise Separable Convolution,它包含一層深度卷積和一層1x1卷積。深度卷積用于處理輸入數(shù)據(jù)的不同通道,1x1卷積用于將不同通道的特征圖合并成更多的通道。這個(gè)操作可以有效地減少參數(shù)數(shù)量和計(jì)算量,并提高模型的性能。
????????另外,模型還使用了AdaptiveAvgPool2d,該層可以自適應(yīng)地將輸入特征圖的大小調(diào)整為任意大小,并對每個(gè)子區(qū)域進(jìn)行平均池化操作。這可以使模型對輸入圖像的尺寸具有更強(qiáng)的魯棒性。
????????通過MobileNet V1,我們可以在保持較高精度的同時(shí)具有較少的參數(shù)量和計(jì)算時(shí)間,在計(jì)算資源受限的情況下尤其有用。文章來源:http://www.zghlxwxcb.cn/news/detail-418184.html
訓(xùn)練10個(gè)epoch的效果
文章來源地址http://www.zghlxwxcb.cn/news/detail-418184.html
到了這里,關(guān)于MobileNetV1詳細(xì)原理(含torch源碼)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!