<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】6.模型的構(gòu)建訪問遍歷存儲(附代碼)

          共 6748字,需瀏覽 14分鐘

           ·

          2020-09-19 11:58

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

          小白學(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 模型構(gòu)建函數(shù)

            • 1.1 add_module

            • 1.2 ModuleList

            • 1.3 Sequential

            • 1.4 小總結(jié)

          • 2 遍歷模型結(jié)構(gòu)

            • 2.1 modules()

            • 2.2 named_modules()

            • 2.3 parameters()

          • 3 保存與載入

          本文是對一些函數(shù)的學(xué)習(xí)。函數(shù)主要包括下面四個方便:

          • 模型構(gòu)建的函數(shù):add_module,add_module,add_module
          • 訪問子模塊:add_module,add_module,add_moduleadd_module
          • 網(wǎng)絡(luò)遍歷:add_module,add_module
          • 模型的保存與加載:add_module,add_module,add_module

          1 模型構(gòu)建函數(shù)

          torch.nn.Module是所有網(wǎng)絡(luò)的基類,在PyTorch實現(xiàn)模型的類中都要繼承這個類(這個在之前的課程中已經(jīng)提到)。在構(gòu)建Module中,Module是一個包含其他的Module的,類似于,你可以先定義一個小的網(wǎng)絡(luò)模塊,然后把這個小模塊作為另外一個網(wǎng)絡(luò)的組件。因此網(wǎng)絡(luò)結(jié)構(gòu)是呈現(xiàn)樹狀結(jié)構(gòu)

          我們先簡單定義一個網(wǎng)絡(luò):

          import?torch.nn?as?nn
          import?torch?
          class?MyNet(nn.Module):
          ????def?__init__(self):
          ????????super(MyNet,self).__init__()
          ????????self.conv1?=?nn.Conv2d(3,64,3)
          ????????self.conv2?=?nn.Conv2d(64,64,3)

          ????def?forward(self,x):
          ????????x?=?self.conv1(x)
          ????????x?=?self.conv2(x)
          ????????return?x
          net?=?MyNet()
          print(net)

          輸出結(jié)果:MyNet中有兩個屬性conv1conv2是兩個卷積層,在正向傳播forward的過程中,依次調(diào)用這兩個卷積層實現(xiàn)網(wǎng)絡(luò)的功能。

          1.1 add_module

          這種是最常見的定義網(wǎng)絡(luò)的功能,在有些項目中,會看到這樣的方法add_module。我們用這個方法來重寫上面的網(wǎng)絡(luò):

          class?MyNet(nn.Module):
          ????def?__init__(self):
          ????????super(MyNet,self).__init__()
          ????????self.add_module('conv1',nn.Conv2d(3,64,3))
          ????????self.add_module('conv2',nn.Conv2d(64,64,3))

          ????def?forward(self,x):
          ????????x?=?self.conv1(x)
          ????????x?=?self.conv2(x)
          ????????return?x

          其實add_module(name,layer)self.name=layer實現(xiàn)了相同的功能,個人感覺也許是因為add_module可以使用字符串來定義變量名字,所以可以放在循環(huán)中?反正這個先了解熟悉熟悉

          上面的兩種方法都是一層一層的添加layer,如果網(wǎng)絡(luò)復(fù)雜的話,那就需要寫很多重復(fù)的代碼了。因此接下來來講解一下網(wǎng)絡(luò)模塊的構(gòu)建,torch.nn.ModuleListtorch.nn.Sequential

          1.2 ModuleList

          ModuleList按照字面意思是用list的形式保存網(wǎng)絡(luò)層的。這樣就可以先將網(wǎng)絡(luò)需要的layer構(gòu)建好,保存到一個list,然后通過ModuleList方法添加到網(wǎng)絡(luò)中.

          class?MyNet(nn.Module):
          ????def?__init__(self):
          ????????super(MyNet,self).__init__()
          ????????self.linears?=?nn.ModuleList(
          ????????????[nn.Linear(10,10)?for?i?in?range(5)]
          ????????)

          ????def?forward(self,x):
          ????????for?l?in?self.linears:
          ????????????x?=?l(x)
          ????????return?x
          net?=?MyNet()
          print(net)

          輸出結(jié)果是:

          這個ModuleList主要是用在讀取config文件來構(gòu)建網(wǎng)絡(luò)模型中的,下面用VGG模型的構(gòu)建為例子:

          vgg_cfg?=?[64,?64,?'M',?128,?128,?'M',?256,?256,?256,?'C',?512,?512,?512,?'M',
          ???????????512,?512,?512,?'M']

          def?vgg(cfg,?i,?batch_norm=False):
          ????layers?=?[]
          ????in_channels?=?i
          ????for?v?in?cfg:
          ????????if?v?==?'M':
          ????????????layers?+=?[nn.MaxPool2d(kernel_size=2,?stride=2)]
          ????????elif?v?==?'C':
          ????????????layers?+=?[nn.MaxPool2d(kernel_size=2,?stride=2,?ceil_mode=True)]
          ????????else:
          ????????????conv2d?=?nn.Conv2d(in_channels,?v,?kernel_size=3,?padding=1)
          ????????????if?batch_norm:
          ????????????????layers?+=?[conv2d,?nn.BatchNorm2d(v),?nn.ReLU(inplace=True)]
          ????????????else:
          ????????????????layers?+=?[conv2d,?nn.ReLU(inplace=True)]
          ????????????in_channels?=?v
          ????return?layers

          class?Model1(nn.Module):
          ????def?__init__(self):
          ????????super(Model1,self).__init__()

          ????????self.vgg?=?nn.ModuleList(vgg(vgg_cfg,3))

          ????def?forward(self,x):

          ????????for?l?in?self.vgg:
          ????????????x?=?l(x)
          m1?=?Model1()
          print(m1)

          先讀取網(wǎng)絡(luò)結(jié)構(gòu)的配置文件vgg_cfg然后根據(jù)這個文件創(chuàng)建對應(yīng)的Layer list,然后使用ModuleList添加到網(wǎng)絡(luò)中,這樣可以快速創(chuàng)建不同的網(wǎng)絡(luò)(用上面為例子的話,可以通過修改配置文件,然后快速修改網(wǎng)絡(luò)結(jié)構(gòu)

          1.3 Sequential

          在一些自己做的小項目中,Sequential其實用的更為頻繁。依然重寫最初最簡單的例子:

          class?MyNet(nn.Module):
          ????def?__init__(self):
          ????????super(MyNet,self).__init__()
          ????????self.conv?=?nn.Sequential(
          ????????????nn.Conv2d(3,64,3),
          ????????????nn.Conv2d(64,64,3)
          ????????)

          ????def?forward(self,x):
          ????????x?=?self.conv(x)
          ????????return?x
          net?=?MyNet()
          print(net)

          運行結(jié)果:

          觀察細致的朋友可以發(fā)現(xiàn)這個問題,Seqential內(nèi)的網(wǎng)絡(luò)層是默認用數(shù)字進行標號的,而一開始我們使用self.conv1self.conv2的時候,使用conv1和conv2作為標號的。

          我們?nèi)绾涡薷?code style="padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 100, 65);">Sequential中網(wǎng)絡(luò)層的名稱呢?這里需要使用到collections.OrderedDict有序字典。Sequential是支持有序字典構(gòu)建的。

          from?collections?import?OrderedDict?
          class?MyNet(nn.Module):
          ????def?__init__(self):
          ????????super(MyNet,self).__init__()
          ????????self.conv?=?nn.Sequential(OrderedDict([
          ????????????('conv1',nn.Conv2d(3,64,3)),
          ????????????('conv2',nn.Conv2d(64,64,3))
          ????????]))

          ????def?forward(self,x):
          ????????x?=?self.conv(x)
          ????????return?x
          net?=?MyNet()
          print(net)

          輸出結(jié)果:

          1.4 小總結(jié)

          • 單獨增加一個網(wǎng)絡(luò)層或者子模塊,可以用add_module或者直接賦予屬性;
          • ModuleList可以將一個Module的List增加到網(wǎng)絡(luò)中,自由度較高。
          • Sequential按照順序產(chǎn)生一個Module模塊。這里推薦習(xí)慣使用OrderedDict的方法進行構(gòu)建。對網(wǎng)絡(luò)層加上規(guī)范的名稱,這樣有助于后續(xù)查找與遍歷

          2 遍歷模型結(jié)構(gòu)

          本章節(jié)使用下面的方法進行遍歷之前提到的Module。(個人理解,Module是多個layer的合并,但是一個layer可以說成Module。 ) 先定義一個網(wǎng)絡(luò)吧,隨便寫一個:

          import?torch.nn?as?nn
          import?torch?
          from?collections?import?OrderedDict
          class?MyNet(nn.Module):
          ????def?__init__(self):
          ????????super(MyNet,self).__init__()
          ????????self.conv1?=?nn.Conv2d(in_channels=3,out_channels=64,kernel_size=3)
          ????????self.conv2?=?nn.Conv2d(64,64,3)
          ????????self.maxpool1?=?nn.MaxPool2d(2,2)

          ????????self.features?=?nn.Sequential(OrderedDict([
          ????????????('conv3',?nn.Conv2d(64,128,3)),
          ????????????('conv4',?nn.Conv2d(128,128,3)),
          ????????????('relu1',?nn.ReLU())
          ????????]))

          ????def?forward(self,x):
          ????????x?=?self.conv1(x)
          ????????x?=?self.conv2(x)
          ????????x?=?self.maxpool1(x)
          ????????x?=?self.features(x)

          ????????return?x
          net?=?MyNet()
          print(net)

          輸出結(jié)果是:

          2.1 modules()

          在第四課中初始化模型各個層的參數(shù)的時候,用到了這個方法,現(xiàn)在我們再來理解一下:

          for?idx,m?in?enumerate(net.modules()):
          ????print(idx,"-",m)

          運行結(jié)果:

          上面那個網(wǎng)絡(luò)構(gòu)建的時候用到了Sequential,所以網(wǎng)絡(luò)中其實是嵌套了一個小的Module,這就是之前提到的樹狀結(jié)構(gòu),然后上面便利的時候也是樹狀結(jié)構(gòu)的便利過程,可以看出來應(yīng)該是一個深度遍歷的過程。

          • 首先第一個輸出的是最大的那個Module,也就是整個網(wǎng)絡(luò),0-Model整個網(wǎng)絡(luò)模塊;
          • 1-2-3-4是網(wǎng)絡(luò)的四個子模塊,4-Sequential中間仍然包含子模塊
          • 5-6-7是模塊4-Sequential的子模塊。

          【總結(jié)】

          modules()是遞歸的返回網(wǎng)絡(luò)的各個module(深度遍歷),從最頂層直到最后的葉子的module。

          2.2 named_modules()

          named_modules()module()類似,只是同時返回name和module。

          for?idx,(name,m)?in?enumerate(net.named_modules()):
          ????print(idx,"-",name)

          輸出結(jié)果:

          2.3 parameters()

          for?p?in?net.parameters():
          ????print(type(p.data),p.size())

          運行結(jié)果:

          輸出的是四個卷積層的權(quán)重矩陣參數(shù)和偏置參數(shù)。值得一提的是,對網(wǎng)絡(luò)進行訓(xùn)練時需要將parameters()作為優(yōu)化器optimizer的參數(shù)。

          optimizer?=?torch.optim.SGD(net.parameters(),
          ????????????????????????????lr?=?0.001,
          ????????????????????????????momentum=0.9)

          總之呢,這個parameters()是返回網(wǎng)絡(luò)所有的參數(shù),主要用在給optimizer優(yōu)化器用的。而要對網(wǎng)絡(luò)的某一層的參數(shù)做處理的時候,一般還是使用named_parameters()方便一些。

          for?idx,(name,m)?in?enumerate(net.named_parameters()):
          ????print(idx,"-",name,m.size())

          輸出結(jié)果:

          【小擴展】

          我個人有時會使用下面的方法來獲取參數(shù):

          for?idx,(name,m)?in?enumerate(net.named_modules()):
          ????if?isinstance(m,nn.Conv2d):
          ????????print(m.weight.shape)
          ????????print(m.bias.shape)

          先判斷是否是卷積層,然后獲取其參數(shù),輸出結(jié)果:

          3 保存與載入

          PyTorch使用torch.savetorch.load方法來保存和加載網(wǎng)絡(luò),而且網(wǎng)絡(luò)結(jié)構(gòu)和參數(shù)可以分開的保存和加載。

          torch.save(model,'model.pth')?#?保存
          model?=?torch.load("model.pth")?#?加載

          pytorch中網(wǎng)絡(luò)結(jié)構(gòu)和模型參數(shù)是可以分開保存的。上面的方法是兩者同時保存到了.pth文件中,當(dāng)然,你也可以僅僅保存網(wǎng)絡(luò)的參數(shù)來減小存儲文件的大小。注意:如果你僅僅保存模型參數(shù),那么在載入的時候,是需要通過運行代碼來初始化模型的結(jié)構(gòu)的。

          torch.save(model.state_dict(),"model.pth")?#?保存參數(shù)
          model?=?MyNet()?#?代碼中創(chuàng)建網(wǎng)絡(luò)結(jié)構(gòu)
          params?=?torch.load("model.pth")?#?加載參數(shù)
          model.load_state_dict(params)?#?應(yīng)用到網(wǎng)絡(luò)結(jié)構(gòu)中

          至此,我們今天已經(jīng)學(xué)習(xí)了不少的內(nèi)容,大家對PyTorch的掌握更近一步了呢~

          - END -


          往期精彩回顧





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

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

          本站qq群1003271085。

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

          瀏覽 57
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

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

          手機掃一掃分享

          分享
          舉報
          <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>
                  免费看黄色的视频 | 亚洲精品一区二区三区蜜桃 | 黄在线免费看 | 久久久久xxxx | 丁香五月天激情网 |