pytorch中model.named_parameters()與model.parameters()解讀
解讀model.named_parameters()與model.parameters()
model.named_parameters()
迭代打印model.named_parameters()將會(huì)打印每一次迭代元素的名字和param。
model = DarkNet([1, 2, 8, 8, 4]) for name, param in model.named_parameters(): ? ? print(name,param.requires_grad) ? ? param.requires_grad = False
輸出結(jié)果為
conv1.weight True
bn1.weight True
bn1.bias True
layer1.ds_conv.weight True
layer1.ds_bn.weight True
layer1.ds_bn.bias True
layer1.residual_0.conv1.weight True
layer1.residual_0.bn1.weight True
layer1.residual_0.bn1.bias True
layer1.residual_0.conv2.weight True
layer1.residual_0.bn2.weight True
layer1.residual_0.bn2.bias True
layer2.ds_conv.weight True
layer2.ds_bn.weight True
layer2.ds_bn.bias True
layer2.residual_0.conv1.weight True
layer2.residual_0.bn1.weight True
layer2.residual_0.bn1.bias True
....
并且可以更改參數(shù)的可訓(xùn)練屬性,第一次打印是True,這是第二次,就是False了
model.parameters()
迭代打印model.parameters()將會(huì)打印每一次迭代元素的param而不會(huì)打印名字,這是它和named_parameters的區(qū)別,兩者都可以用來(lái)改變r(jià)equires_grad的屬性。
for index, param in enumerate(model.parameters()): ? ? print(param.shape)
輸出結(jié)果為
torch.Size([32, 3, 3, 3])
torch.Size([32])
torch.Size([32])
torch.Size([64, 32, 3, 3])
torch.Size([64])
torch.Size([64])
torch.Size([32, 64, 1, 1])
torch.Size([32])
torch.Size([32])
torch.Size([64, 32, 3, 3])
torch.Size([64])
torch.Size([64])
torch.Size([128, 64, 3, 3])
torch.Size([128])
torch.Size([128])
torch.Size([64, 128, 1, 1])
torch.Size([64])
torch.Size([64])
torch.Size([128, 64, 3, 3])
torch.Size([128])
torch.Size([128])
torch.Size([64, 128, 1, 1])
torch.Size([64])
torch.Size([64])
torch.Size([128, 64, 3, 3])
torch.Size([128])
torch.Size([128])
torch.Size([256, 128, 3, 3])
torch.Size([256])
torch.Size([256])
torch.Size([128, 256, 1, 1])
....
將兩者結(jié)合進(jìn)行迭代,同時(shí)具有索引,網(wǎng)絡(luò)層名字及param
?? ?for index, (name, param) in zip(enumerate(model.parameters()), model.named_parameters()): ?? ??? ?print(index[0]) ?? ??? ?print(name, param.shape)
輸出結(jié)果為
0
conv1.weight torch.Size([32, 3, 3, 3])
1
bn1.weight torch.Size([32])
2
bn1.bias torch.Size([32])
3
layer1.ds_conv.weight torch.Size([64, 32, 3, 3])
4
layer1.ds_bn.weight torch.Size([64])
5
layer1.ds_bn.bias torch.Size([64])
6
layer1.residual_0.conv1.weight torch.Size([32, 64, 1, 1])
7
layer1.residual_0.bn1.weight torch.Size([32])
8
layer1.residual_0.bn1.bias torch.Size([32])
9
layer1.residual_0.conv2.weight torch.Size([64, 32, 3, 3])
state_dict()、named_parameters()和parameters()的區(qū)別
Pytorch中有3個(gè)功能極其類(lèi)似的方法,分別是model.parameters()、model.named_parameters()和model.state_dict(),下面就來(lái)探究一下這三種方法的區(qū)別。
它們的差異主要體現(xiàn)在3方面:
- 返回值類(lèi)型不同
- 存儲(chǔ)的模型參數(shù)的種類(lèi)不同
- 返回的值的require_grad屬性不同
測(cè)試代碼準(zhǔn)備工作
import torch import torch.nn as nn import torch.optim as optim import random import os import numpy as np def seed_torch(seed=1029): random.seed(seed) os.environ['PYTHONHASHSEED'] = str(seed) # 為了禁止hash隨機(jī)化,使得實(shí)驗(yàn)可復(fù)現(xiàn) np.random.seed(seed) torch.manual_seed(seed) torch.cuda.manual_seed(seed) torch.cuda.manual_seed_all(seed) # if you are using multi-GPU. torch.backends.cudnn.benchmark = False torch.backends.cudnn.deterministic = True seed_torch() # 固定隨機(jī)數(shù) # 定義一個(gè)網(wǎng)絡(luò) class net(nn.Module): def __init__(self, num_class=10): super(net, self).__init__() self.pool1 = nn.AvgPool1d(2) self.bn1 = nn.BatchNorm1d(3) self.fc1 = nn.Linear(12, 4) def forward(self, x): x = self.pool1(x) x = self.bn1(x) x = x.reshape(x.size(0), -1) x = self.fc1(x) return x # 定義網(wǎng)絡(luò) model = net() # 定義loss loss_fn = nn.CrossEntropyLoss() # 定義優(yōu)化器 optimizer = optim.SGD(model.parameters(), lr=1e-2) # 定義訓(xùn)練數(shù)據(jù) x = torch.randn((3, 3, 8))
兩個(gè)概念
可學(xué)習(xí)參數(shù)
可學(xué)習(xí)參數(shù)也可叫做模型參數(shù),其就是要參與學(xué)習(xí)和更新的,特別注意這里的參數(shù)更新是指在優(yōu)化器的optim.step步驟里更新參數(shù),即需要反向傳播更新的參數(shù)
使用nn.parameter.Parameter()創(chuàng)建的變量是可學(xué)習(xí)參數(shù)(模型參數(shù))
模型中的可學(xué)習(xí)參數(shù)的數(shù)據(jù)類(lèi)型都是nn.parameter.Parameter
optim.step只能更新nn.parameter.Parameter類(lèi)型的參數(shù)
nn.parameter.Parameter類(lèi)型的參數(shù)的特點(diǎn)是默認(rèn)requires_grad=True,也就是說(shuō)訓(xùn)練過(guò)程中需要反向傳播的,就需要使用這個(gè)
示例:
在上述定義的網(wǎng)絡(luò)中,self.fc1層中的參數(shù)(weight和bias)是可學(xué)習(xí)參數(shù),要在訓(xùn)練過(guò)程中進(jìn)行學(xué)習(xí)與更新
print(type(model.fc1.weight))
(bbn) jyzhang@admin2-X10DAi:~/test$ python net.py <class 'torch.nn.parameter.Parameter'>
不可學(xué)習(xí)參數(shù)
不可學(xué)習(xí)參數(shù)不參與學(xué)習(xí)和在優(yōu)化器中的更新,即不需要參與反向傳播
不可學(xué)習(xí)參數(shù)將會(huì)通過(guò)Module.register_parameter()注冊(cè)在self._buffers中,self._buffers是一個(gè)OrderedDict
舉例:上述定義的模型中,self.bn1層中的參數(shù)running_mean、running_var和num_batches_tracked均是不可學(xué)習(xí)參數(shù)
self.register_parameter('running_mean', None)
存儲(chǔ)在self._buffers中的不可學(xué)習(xí)參數(shù)不能通過(guò)optim.step()更新參數(shù),但例如上述的self.bn1層中的不可學(xué)習(xí)參數(shù)也會(huì)更新,其更新是發(fā)生在forward的過(guò)程中
示例:
在上述定義的網(wǎng)絡(luò)中,self.bn1層中的參數(shù)(running_mean)是不可學(xué)習(xí)參數(shù)
print(type(model.bn1.running_mean))
(bbn) jyzhang@admin2-X10DAi:~/test$ python net.py <class 'torch.Tensor'>
named_parameters()
總述
model.named_parameters()返回的是一個(gè)生成器(generator),該生成器中只保存了可學(xué)習(xí)、可被優(yōu)化器更新的參數(shù)的參數(shù)名和具體的參數(shù),可通過(guò)循環(huán)迭代打印參數(shù)名和參數(shù)(參見(jiàn)代碼示例一)
該方法可以用來(lái)改變可學(xué)習(xí)、可被優(yōu)化器更新參數(shù)的requires_grad屬性,因此可用于鎖住某些層的參數(shù),讓其在訓(xùn)練的時(shí)候不更新參數(shù)(參見(jiàn)代碼示例二)
代碼示例一
# model.named_parameters()的用法 print(type(model.named_parameters())) for name, param in model.named_parameters(): ? ? print(name) ? ? print(param)
結(jié)果
(bbn) jyzhang@admin2-X10DAi:~/test$ python net.py
<class 'generator'>
bn1.weight
Parameter containing:
tensor([1., 1., 1.], requires_grad=True)
bn1.bias
Parameter containing:
tensor([0., 0., 0.], requires_grad=True)
fc1.weight
Parameter containing:
tensor([[ 0.0036, 0.1960, 0.2315, -0.2408, 0.1217, 0.2579, -0.0676, -0.1880,
-0.2855, -0.1587, 0.0409, 0.0312],
[ 0.1057, 0.1348, -0.0590, -0.1538, 0.2505, 0.0651, -0.2461, -0.1856,
0.2498, -0.1969, 0.0013, 0.1979],
[-0.1812, 0.1153, 0.2723, -0.2190, 0.0371, -0.0341, 0.2282, 0.1461,
0.1890, 0.1762, 0.2657, -0.0827],
[-0.0188, 0.0081, -0.2674, -0.1858, 0.1296, 0.1728, -0.0770, 0.1444,
-0.2360, -0.1793, 0.1921, -0.2791]], requires_grad=True)
fc1.bias
Parameter containing:
tensor([-0.0020, 0.0985, 0.1859, -0.0175], requires_grad=True)
代碼示例二
print(model.fc1.weight.requires_grad) ?# 可學(xué)習(xí)參數(shù)fc1.weight的requires_grad屬性 for name, param in model.named_parameters(): ? ? if ("fc1" in name): ? ? ? ? param.requires_grad = False print(model.fc1.weight.requires_grad) ?# 修改后可學(xué)習(xí)參數(shù)fc1.weight的requires_grad屬性
結(jié)果
(bbn) jyzhang@admin2-X10DAi:~/test$ python net.py
True
False
parameters()
總述
model.parameters()返回的是一個(gè)生成器,該生成器中只保存了可學(xué)習(xí)、可被優(yōu)化器更新的參數(shù)的具體的參數(shù),可通過(guò)循環(huán)迭代打印參數(shù)。(參見(jiàn)代碼示例一)
與model.named_parameters()相比,model.parameters()不會(huì)保存參數(shù)的名字。
該方法可以用來(lái)改變可學(xué)習(xí)、可被優(yōu)化器更新參數(shù)的requires_grad屬性,但由于其只有參數(shù),沒(méi)有對(duì)應(yīng)的參數(shù)名,所以當(dāng)要修改指定的某些層的requires_grad屬性時(shí),沒(méi)有model.named_parameters()方便。(參見(jiàn)
代碼示例二)
代碼示例一
# model.parameters()的用法 print(type(model.parameters())) for param in model.parameters(): ? ? print(param)
結(jié)果
(bbn) jyzhang@admin2-X10DAi:~/test$ python net.py
<class 'generator'>
Parameter containing:
tensor([1., 1., 1.], requires_grad=True)
Parameter containing:
tensor([0., 0., 0.], requires_grad=True)
Parameter containing:
tensor([[ 0.0036, 0.1960, 0.2315, -0.2408, 0.1217, 0.2579, -0.0676, -0.1880,
-0.2855, -0.1587, 0.0409, 0.0312],
[ 0.1057, 0.1348, -0.0590, -0.1538, 0.2505, 0.0651, -0.2461, -0.1856,
0.2498, -0.1969, 0.0013, 0.1979],
[-0.1812, 0.1153, 0.2723, -0.2190, 0.0371, -0.0341, 0.2282, 0.1461,
0.1890, 0.1762, 0.2657, -0.0827],
[-0.0188, 0.0081, -0.2674, -0.1858, 0.1296, 0.1728, -0.0770, 0.1444,
-0.2360, -0.1793, 0.1921, -0.2791]], requires_grad=True)
Parameter containing:
tensor([-0.0020, 0.0985, 0.1859, -0.0175], requires_grad=True)
代碼示例二
print(model.fc1.weight.requires_grad) for param in model.parameters(): ? ? param.requires_grad = False print(model.fc1.weight.requires_grad)
結(jié)果
(bbn) jyzhang@admin2-X10DAi:~/test$ python net.py
True
False
state_dict()
總述
model.state_dict()返回的是一個(gè)有序字典OrderedDict,該有序字典中保存了模型所有參數(shù)的參數(shù)名和具體的參數(shù)值,所有參數(shù)包括可學(xué)習(xí)參數(shù)和不可學(xué)習(xí)參數(shù),可通過(guò)循環(huán)迭代打印參數(shù),因此,該方法可用于保存模型,當(dāng)保存模型時(shí),會(huì)將不可學(xué)習(xí)參數(shù)也存下,當(dāng)加載模型時(shí),也會(huì)將不可學(xué)習(xí)參數(shù)進(jìn)行賦值。(參見(jiàn)代碼示例一)
一般在使用model.state_dict()時(shí)會(huì)使用該函數(shù)的默認(rèn)參數(shù),model.state_dict()源碼如下:
# torch.nn.modules.module.py class Module(object): ? ? def state_dict(self, destination=None, prefix='', keep_vars=False): ? ? ? ? if destination is None: ? ? ? ? ? ? destination = OrderedDict() ? ? ? ? ? ? destination._metadata = OrderedDict() ? ? ? ? destination._metadata[prefix[:-1]] = local_metadata = dict(version=self._version) ? ? ? ? for name, param in self._parameters.items(): ? ? ? ? ? ? if param is not None: ? ? ? ? ? ? ? ? destination[prefix + name] = param if keep_vars else param.data ? ? ? ? for name, buf in self._buffers.items(): ? ? ? ? ? ? if buf is not None: ? ? ? ? ? ? ? ? destination[prefix + name] = buf if keep_vars else buf.data ? ? ? ? for name, module in self._modules.items(): ? ? ? ? ? ? if module is not None: ? ? ? ? ? ? ? ? module.state_dict(destination, prefix + name + '.', keep_vars=keep_vars) ? ? ? ? for hook in self._state_dict_hooks.values(): ? ? ? ? ? ? hook_result = hook(self, destination, prefix, local_metadata) ? ? ? ? ? ? if hook_result is not None: ? ? ? ? ? ? ? ? destination = hook_result ? ? ? ? return destination
在默認(rèn)參數(shù)下,model.state_dict()保存參數(shù)時(shí)只會(huì)保存參數(shù)(Tensor對(duì)象)的data屬性,不會(huì)保存參數(shù)的requires_grad屬性,因此,其保存的參數(shù)的requires_grad的屬性變?yōu)镕alse,沒(méi)有辦法改變r(jià)equires_grad的屬性,所以改變r(jià)equires_grad的屬性只能通過(guò)上面的兩種方式。(參見(jiàn)代碼示例二)
model.state_dict()本質(zhì)上是淺拷貝,即返回的OrderedDict對(duì)象本身是新創(chuàng)建的對(duì)象,但其中的param參數(shù)的引用仍是模型參數(shù)的data屬性的地址,又因?yàn)門(mén)ensor是可變對(duì)象,因此,若對(duì)param參數(shù)進(jìn)行修改(在原地址變更數(shù)據(jù)內(nèi)容),會(huì)導(dǎo)致對(duì)應(yīng)的模型參數(shù)的改變。(參見(jiàn)代碼示例三)
代碼示例一
# model.state_dict()的用法 print(model.state_dict()) for name, param in model.state_dict().items(): ? ? print(name) ? ? print(param) ? ? print(param.requires_grad)
結(jié)果
(bbn) jyzhang@admin2-X10DAi:~/test$ python net.py
OrderedDict([('bn1.weight', tensor([1., 1., 1.])), ('bn1.bias', tensor([0., 0., 0.])), ('bn1.running_mean', tensor([0., 0., 0.])), ('bn1.running_var', tensor([1., 1., 1.])), ('bn1.num_batches_tracked', tensor(0)), ('fc1.weight', tensor([[ 0.0036, 0.1960, 0.2315, -0.2408, 0.1217, 0.2579, -0.0676, -0.1880,
-0.2855, -0.1587, 0.0409, 0.0312],
[ 0.1057, 0.1348, -0.0590, -0.1538, 0.2505, 0.0651, -0.2461, -0.1856,
0.2498, -0.1969, 0.0013, 0.1979],
[-0.1812, 0.1153, 0.2723, -0.2190, 0.0371, -0.0341, 0.2282, 0.1461,
0.1890, 0.1762, 0.2657, -0.0827],
[-0.0188, 0.0081, -0.2674, -0.1858, 0.1296, 0.1728, -0.0770, 0.1444,
-0.2360, -0.1793, 0.1921, -0.2791]])), ('fc1.bias', tensor([-0.0020, 0.0985, 0.1859, -0.0175]))])
bn1.weight
tensor([1., 1., 1.])
False
bn1.bias
tensor([0., 0., 0.])
False
bn1.running_mean
tensor([0., 0., 0.])
False
bn1.running_var
tensor([1., 1., 1.])
False
bn1.num_batches_tracked
tensor(0)
False
fc1.weight
tensor([[ 0.0036, 0.1960, 0.2315, -0.2408, 0.1217, 0.2579, -0.0676, -0.1880,
-0.2855, -0.1587, 0.0409, 0.0312],
[ 0.1057, 0.1348, -0.0590, -0.1538, 0.2505, 0.0651, -0.2461, -0.1856,
0.2498, -0.1969, 0.0013, 0.1979],
[-0.1812, 0.1153, 0.2723, -0.2190, 0.0371, -0.0341, 0.2282, 0.1461,
0.1890, 0.1762, 0.2657, -0.0827],
[-0.0188, 0.0081, -0.2674, -0.1858, 0.1296, 0.1728, -0.0770, 0.1444,
-0.2360, -0.1793, 0.1921, -0.2791]])
False
fc1.bias
tensor([-0.0020, 0.0985, 0.1859, -0.0175])
False
代碼示例二
# model.state_dict()的用法 print(model.bn1.weight.requires_grad) model.bn1.weight.requires_grad = False print(model.bn1.weight.requires_grad) for name, param in model.state_dict().items(): ? ? if (name == "bn1.weight"): ? ? ? ? param.requires_grad = True print(model.bn1.weight.requires_grad)
結(jié)果
(bbn) jyzhang@admin2-X10DAi:~/test$ python net.py
True
False
False
代碼示例三
# model.state_dict()的用法 print(model.bn1.weight) for name, param in model.state_dict().items(): ? ? if (name == "bn1.weight"): ? ? ? ? param[0] = 1000 print(model.bn1.weight)
結(jié)果
(bbn) jyzhang@admin2-X10DAi:~/test$ python net.py
Parameter containing:
tensor([1., 1., 1.], requires_grad=True)
Parameter containing:
tensor([1000., 1., 1.], requires_grad=True)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
python中Apriori算法實(shí)現(xiàn)講解
給大家詳細(xì)講解一下Apriori 算法在python中的實(shí)現(xiàn)過(guò)程,有需要的朋友收藏一下本片文章吧。2017-12-12Python+pyaudio實(shí)現(xiàn)音頻控制示例詳解
PyAudio?是語(yǔ)音處理的?Python?庫(kù),提供了比較豐富的功能。本文將利用pyaudio控制指定設(shè)備,實(shí)現(xiàn)錄制音頻、采集音頻流、播放音頻,感興趣的可以了解一下2022-07-07python實(shí)現(xiàn)npy格式文件轉(zhuǎn)換為txt文件操作
這篇文章主要介紹了python實(shí)現(xiàn)npy格式文件轉(zhuǎn)換為txt文件操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07深入講解Python函數(shù)中參數(shù)的使用及默認(rèn)參數(shù)的陷阱
這篇文章主要介紹了Python函數(shù)中參數(shù)的使用及默認(rèn)參數(shù)的陷阱,文中將函數(shù)的參數(shù)分為必選參數(shù)、默認(rèn)參數(shù)、可變參數(shù)和關(guān)鍵字參數(shù)來(lái)講,要的朋友可以參考下2016-03-03python實(shí)現(xiàn)任意位置文件分割的實(shí)例
今天小編就為大家分享一篇python實(shí)現(xiàn)任意位置文件分割的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-12-12python可視化plotly?圖例(legend)設(shè)置
這篇文章主要介紹了python可視化plotly?圖例(legend)設(shè)置,主要介紹了關(guān)于python?的legend圖例,參數(shù)使用說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,需要的朋友可以參考下賣(mài)你具體內(nèi)容2022-02-02Python實(shí)現(xiàn)動(dòng)態(tài)柱狀圖的繪制
這篇文章主要為大家詳細(xì)介紹了Python實(shí)現(xiàn)動(dòng)態(tài)柱狀圖的繪制的相關(guān)資料,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)與借鑒價(jià)值,需要的可以參考一下2022-12-12如何解決jupyter?notebook中文亂碼問(wèn)題
這篇文章主要介紹了如何解決jupyter?notebook中文亂碼問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06