乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

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

       520jefferson 2021-01-13

      文章目錄:

      • 1 模型三要素

      • 2 參數(shù)初始化

      • 3 完整運行代碼

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

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

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

      1 模型三要素

      三要素其實很簡單

      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)

      其實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 完整運行代碼

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

      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(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)

          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

          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_()

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

      運行結(jié)果:

      # 這個是print(net.modules())的輸出
      <generator object Module.modules at 0x0000023BDCA23258>
      # 這個是第一次從net.modules()取出來的東西,是整個網(wǎng)絡(luò)的結(jié)構(gòu)
      Net(
        (conv1): Conv2d(3, 6, kernel_size=(5, 5), stride=(1, 1))
        (pool1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
        (conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
        (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(3, 6, kernel_size=(5, 5), stride=(1, 1))
      MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
      Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
      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 尺寸計算與參數(shù)計算

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

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

      這里的輸出m就是:

      Conv2d(3, 6, kernel_size=(5, 5), stride=(1, 1))

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

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

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

      用代碼來驗證一下這個公式:

      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([16, 3, 10, 10])
      torch.Size([16, 6, 6, 6])

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

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

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

      下面用代碼來驗證:

      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(3, 6, kernel_size=(5, 5), stride=(1, 1))
      torch.Size([6, 3, 5, 5])
      torch.Size([6])

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多