<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)重初始化

          共 5730字,需瀏覽 12分鐘

           ·

          2020-09-17 05:43

          文章目錄:

          • 1 模型三要素

          • 2 參數(shù)初始化

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

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

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

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

          1 模型三要素

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

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

          我們來看一個(gè)例子:先看__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)備

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

          例如:

          net?=?Net()
          outputs?=?net(inputs)

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

          2 參數(shù)初始化

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

          話不多說,看一個(gè)案例:

          #?定義權(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初始化,是何愷明大佬在微軟亞洲研究院的時(shí)候,因此得名。

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

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

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

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

          我們用下面的例子來更深入的理解self.modules(),同時(shí)也把上面的內(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(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)

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

          #?這個(gè)是print(net.modules())的輸出
          0x0000023BDCA23258>
          #?這個(gè)是第一次從net.modules()取出來的東西,是整個(gè)網(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 尺寸計(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(3,?6,?kernel_size=(5,?5),?stride=(1,?1))

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

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

          之前的文章也講過這個(gè)了,

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

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

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

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

          【問題2:這個(gè)卷積層中有多少的參數(shù)?】輸入通道是3通道的,輸出是6通道的,卷積核是的,所以理解為6個(gè)的卷積核,所以不考慮bias的話,參數(shù)量是,考慮bais的話,就每一個(gè)卷積核再增加一個(gè)偏置值。(這是一個(gè)一般人會(huì)忽略的知識點(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(3,?6,?kernel_size=(5,?5),?stride=(1,?1))
          torch.Size([6,?3,?5,?5])
          torch.Size([6])

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

          - END -


          往期精彩回顧





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

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

          本站qq群1003271085。

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

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

          手機(jī)掃一掃分享

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

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  18禁免费看片 | 俺来也俺去也 | 亚洲色鬼 | 蜜乳影视| 免费黄色小视频网站 |