1. 程式人生 > 實用技巧 >《動手學深度學習》mxnet版/第四章學習筆記

《動手學深度學習》mxnet版/第四章學習筆記

第四章

概括深度學習計算的各個重要組成部分,如模型構造、引數的訪問和初始化等,自定義層,讀取、儲存和 使用GPU

  • 模型構造
  • 模型引數的訪問、初始化和共享
  • 讀寫Gluon模型的引數

模型構造

Block類是nn模組裡提供的一個模型構造類,可以繼承它來定義我們想要的模型。

#這裡定義的MLP類過載了Block類的__init__函 數和forward函式。它們分別用於建立模型引數和定義前向計算
from mxnet import nd 
from mxnet.gluon import nn 
class MLP(nn.Block): 
    # 宣告帶有模型引數的層,這裡聲明瞭兩個全連線層 
    def __init__(self, **kwargs): 
    # 呼叫MLP父類Block的建構函式來進行必要的初始化。這樣在構造例項時還可以指定其他函式 
    # 引數,如“模型引數的訪問、初始化和共享”一節將介紹的模型引數
    super(MLP, self).__init__(**kwargs) 
    self.hidden = nn.Dense(256, activation='relu')# 隱藏層 
    self.output = nn.Dense(10) # 輸出層 
    
    # 定義模型的前向計算,即如何根據輸入x計算返回所需要的模型輸出 
    def forward(self, x): 
        return self.output(self.hidden(x)) 
#實現一個與Sequential類有相同功能的MySequential類
class MySequential(nn.Block): 
    def __init__(self, **kwargs): 
        super(MySequential, self).__init__(**kwargs)
        
    def add(self, block):
    # block是一個Block子類例項,假設它有一個獨一無二的名字。我們將它儲存在Block類的 
    # 成員變數_children裡,其型別是OrderedDict。當MySequential例項呼叫 
    # initialize函式時,系統會自動對_children裡所有成員初始化 
    self._children[block.name] = block def forward(self, x): 
    # OrderedDict保證會按照成員新增時的順序遍歷成員 
    for block in self._children.values(): 
        x = block(x) 
    return x 
    
# 使用起來與Sequential差不多    
net = MySequential() 
net.add(nn.Dense(256, activation='relu')) 
net.add(nn.Dense(10)) 
net.initialize() 
net(X) 

模型引數的訪問、初始化和共享

在有些情況下,我們希望在多個層之間共享模型引數

#讓模型的第二隱藏層(shared變數)和第三隱藏層共享模型引數
net = nn.Sequential() 
shared = nn.Dense(8, activation='relu') 
net.add(nn.Dense(8, activation='relu'), shared, 
nn.Dense(8, activation='relu', params=shared.params), 
nn.Dense(10)) 
net.initialize()
#在構造第三隱藏層時通過params來指定它使用第二隱藏層的引數。因為模型引數裡包含了 梯度, 所以在反向傳播計算時, 第二隱藏層和第三隱藏層的梯度都會被累加在shared.params.grad()裡

讀寫Gluon模型的引數

Gluon的Block類提供了save_parameters函式和load_parameters函式來讀寫模型引數。

class MLP(nn.Block): 
    def __init__(self, **kwargs): 
        super(MLP, self).__init__(**kwargs)
        self.hidden = nn.Dense(256, activation='relu') 
        self.output = nn.Dense(10) 
    def forward(self, x): 
        return self.output(self.hidden(x))
        
net = MLP() 
net.initialize() 
X = nd.random.uniform(shape=(2, 20)) 
Y = net(X) 
#把該模型的引數存成檔案,檔名為mlp.params
filename = 'mlp.params' net.save_parameters(filename) 
#再例項化一次定義好的多層感知機。與隨機初始化模型引數不同,我們在這裡直接 讀取儲存在檔案裡的引數
net2 = MLP() 
net2.load_parameters(filename) 
#因為這兩個例項都有同樣的模型引數,那麼對同一個輸入X的計算結果將會是一樣的
Y2 = net2(X) 
Y2 == Y