1. 模型構(gòu)造
在構(gòu)造自定義塊之前,我們先回顧一下多層感知機(jī)的代碼。 下面的代碼生成一個(gè)網(wǎng)絡(luò),其中包含一個(gè)具有256個(gè)單元和ReLU激活函數(shù)的全連接隱藏層, 然后是一個(gè)具有10個(gè)隱藏單元且不帶激活函數(shù)的全連接輸出層。
層和塊
構(gòu)造單層神經(jīng)網(wǎng)咯:線性層+RELU+線性層
生成2x20(2是批量大小,20是批量維度)的隨機(jī)矩陣
在這個(gè)例子中,我們通過(guò)實(shí)例化nn.Sequential來(lái)構(gòu)建我們的模型, 層的執(zhí)行順序是作為參數(shù)傳遞的。 簡(jiǎn)而言之,nn.Sequential定義了一種特殊的Module, 即在PyTorch中表示一個(gè)塊的類, 它維護(hù)了一個(gè)由Module組成的有序列表。 注意,兩個(gè)全連接層都是Linear類的實(shí)例,Linear類本身就是Module的子類。 另外,到目前為止,我們一直在通過(guò)net(X)調(diào)用我們的模型來(lái)獲得模型的輸出。 這實(shí)際上是net.__call__(X)的簡(jiǎn)寫。 這個(gè)前向傳播函數(shù)非常簡(jiǎn)單: 它將列表中的每個(gè)塊連接在一起,將每個(gè)塊的輸出作為下一個(gè)塊的輸入。
1.1 自定義
要想直觀地了解塊是如何工作的,最簡(jiǎn)單的方法就是自己實(shí)現(xiàn)一個(gè)。 在實(shí)現(xiàn)我們自定義塊之前,我們簡(jiǎn)要總結(jié)一下每個(gè)塊必須提供的基本功能。
-
將輸入數(shù)據(jù)作為其前向傳播函數(shù)的參數(shù)。
-
通過(guò)前向傳播函數(shù)來(lái)生成輸出。請(qǐng)注意,輸出的形狀可能與輸入的形狀不同。例如,我們上面模型中的第一個(gè)全連接的層接收一個(gè)20維的輸入,但是返回一個(gè)維度為256的輸出。
-
計(jì)算其輸出關(guān)于輸入的梯度,可通過(guò)其反向傳播函數(shù)進(jìn)行訪問(wèn)。通常這是自動(dòng)發(fā)生的。
-
存儲(chǔ)和訪問(wèn)前向傳播計(jì)算所需的參數(shù)。
-
根據(jù)需要初始化模型參數(shù)
自定義快
MLP是nn.Module的子類,所以nn.Module有兩個(gè)函數(shù)
實(shí)例化多層感知機(jī)的層
# 動(dòng)手打一遍吧,加深一下印象嘞 class MLP(nn.Module): # 用模型參數(shù)聲明層。這里,我們聲明兩個(gè)全連接的層 def __init__(self): # 調(diào)用MLP的父類Module的構(gòu)造函數(shù)來(lái)執(zhí)行必要的初始化。 # 這樣,在類實(shí)例化時(shí)也可以指定其他函數(shù)參數(shù),例如模型參數(shù)params(稍后將介紹) super().__init__() self.hidden = nn.Linear(20, 256) # 隱藏層 self.out = nn.Linear(256, 10) # 輸出層 # 定義模型的前向傳播,即如何根據(jù)輸入X返回所需的模型輸出 def forward(self, X): # 注意,這里我們使用ReLU的函數(shù)版本,其在nn.functional模塊中定義。 return self.out(F.relu(self.hidden(X)))
上述代碼的解析
# 測(cè)試上述代碼 net = MLP() net(X) # 塊的一個(gè)主要優(yōu)點(diǎn)是它的多功能性。 # 我們可以子類化塊以創(chuàng)建層(如全連接層的類)、 整個(gè)模型(如上面的MLP類)或具有中等復(fù)雜度的各種組件。 # 我們?cè)诮酉聛?lái)的章節(jié)中充分利用了這種多功能性, 比如在處理卷積神經(jīng)網(wǎng)絡(luò)時(shí)。
1.2 順序塊
現(xiàn)在我們可以更仔細(xì)地看看Sequential類是如何工作的, 回想一下Sequential的設(shè)計(jì)是為了把其他模塊串起來(lái)。 為了構(gòu)建我們自己的簡(jiǎn)化的MySequential, 我們只需要定義兩個(gè)關(guān)鍵函數(shù):
-
一種將塊逐個(gè)追加到列表中的函數(shù);
-
一種前向傳播函數(shù),用于將輸入按追加塊的順序傳遞給塊組成的“鏈條”。
下面的MySequential類提供了與默認(rèn)Sequential類相同的功能。
順序塊
*args: lists of inputs of arguments
super( )._init_( ) 調(diào)用父類的初始化函數(shù)
self._modeules[block] : ordered dictionary. 放進(jìn)去key. 【也就是說(shuō)把傳進(jìn)去的每一層layer都按照順序放在這個(gè)容器里,感覺(jué)相當(dāng)于是數(shù)組的作用,只不過(guò)她存的是神經(jīng)網(wǎng)絡(luò)層】
class MySequential(nn.Module): def __init__(self, *args): super().__init__() for idx, module in enumerate(args): # 這里,module是Module子類的一個(gè)實(shí)例。我們把它保存在'Module'類的成員 # 變量_modules中。_module的類型是OrderedDict self._modules[str(idx)] = module def forward(self, X): # OrderedDict保證了按照成員添加的順序遍歷它們 for block in self._modules.values(): X = block(X) return X net = MySequential(nn.Linear(20, 256), nn.ReLU(), nn.Linear(256, 10)) net(X)
1.3 在前向傳播函數(shù)中執(zhí)行代碼
Sequential類使模型構(gòu)造變得簡(jiǎn)單, 允許我們組合新的架構(gòu),而不必定義自己的類。 然而,并不是所有的架構(gòu)都是簡(jiǎn)單的順序架構(gòu)。 當(dāng)需要更強(qiáng)的靈活性時(shí),我們需要定義自己的塊。 例如,我們可能希望在前向傳播函數(shù)中執(zhí)行Python的控制流。 此外,我們可能希望執(zhí)行任意的數(shù)學(xué)運(yùn)算, 而不是簡(jiǎn)單地依賴預(yù)定義的神經(jīng)網(wǎng)絡(luò)層。
添加圖片注釋,不超過(guò) 140 字(可選)
class FixedHiddenMLP(nn.Module): def __init__(self): super().__init__() # 不計(jì)算梯度的隨機(jī)權(quán)重參數(shù)。因此其在訓(xùn)練期間保持不變 self.rand_weight = torch.rand((20, 20), requires_grad=False) self.linear = nn.Linear(20, 20) def forward(self, X): X = self.linear(X) # 使用創(chuàng)建的常量參數(shù)以及relu和mm函數(shù) X = F.relu(torch.mm(X, self.rand_weight) + 1) # 復(fù)用全連接層。這相當(dāng)于兩個(gè)全連接層共享參數(shù) X = self.linear(X) # 控制流 while X.abs().sum() > 1: X /= 2 return X.sum() net = FixedHiddenMLP() net(X)
添加圖片注釋,不超過(guò) 140 字(可選)
我們可以混合搭配各種組合塊的方法。 在下面的例子中,我們以一些想到的方法嵌套塊。
class NestMLP(nn.Module): def __init__(self): super().__init__() self.net = nn.Sequential(nn.Linear(20, 64), nn.ReLU(), nn.Linear(64, 32), nn.ReLU()) self.linear = nn.Linear(32, 16) def forward(self, X): return self.linear(self.net(X)) chimera = nn.Sequential(NestMLP(), nn.Linear(16, 20), FixedHiddenMLP()) chimera(X)
不是很能完全理解....先這樣,學(xué)到后面應(yīng)該這里會(huì)好一些,迷茫拋在這里啦
2. 參數(shù)管理
我們首先看一下具有單隱藏層的多層感知機(jī)。
import torch from torch import nn net = nn.Sequential(nn.Linear(4, 8), nn.ReLU(), nn.Linear(8, 1)) X = torch.rand(size=(2, 4)) net(X)
2.1 參數(shù)訪問(wèn)
print(net[2].state_dict())
輸出的結(jié)果告訴我們一些重要的事情: 首先,這個(gè)全連接層包含兩個(gè)參數(shù),分別是該層的權(quán)重和偏置。 兩者都存儲(chǔ)為單精度浮點(diǎn)數(shù)(float32)。 注意,參數(shù)名稱允許唯一標(biāo)識(shí)每個(gè)參數(shù),即使在包含數(shù)百個(gè)層的網(wǎng)絡(luò)中也是如此。
net[2] 拿到的是nn.Linear(8, 1)
state_dict() 就是權(quán)重
目標(biāo)參數(shù)
一次性訪問(wèn)所有參數(shù)
添加圖片注釋,不超過(guò) 140 字(可選)
添加圖片注釋,不超過(guò) 140 字(可選)
添加圖片注釋,不超過(guò) 140 字(可選)
添加圖片注釋,不超過(guò) 140 字(可選)
添加圖片注釋,不超過(guò) 140 字(可選)
添加圖片注釋,不超過(guò) 140 字(可選)
添加圖片注釋,不超過(guò) 140 字(可選)
3. 自定義層
添加圖片注釋,不超過(guò) 140 字(可選)
添加圖片注釋,不超過(guò) 140 字(可選)
添加圖片注釋,不超過(guò) 140 字(可選)
添加圖片注釋,不超過(guò) 140 字(可選)
4. 讀寫文件
添加圖片注釋,不超過(guò) 140 字(可選)
添加圖片注釋,不超過(guò) 140 字(可選)
添加圖片注釋,不超過(guò) 140 字(可選)
看不懂的可以看看這本書(shū)的講解:
http://www.feiguyunai.com/index.php/2019/09/11/pytorch-char03/
Pytorch神經(jīng)網(wǎng)絡(luò)工具箱
jupyter路徑:pytorch/chapter_deep-learning-computation/model-construction.ipynb文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-838258.html
https://github.com/Miraclelucy/dive-into-deep-learning 將李沐老師課堂中的jupyter notebook代碼整理成了py格式的,歡迎關(guān)注,共同學(xué)習(xí)。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-838258.html
到了這里,關(guān)于16 PyTorch 神經(jīng)網(wǎng)絡(luò)基礎(chǔ)【李沐動(dòng)手學(xué)深度學(xué)習(xí)v2】的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!