為什么要多帶帶摘出來參數(shù)講一下。
因為在訓(xùn)練的過程中,我們的目標(biāo)就是找到讓損失函數(shù)最小化的參數(shù)值。經(jīng)過訓(xùn)練之后我們需要將這些參數(shù)拿出來做預(yù)測,或者在其他地方使用。
所以為了以后方便,我們現(xiàn)在就要摘出來多帶帶講一下:
- 訪問參數(shù),用于調(diào)試、診斷和可視化。
- 參數(shù)初始化。
- 在不同模型組件間共享參數(shù)。
import torchfrom torch import nnnet = nn.Sequential(nn.Linear(4, 8), nn.ReLU(), nn.Linear(8, 1))X = torch.rand(size=(2, 4))net(X)
這還是簡易實現(xiàn)了一個多層感知機(jī),然后弄了一個X做輸入。
當(dāng)通過Sequential
類定義模型時,我們可以通過索引來訪問模型的任意層。
print(net)
可以看到輸出為:
>>Sequential( (0): Linear(in_features=4, out_features=8, bias=True) (1): ReLU() (2): Linear(in_features=8, out_features=1, bias=True))
我們可以通過前邊的序號得到想要的層。
print(net[0])print(net[1])print(net[2].state_dict())
>>Linear(in_features=4, out_features=8, bias=True)ReLU()OrderedDict([(weight, tensor([[-0.0264, -0.0906, 0.3497, 0.3284, -0.0173, 0.0124, 0.0136, 0.0782]])), (bias, tensor([0.2243]))])
不出意外,我們看到了前兩層是什么。
至于第三個輸出,我們可以看到,這個層包含兩個參數(shù)。
[ ( weight, tensor([[-0.0264, -0.0906, 0.3497, 0.3284, -0.0173, 0.0124, 0.0136, 0.0782]]) ), ( bias, tensor([0.2243]) )]
print(type(net[2].bias))print(type(net[0].weight))
>>
可以看到每個參數(shù)都表示為參數(shù)(parameter)類的一個實例。
print(net[2].bias)print(net[0].weight)
Parameter containing:tensor([-0.1431, 0.1381, -0.2775, 0.0038, -0.0269, 0.0631, -0.1791, 0.1291], requires_grad=True)Parameter containing:tensor([[-0.4736, 0.2223, -0.0059, 0.4146], [-0.1052, 0.2813, -0.2315, 0.2931], [-0.4990, -0.1991, -0.1453, 0.0369], [-0.4676, 0.0669, -0.0069, -0.4932], [-0.4223, 0.0659, -0.3783, -0.1145], [-0.0460, 0.2386, -0.1586, 0.2148], [-0.0085, -0.3642, 0.0265, 0.0487], [ 0.2703, -0.2903, 0.1822, -0.3782]], requires_grad=True)
相應(yīng)的層序號+方法調(diào)用,提取網(wǎng)絡(luò)的偏置或參數(shù)。
print(*[(name, param.shape) for name, param in net[0].named_parameters()])print(*[(name, param.shape) for name, param in net.named_parameters()])print(*net.named_parameters(),end="/n",sep=/n)# 這里*是一個解包器 ,用于輸出列表的每一個元素
>>(weight, torch.Size([8, 4])) (bias, torch.Size([8]))(0.weight, torch.Size([8, 4])) (0.bias, torch.Size([8]))(2.weight, torch.Size([1, 8])) (2.bias, torch.Size([1]))(0.weight, Parameter containing:tensor([[ 0.3700, 0.3270, -0.3741, -0.1365], [ 0.2200, 0.0786, 0.1241, -0.2834], [ 0.3143, 0.3718, 0.3278, 0.0949], [ 0.1565, 0.4639, -0.1515, -0.4962], [ 0.3102, -0.0025, -0.0099, -0.4132], [ 0.1754, -0.1320, -0.3762, -0.1371], [-0.3860, -0.0369, 0.3743, -0.0892], [ 0.0280, -0.2877, -0.1884, 0.2915]], requires_grad=True))(0.bias, Parameter containing:tensor([ 0.4722, -0.4143, 0.0858, -0.2280, 0.4349, 0.3954, 0.0971, -0.1192], requires_grad=True))(2.weight, Parameter containing:tensor([[ 0.0984, 0.0207, -0.1292, 0.0530, -0.0693, 0.0413, -0.2231, -0.3125]], requires_grad=True))(2.bias, Parameter containing:tensor([0.1844], requires_grad=True))
關(guān)于解包器看這里:Python * ** 打包解包詳解 - 掘金 (juejin.cn)
我把三個輸出分開了。
- 第一個是解包net的第0層的參數(shù)參數(shù)名稱和參數(shù)形狀
- 第二個是解包net所有層的參數(shù)名稱和參數(shù)形狀
- 第三個是解包net的參數(shù)列表
還可以這樣獲取參數(shù)列表:
print(net.state_dict()[2.bias].data)print(net.state_dict()[0.weight])
>>tensor([0.1844])tensor([[ 0.3700, 0.3270, -0.3741, -0.1365], [ 0.2200, 0.0786, 0.1241, -0.2834], [ 0.3143, 0.3718, 0.3278, 0.0949], [ 0.1565, 0.4639, -0.1515, -0.4962], [ 0.3102, -0.0025, -0.0099, -0.4132], [ 0.1754, -0.1320, -0.3762, -0.1371], [-0.3860, -0.0369, 0.3743, -0.0892], [ 0.0280, -0.2877, -0.1884, 0.2915]])
后邊不管加不加.data
都可以直接輸出參數(shù)的值。
def block1(): return nn.Sequential(nn.Linear(4, 8), nn.ReLU(), nn.Linear(8, 4), nn.ReLU())def block2(): net = nn.Sequential() for i in range(4): # 在這里嵌套 net.add_module(fblock {i}, block1()) net[2] = nn.Linear(4,4) return netX = torch.rand(size=(2, 4))rgnet = nn.Sequential(block2(), nn.Linear(4, 1))rgnet(X)
定義一個嵌套的網(wǎng)絡(luò)。隨手畫了個圖,長這樣。
print(rgnet)
輸出一下這個網(wǎng)路哦,可以看到其結(jié)構(gòu)如下:
>>Sequential( (0): Sequential( (block 0): Sequential( (0): Linear(in_features=4, out_features=8, bias=True) (1): ReLU() (2): Linear(in_features=8, out_features=4, bias=True) (3): ReLU() ) (block 1): Linear(in_features=4, out_features=4, bias=True) (block 2): Sequential( (0): Linear(in_features=4, out_features=8, bias=True) (1): ReLU() (2): Linear(in_features=8, out_features=4, bias=True) (3): ReLU() ) ) (1): Linear(in_features=4, out_features=1, bias=True))
比如:
print(rgnet[0][2][0].bias.data)print(rgnet.state_dict()[0.block 2.0.bias])
>>tensor([-0.1555, 0.4410, -0.4920, 0.1434, 0.1243, 0.4114, -0.0883, 0.1387])tensor([-0.1555, 0.4410, -0.4920, 0.1434, 0.1243, 0.4114, -0.0883, 0.1387])
在這種情況下要取到其中的參數(shù),第一個放大就是增加一個地址而已。
第二種方法要首先指明在哪一個塊。再指明哪一個塊上的哪一層。
本文是《動手學(xué)深度學(xué)習(xí)》的筆記,Github地址:DeepLearningNotes/d2l(github.com)
還在更新中…………