<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          【小白學(xué)PyTorch】11.MobileNet詳解及PyTorch實現(xiàn)

          共 4573字,需瀏覽 10分鐘

           ·

          2020-09-24 16:46

          <<小白學(xué)PyTorch>>

          小白學(xué)PyTorch | 10 pytorch常見運算詳解

          小白學(xué)PyTorch | 9 tensor數(shù)據(jù)結(jié)構(gòu)與存儲結(jié)構(gòu)

          小白學(xué)PyTorch | 8 實戰(zhàn)之MNIST小試牛刀

          小白學(xué)PyTorch | 7 最新版本torchvision.transforms常用API翻譯與講解

          小白學(xué)PyTorch | 6 模型的構(gòu)建訪問遍歷存儲(附代碼)

          小白學(xué)PyTorch | 5 torchvision預(yù)訓(xùn)練模型與數(shù)據(jù)集全覽

          小白學(xué)PyTorch | 4 構(gòu)建模型三要素與權(quán)重初始化

          小白學(xué)PyTorch | 3 淺談Dataset和Dataloader

          小白學(xué)PyTorch | 2 淺談訓(xùn)練集驗證集和測試集

          小白學(xué)PyTorch | 1 搭建一個超簡單的網(wǎng)絡(luò)

          小白學(xué)PyTorch | 動態(tài)圖與靜態(tài)圖的淺顯理解


          參考目錄:

          • 1 背景

          • 2 深度可分離卷積

            • 2.2 一般卷積計算量

            • 2.2 深度可分離卷積計算量

            • 2.3 網(wǎng)絡(luò)結(jié)構(gòu)

          • 3 PyTorch實現(xiàn)


          本來計劃是想在今天講EfficientNet PyTorch的,但是發(fā)現(xiàn)EfficientNet是依賴于SENet和MobileNet兩個網(wǎng)絡(luò)結(jié)構(gòu),所以本著本系列是給“小白”初學(xué)者學(xué)習(xí)的,所以這一課先講解MobileNet,然后下一課講解SENet,然后再下一課講解EfficientNet,當(dāng)然,每一節(jié)課都是由PyTorch實現(xiàn)的。

          這個系列《小白學(xué)PyTorch》的所有代碼和數(shù)據(jù)集放在了公眾號【機(jī)器學(xué)習(xí)煉丹術(shù)】后臺,回復(fù)【pytorch】獲取(還在更新的呢):

          當(dāng)然有什么問題、有事沒事都可以找煉丹兄交流哈哈,煉丹兄就是一個非Top學(xué)校的跨專業(yè)應(yīng)屆研究生。

          ↑↑↑掃碼加煉丹兄好友↑↑↑

          1 背景

          Mobile是移動、手機(jī)的概念,MobileNet是Google在2017年提出的輕量級深度神經(jīng)網(wǎng)絡(luò),專門用于移動端、嵌入式這種計算力不高、要求速度、實時性的設(shè)備。

          2 深度可分離卷積

          主要應(yīng)用了深度可分離卷積來代替?zhèn)鹘y(tǒng)的卷積操作,并且放棄pooling層。把標(biāo)準(zhǔn)卷積分解成:

          • 深度卷積(depthwise convolution)
          • 逐點卷積(pointwise convolution)。這么做的好處是可以大幅度降低參數(shù)量和計算量。

          2.2 一般卷積計算量

          我們先來回顧一下什么是一般的卷積:先說一下題目:特征圖尺寸是H(高)和W(寬),尺寸(邊長)為K,M是輸入特征圖的通道數(shù),N是輸出特征圖的通道數(shù)。

          現(xiàn)在簡化問題,如上圖所示,輸入單通道特征圖,輸出特征圖也是單通道的, 我們知道每一個卷積結(jié)果為一個標(biāo)量,從輸出特征圖來看,總共進(jìn)行了9次卷積。每一次卷積計算了9次,因為每一次卷積都需要讓卷積核上的每一個數(shù)字與原來特征圖上對應(yīng)的數(shù)字相乘(這里只算乘法不用考慮加法)。所以圖6.18所示,總共計算了:

          如果輸入特征圖是一個2通道的 ,那么意味著卷積核也是要2通道的卷積核才行,此時輸出特征圖還是單通道的。這樣計算量就變成:

          原本單通道特征圖每一次卷積只用計算9次乘法,現(xiàn)在因為輸入通道數(shù)變成2,要計算18次乘法才能得到輸出中的1個數(shù)字。現(xiàn)在假設(shè)輸出特征圖要輸出3通道的特征圖。 那么就要準(zhǔn)備3個不同的卷積核,重復(fù)上述全部操作3次才能拿的到3個特征圖。所以計算量就是:

          現(xiàn)在解決原來的問題:特征圖尺寸是H(高)和W(寬),卷積核是正方形的,尺寸(邊長)為K,M是輸入特征圖的通道數(shù),N是輸出特征圖的通道數(shù)。 那么這樣卷積的計算量為:

          這個就是卷積的計算量的公式。

          2.2 深度可分離卷積計算量

          • 深度可分離卷積(Depthwise Separable Convolution,DSC)

          假設(shè)在一次一般的卷積中,需要將一個輸入特征圖64×7×7,經(jīng)過3×3的卷積核,變成128×7×7的輸出特征圖。計算一下這個過程需要多少的計算量:

          如果用了深度可分離卷積,就是把這個卷積變成兩個步驟:

          1. Depthwise:先用64×7×7經(jīng)過3×3的卷積核得到一個64×7×7的特征圖。注意注意!這里是64×7×7的特征圖經(jīng)過3×3的卷積核,不是64×3×3的卷積核!這里將64×7×7的特征圖看成64張7×7的圖片,然后依次與3×3的卷積核進(jìn)行卷積;
          2. Pointwise:在Depthwise的操作中,不難發(fā)現(xiàn),這樣的計算根本無法整合不同通道的信息,因為上一步把所有通道都拆開了,所以在這一步要用64×1×1的卷積核去整合不同通道上的信息,用128個64×1×1的卷積核,產(chǎn)生128×7×7的特征圖。

          最后的計算量就是:

          計算量減少了百分之80以上。

          分解過程示意圖如下:

          在圖中可以看到:

          • (a)表示一般卷積過程, 卷積核都是M個通道,然后總共有N和卷積核,意味著輸入特征圖有M個通道,然后輸出特征圖有N個通道。
          • (b)表示depthwise過程, 總共有M個卷積核,這里是對輸入特征圖的M個通道分別做一個卷積,輸出的特征圖也是M個通道的;
          • (c)表示pointwise過程,總共有N個的卷積核,這樣來整合不同通道的信息,輸出特征圖有N個通道數(shù)。

          2.3 網(wǎng)絡(luò)結(jié)構(gòu)

          左圖表示的是一般卷積過程,卷積之后跟上BN和ReLU激活層,因為DBC將分成了兩個卷積過程,所以就變成了圖右這種結(jié)構(gòu),Depthwise之后加上BN和ReLU,然后Pointwise之后再加上Bn和ReLU。

          從整個網(wǎng)絡(luò)結(jié)構(gòu)可以看出來:

          • 除了第一層為標(biāo)準(zhǔn)的卷積層之外,其他的層都為深度可分離卷積。
          • 整個網(wǎng)絡(luò)沒有使用Pooling層。

          3 PyTorch實現(xiàn)

          import?torch
          import?torch.nn?as?nn
          import?torch.nn.functional?as?F


          class?Block(nn.Module):
          ????'''Depthwise?conv?+?Pointwise?conv'''
          ????def?__init__(self,?in_planes,?out_planes,?stride=1):
          ????????super(Block,?self).__init__()
          ????????self.conv1?=?nn.Conv2d\
          ????????????(in_planes,?in_planes,?kernel_size=3,?stride=stride,?
          ?????????????padding=1,?groups=in_planes,?bias=False)
          ????????self.bn1?=?nn.BatchNorm2d(in_planes)
          ????????self.conv2?=?nn.Conv2d\
          ????????????(in_planes,?out_planes,?kernel_size=1,?
          ????????????stride=1,?padding=0,?bias=False)
          ????????self.bn2?=?nn.BatchNorm2d(out_planes)

          ????def?forward(self,?x):
          ????????out?=?F.relu(self.bn1(self.conv1(x)))
          ????????out?=?F.relu(self.bn2(self.conv2(out)))
          ????????return?out


          class?MobileNet(nn.Module):
          ????#?(128,2)?means?conv?planes=128,?conv?stride=2,?
          ????#?by?default?conv?stride=1
          ????cfg?=?[64,?(128,2),?128,?(256,2),?256,?(512,2),?
          ???????????512,?512,?512,?512,?512,?(1024,2),?1024]

          ????def?__init__(self,?num_classes=10):
          ????????super(MobileNet,?self).__init__()
          ????????self.conv1?=?nn.Conv2d(3,?32,?kernel_size=3,?
          ?????????stride=1,?padding=1,?bias=False)
          ????????self.bn1?=?nn.BatchNorm2d(32)
          ????????self.layers?=?self._make_layers(in_planes=32)
          ????????self.linear?=?nn.Linear(1024,?num_classes)

          ????def?_make_layers(self,?in_planes):
          ????????layers?=?[]
          ????????for?x?in?self.cfg:
          ????????????out_planes?=?x?if?isinstance(x,?int)?else?x[0]
          ????????????stride?=?1?if?isinstance(x,?int)?else?x[1]
          ????????????layers.append(Block(in_planes,?out_planes,?stride))
          ????????????in_planes?=?out_planes
          ????????return?nn.Sequential(*layers)

          ????def?forward(self,?x):
          ????????out?=?F.relu(self.bn1(self.conv1(x)))
          ????????out?=?self.layers(out)
          ????????out?=?F.avg_pool2d(out,?2)
          ????????out?=?out.view(out.size(0),?-1)
          ????????out?=?self.linear(out)
          ????????return?out

          net?=?MobileNet()
          x?=?torch.randn(1,3,32,32)
          y?=?net(x)
          print(y.size())
          >?torch.Size([1,?10])

          正常情況下這個預(yù)訓(xùn)練模型都會輸出1024個線性節(jié)點,然后這里我自己加上了一個1024->10的一個全連接層。

          我們來看一下這個網(wǎng)絡(luò)結(jié)構(gòu):

          print(net)

          輸出結(jié)果:

          然后代碼中:

          關(guān)于模型通道數(shù)的設(shè)置部分:

          MobileNet就差不多完事了,下一節(jié)課為SENet的PyTorch實現(xiàn)和詳解。

          - END -



          往期精彩回顧





          獲取一折本站知識星球優(yōu)惠券,復(fù)制鏈接直接打開:

          https://t.zsxq.com/662nyZF

          本站qq群704220115。

          加入微信群請掃碼進(jìn)群(如果是博士或者準(zhǔn)備讀博士請說明):

          瀏覽 73
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美色视频在线 | 成人黄色电影在线 | 99精品免费在线 | 18岁高清无码 | 成人激情五月 |