<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】4.構(gòu)建模型三要素與權(quán)重初始化

          共 9542字,需瀏覽 20分鐘

           ·

          2021-09-03 14:54

          點(diǎn)擊上方小白學(xué)視覺”,選擇加"星標(biāo)"或“置頂

          重磅干貨,第一時間送達(dá)

          文章目錄:

          • 1 模型三要素

          • 2 參數(shù)初始化

          • 3 完整運(yùn)行代碼

          • 4 尺寸計(jì)算與參數(shù)計(jì)算

          這篇文章內(nèi)容不多,比較基礎(chǔ),里面的代碼塊可以復(fù)制到本地進(jìn)行實(shí)踐,以加深理解。

          喜歡的話,可以給公眾號加一個星標(biāo),點(diǎn)點(diǎn)在看,這是對我最大的支持


          1 模型三要素


          三要素其實(shí)很簡單

          1. 必須要繼承nn.Module這個類,要讓PyTorch知道這個類是一個Module
          2. 在__init__(self)中設(shè)置好需要的組件,比如conv,pooling,Linear,BatchNorm等等
          3. 最后在forward(self,x)中用定義好的組件進(jìn)行組裝,就像搭積木,把網(wǎng)絡(luò)結(jié)構(gòu)搭建出來,這樣一個模型就定義好了

          我們來看一個例子:先看__init__(self)函數(shù)

          def __init__(self):
           super(Net,self).__init__()
           self.conv1 = nn.Conv2d(3,6,5)
           self.pool1 = nn.MaxPool2d(2,2)
           self.conv2 = nn.Conv2d(6,16,5)
           self.pool2 = nn.MaxPool2d(2,2)
           self.fc1 = nn.Linear(16*5*5,120)
           self.fc2 = nn.Linear(120,84)
           self.fc3 = nn.Linear(84,10)

          第一行是初始化,往后定義了一系列組件。nn.Conv2d就是一般圖片處理的卷積模塊,然后池化層,全連接層等等。

          定義完這些定義forward函數(shù)

          def forward(self,x):
           x = self.pool1(F.relu(self.conv1(x)))
           x = self.pool2(F.relu(self.conv2(x)))
           x = x.view(-1,16*5*5)
           x = F.relu(self.fc1(x))
           x = F.relu(self.fc2(x))
           x = self.fc3(x)
           return x

          x為模型的輸入,第一行表示x經(jīng)過conv1,然后經(jīng)過激活函數(shù)relu,然后經(jīng)過pool1操作 第三行表示對x進(jìn)行reshape,為后面的全連接層做準(zhǔn)備

          至此,對一個模型的定義完畢,如何使用呢?

          例如:

          net = Net()
          outputs = net(inputs)

          其實(shí)net(inputs),就是類似于使用了net.forward(inputs)這個函數(shù)。


          2 參數(shù)初始化


          簡單地說就是設(shè)定什么層用什么初始方法,初始化的方法會在torch.nn.init中

          話不多說,看一個案例:

          # 定義權(quán)值初始化
          def initialize_weights(self):
           for m in self.modules():
            if isinstance(m,nn.Conv2d):
             torch.nn.init.xavier_normal_(m.weight.data)
             if m.bias is not None:
              m.bias.data.zero_()
            elif isinstance(m,nn.BatchNorm2d):
             m.weight.data.fill_(1)
             m.bias.data.zero_()
            elif isinstance(m,nn.Linear):
             torch.nn.init.normal_(m.weight.data,0,0.01)
             # m.weight.data.normal_(0,0.01)
             m.bias.data.zero_()

          這段代碼的基本流程就是,先從self.modules()中遍歷每一層,然后判斷更曾屬于什么類型,是否是Conv2d,是否是BatchNorm2d,是否是Linear的,然后根據(jù)不同類型的層,設(shè)定不同的權(quán)值初始化方法,例如Xavier,kaiming,normal_等等。kaiming也是MSRA初始化,是何愷明大佬在微軟亞洲研究院的時候,因此得名。

          上面代碼中用到了self.modules(),這個是什么東西呢?

          # self.modules的源碼
          def modules(self):
           for name,module in self.named_modules():
            yield module

          功能就是:能依次返回模型中的各層,yield是讓一個函數(shù)可以像迭代器一樣可以用for循環(huán)不斷從里面遍歷(可能說的不太明確)。


          3 完整運(yùn)行代碼


          我們用下面的例子來更深入的理解self.modules(),同時也把上面的內(nèi)容都串起來(下面的代碼塊可以運(yùn)行):

          import torch
          import torch.nn as nn
          import torch.nn.functional as F
          from torch.utils.data import Dataset,DataLoader

          class Net(nn.Module):
              def __init__(self):
                  super(Net, self).__init__()
                  self.conv1 = nn.Conv2d(365)
                  self.pool1 = nn.MaxPool2d(22)
                  self.conv2 = nn.Conv2d(6165)
                  self.pool2 = nn.MaxPool2d(22)
                  self.fc1 = nn.Linear(16 * 5 * 5120)
                  self.fc2 = nn.Linear(12084)
                  self.fc3 = nn.Linear(8410)

              def forward(self, x):
                  x = self.pool1(F.relu(self.conv1(x)))
                  x = self.pool2(F.relu(self.conv2(x)))
                  x = x.view(-116 * 5 * 5)
                  x = F.relu(self.fc1(x))
                  x = F.relu(self.fc2(x))
                  x = self.fc3(x)
                  return x

              def initialize_weights(self):
                  for m in self.modules():
                      if isinstance(m, nn.Conv2d):
                          torch.nn.init.xavier_normal_(m.weight.data)
                          if m.bias is not None:
                              m.bias.data.zero_()
                      elif isinstance(m, nn.BatchNorm2d):
                          m.weight.data.fill_(1)
                          m.bias.data.zero_()
                      elif isinstance(m, nn.Linear):
                          torch.nn.init.normal_(m.weight.data, 00.01)
                          # m.weight.data.normal_(0,0.01)
                          m.bias.data.zero_()

          net = Net()
          net.initialize_weights()
          print(net.modules())
          for m in net.modules():
              print(m)

          運(yùn)行結(jié)果:

          # 這個是print(net.modules())的輸出
          <generator object Module.modules at 0x0000023BDCA23258>
          # 這個是第一次從net.modules()取出來的東西,是整個網(wǎng)絡(luò)的結(jié)構(gòu)
          Net(
            (conv1): Conv2d(36, kernel_size=(55), stride=(11))
            (pool1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
            (conv2): Conv2d(616, kernel_size=(55), stride=(11))
            (pool2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
            (fc1): Linear(in_features=400, out_features=120, bias=True)
            (fc2): Linear(in_features=120, out_features=84, bias=True)
            (fc3): Linear(in_features=84, out_features=10, bias=True)
          )
          # 從net.modules()第二次開始取得東西就是每一層了
          Conv2d(36, kernel_size=(55), stride=(11))
          MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
          Conv2d(616, kernel_size=(55), stride=(11))
          MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
          Linear(in_features=400, out_features=120, bias=True)
          Linear(in_features=120, out_features=84, bias=True)
          Linear(in_features=84, out_features=10, bias=True)

          其中呢,并不是每一層都有偏執(zhí)bias的,有的卷積層可以設(shè)置成不要bias的,所以對于卷積網(wǎng)絡(luò)參數(shù)的初始化,需要判斷一下是否有bias,(不過我好像記得bias默認(rèn)初始化為0?不確定,有知道的朋友可以交流)

          torch.nn.init.xavier_normal(m.weight.data)
          if m.bias is not None:
           m.bias.data.zero_()

          上面代碼表示用xavier_normal方法對該層的weight初始化,并判斷是否存在偏執(zhí)bias,若存在,將bias初始化為0。


          4 尺寸計(jì)算與參數(shù)計(jì)算


          我們把上面的主函數(shù)部分改成:

          net = Net()
          net.initialize_weights()
          layers = {}
          for m in net.modules():
              if isinstance(m,nn.Conv2d):
                  print(m)
                  break

          這里的輸出m就是:

          Conv2d(36, kernel_size=(55), stride=(11))

          這個卷積層,就是我們設(shè)置的第一個卷積層,含義就是:輸入3通道,輸出6通道,卷積核,步長1,padding=0.

          【問題1:輸入特征圖和輸出特征圖的尺寸計(jì)算】

          之前的文章也講過這個了,

          用代碼來驗(yàn)證一下這個公式:

          net = Net()
          net.initialize_weights()
          input = torch.ones((16,3,10,10))
          output = net.conv1(input)
          print(input.shape)
          print(output.shape)

          初始結(jié)果:

          torch.Size([1631010])
          torch.Size([16666])

          第一個維度上batch,第二個是通道channel,第三個和第四個是圖片(特征圖)的尺寸。

          算出來的結(jié)果沒毛病。

          【問題2:這個卷積層中有多少的參數(shù)?】輸入通道是3通道的,輸出是6通道的,卷積核是的,所以理解為6個的卷積核,所以不考慮bias的話,參數(shù)量是,考慮bais的話,就每一個卷積核再增加一個偏置值。(這是一個一般人會忽略的知識點(diǎn)欸)

          下面用代碼來驗(yàn)證:

          net = Net()
          net.initialize_weights()
          for m in net.modules():
              if isinstance(m,nn.Conv2d):
                  print(m)
                  print(m.weight.shape)
                  print(m.bias.shape)
                  break

          輸出結(jié)果是:

          Conv2d(36, kernel_size=(55), stride=(11))
          torch.Size([6355])
          torch.Size([6])

          都和預(yù)料中一樣。

          下載1:OpenCV-Contrib擴(kuò)展模塊中文版教程
          在「小白學(xué)視覺」公眾號后臺回復(fù):擴(kuò)展模塊中文教程即可下載全網(wǎng)第一份OpenCV擴(kuò)展模塊教程中文版,涵蓋擴(kuò)展模塊安裝、SFM算法、立體視覺、目標(biāo)跟蹤、生物視覺、超分辨率處理等二十多章內(nèi)容。

          下載2:Python視覺實(shí)戰(zhàn)項(xiàng)目52講
          小白學(xué)視覺公眾號后臺回復(fù):Python視覺實(shí)戰(zhàn)項(xiàng)目即可下載包括圖像分割、口罩檢測、車道線檢測、車輛計(jì)數(shù)、添加眼線、車牌識別、字符識別、情緒檢測、文本內(nèi)容提取、面部識別等31個視覺實(shí)戰(zhàn)項(xiàng)目,助力快速學(xué)校計(jì)算機(jī)視覺。

          下載3:OpenCV實(shí)戰(zhàn)項(xiàng)目20講
          小白學(xué)視覺公眾號后臺回復(fù):OpenCV實(shí)戰(zhàn)項(xiàng)目20講即可下載含有20個基于OpenCV實(shí)現(xiàn)20個實(shí)戰(zhàn)項(xiàng)目,實(shí)現(xiàn)OpenCV學(xué)習(xí)進(jìn)階。

          交流群


          歡迎加入公眾號讀者群一起和同行交流,目前有SLAM、三維視覺、傳感器自動駕駛、計(jì)算攝影、檢測、分割、識別、醫(yī)學(xué)影像、GAN算法競賽等微信群(以后會逐漸細(xì)分),請掃描下面微信號加群,備注:”昵稱+學(xué)校/公司+研究方向“,例如:”張三 + 上海交大 + 視覺SLAM“。請按照格式備注,否則不予通過。添加成功后會根據(jù)研究方向邀請進(jìn)入相關(guān)微信群。請勿在群內(nèi)發(fā)送廣告,否則會請出群,謝謝理解~


          瀏覽 39
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(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>
                  成人在线日本 | 中文字幕在线观看免费视频 | 中文字幕日韩无码一区 | 干欧美老女人 | 东京热成人AV无码 |