J'ai récemment lu l'article et j'ai vu que certains programmes doivent d'abord former un modèle, puis intégrer une partie de la structure du modèle formé dans le nouveau modèle, puis utiliser les nouvelles données pour former le nouveau modèle, mais les paramètres de cette partie sont Pour le garder, au début je pensais que c'était très similaire à l'apprentissage par transfert, parce que je ne l'avais pas étudié en détail, donc je n'étais pas sûr, alors j'ai d'abord appris à réaliser le plan de la thèse, et l'ai enregistré ici pour référence future. Quant à l'apprentissage par transfert, étudions à l'avenir, il devrait être utilisé!
PyTorch enregistre certains paramètres du modèle et les charge dans un nouveau modèle
- état_dict
- Enregistrez le modèle dans le chemin actuel avec le nom test_state_dict.pth
- OrderedDict
- Enregistrez certains paramètres du modèle et chargez-les dans un nouveau modèle
- La différence entre state_dict(), named_parameters(), model.parameter(), named_modules()
- Geler certaines couches / ne laisser que certaines couches apprendre
- Les références
état_dict
Introduction à state_dict
state_dict
est un objet de dictionnaire Python qui peut être utilisé pour enregistrer les paramètres du modèle, les hyperparamètres et les informations d'état de l'optimiseur (torch.optim). Il convient de noter que seules les couches avec des paramètres apprenables (telles que les couches convolutionnelles, les couches linéaires, etc.) ont un state_dict.
Donnez une châtaigne pour illustrer l'utilisation de state_dict :
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
# 定义模型
class TheModelClass(nn.Module):
def __init__(self):
super(TheModelClass, self).__init__()
self.conv1 = nn.Conv2d(3, 6, 5)
self.pool = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(6, 16, 5)
self.fc1 = nn.Linear(16 * 5 * 5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x = x.view(-1, 16 * 5 * 5)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
# 初始化模型
model = TheModelClass()
# 初始化优化器
optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)
# 打印模型的状态字典
print("Model's state_dict:")
for param_tensor in model.state_dict():
print(param_tensor, "\t", model.state_dict()[param_tensor].size())
sortir:
Model's state_dict:
conv1.weight torch.Size([6, 3, 5, 5])
conv1.bias torch.Size([6])
conv2.weight torch.Size([16, 6, 5, 5])
conv2.bias torch.Size([16])
fc1.weight torch.Size([120, 400])
fc1.bias torch.Size([120])
fc2.weight torch.Size([84, 120])
fc2.bias torch.Size([84])
fc3.weight torch.Size([10, 84])
fc3.bias torch.Size([10])
# 打印优化器的状态字典
print("Optimizer's state_dict:")
for var_name in optimizer.state_dict():
print(var_name, "\t", optimizer.state_dict()[var_name])
sortir:
Optimizer's state_dict:
state {
}
param_groups [{
'lr': 0.001, 'momentum': 0.9, 'dampening': 0, 'weight_decay': 0, 'nesterov': False, 'maximize': False, 'foreach': None, 'params': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]}]
Enregistrer et charger state_dict
Le state_dict du modèle peut torch.save()
être enregistré par , c'est-à-dire que seuls les paramètres de modèle appris sont enregistrés, et les load_state_dict()
paramètres de modèle peuvent être chargés et restaurés par . Les extensions de sauvegarde de modèle les plus courantes dans PyTorch sont ' .pt ' ou ' .pth '.
Enregistrez le modèle dans le chemin actuel avec le nom test_state_dict.pth
PATH = './test_state_dict.pth'
torch.save(model.state_dict(), PATH)
model = TheModelClass() # 首先通过代码获取模型结构
model.load_state_dict(torch.load(PATH)) # 然后加载模型的state_dict
model.eval()
Remarque : La fonction load_state_dict() accepte uniquement 字典对象
et ne peut pas transmettre directement le chemin du modèle. Vous devez donc utiliser torch.load() pour désérialiser d'abord le state_dict enregistré.
Enregistrer et charger des modèles complets
# 保存完整模型
torch.save(model, PATH)
# 加载完整模型
model = torch.load(PATH)
model.eval()
Bien que le code de cette méthode semble plus concis que la méthode state_dict, il est moins flexible. Parce que la fonction torch.save() utilise le module pickle de Python pour la sérialisation, mais pickle ne peut pas enregistrer le modèle lui-même, mais enregistre le chemin du fichier contenant la classe, qui sera utilisée lors du chargement du modèle. Ainsi, lorsque le modèle est refactorisé dans d'autres projets, des erreurs inattendues peuvent apparaître.
OrderedDict
Si nous imprimons state_dict
le type de données, nous obtiendrons la sortie suivante :
print(type(model.state_dict()))
sortir:
<class 'collections.OrderedDict'>
Le module de collections implémente des conteneurs spécifiques à l'objet pour fournir une alternative aux conteneurs intégrés standard de Python dict , list , set et tuple .
class collections.OrderedDict([items])
OrderedDict
dict
Une instance d' une sous-classe , un dictionnaire ordonné est comme un dictionnaire ordinaire, mais avec quelques fonctionnalités supplémentaires liées aux opérations de tri.
Il convient de mentionner qu'après python3.7 , la classe dict intégrée a acquis la capacité de se souvenir de l'ordre d'insertion, donc ce conteneur n'est pas si important.
Quelques différences avec dict :
- Les dicts réguliers sont conçus pour être très bons dans les opérations de cartographie. Le suivi de l'ordre d'insertion est secondaire ;
- OrderedDict est conçu pour être efficace dans la réorganisation des opérations. L'efficacité de l'espace, la vitesse d'itération et les performances des opérations de mise à jour sont secondaires ;
- Algorithmiquement, OrderedDict peut mieux gérer les opérations de réorganisation fréquentes que dict. Cela le rend approprié pour garder une trace des accès récents (par exemple dans un cache LRU);
Enregistrez certains paramètres du modèle et chargez-les dans un nouveau modèle
Pour le modèle ci-dessus, le dictionnaire d'état du modèle est :
Model's state_dict:
conv1.weight torch.Size([6, 3, 5, 5])
conv1.bias torch.Size([6])
conv2.weight torch.Size([16, 6, 5, 5])
conv2.bias torch.Size([16])
fc1.weight torch.Size([120, 400])
fc1.bias torch.Size([120])
fc2.weight torch.Size([84, 120])
fc2.bias torch.Size([84])
fc3.weight torch.Size([10, 84])
fc3.bias torch.Size([10])
Si nous voulons uniquement enregistrer les paramètres formés de conv1 , nous pouvons le faire :
save_state = {
}
print("Model's state_dict:")
for param_tensor in model.state_dict():
if 'conv1' in param_tensor:
save_state.update({
param_tensor:torch.ones((model.state_dict()[param_tensor].size()))})
print(param_tensor, "\t", model.state_dict()[param_tensor].size())
Ici, pour la commodité des démonstrations ultérieures, notre phrase clé est écrite comme ceci :
save_state.update({
param_tensor:torch.ones((model.state_dict()[param_tensor].size()))})
Mais lors de la sauvegarde, nous devrions écrire comme ceci :
save_state.update({
param_tensor:model.state_dict()[param_tensor]})
Enregistrez ensuite le dictionnaire save_state :
PATH = './test_state_dict.pth'
torch.save(save_state, PATH)
Chargez ensuite le nouveau modèle et affectez les paramètres enregistrés au nouveau modèle :
model = TheModelClass() # 首先通过代码获取模型结构
model.load_state_dict(torch.load(PATH), strict=False) # 然后加载模型的state_dict
sortir:
_IncompatibleKeys(missing_keys=['conv2.weight', 'conv2.bias', 'fc1.weight', 'fc1.bias', 'fc2.weight', 'fc2.bias', 'fc3.weight', 'fc3.bias'], unexpected_keys=[])
Voici le mode de démarrage à chaud, en définissant le paramètre strict sur False dans la fonction load_state_dict() pour ignorer les paramètres des clés non concordantes.
Reprenons les paramètres du nouveau modèle :
model.state_dict()['conv1.bias']
sortir:
tensor([1., 1., 1., 1., 1., 1.])
Les paramètres enregistrés entre les découvertes ont été chargés dans le nouveau modèle.
Regardez les autres paramètres du modèle :
model.state_dict()['conv2.bias']
sortir:
tensor([ 0.0468, 0.0024, -0.0510, 0.0791, 0.0244, -0.0379, -0.0708, 0.0317,
-0.0410, -0.0238, 0.0071, 0.0193, -0.0562, -0.0336, 0.0109, -0.0323])
Vous pouvez voir que les autres paramètres sont normaux !
La différence entre state_dict(), named_parameters(), model.parameter(), named_modules()
modèle.state_dict()
state_dict()
Il s'agit de stocker layer_name et layer_param sous forme de clés sous la forme de dict . Contient les noms et les paramètres de toutes les couches, les paramètres de modèle stockés tensor 的 require_grad 属性都是 False
. La valeur de sortie n'inclut pas require_grad. Vous ne pouvez pas utiliser model.state_dict() pour obtenir des paramètres et définir l'attribut require_grad lors de la correction d'un certain calque .
import torch
import torch.nn as nn
import torch.optim as optim
# 定义模型
class TheModelClass(nn.Module):
def __init__(self):
super(TheModelClass, self).__init__()
self.conv1 = nn.Conv2d(1, 2, 3)
self.bn = nn.BatchNorm2d(num_features=2)
self.act = nn.ReLU()
self.pool = nn.MaxPool2d(2, 2)
self.fc1 = nn.Linear(8, 4)
self.softmax = nn.Softmax(dim=-1)
def forward(self, x):
x = self.conv1(x)
x = self.bn(x)
x = self.act(x)
x = self.pool(x)
x = x.view(-1, 8)
x = self.fc1(x)
x = self.softmax(x)
return x
# 初始化模型
model = TheModelClass()
# 初始化优化器
optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)
for param_tensor in model.state_dict():
print(param_tensor, "\n", model.state_dict()[param_tensor])
sortir:
conv1.weight
tensor([[[[ 0.2438, -0.0467, 0.0486],
[-0.1932, -0.2083, 0.3239],
[ 0.1712, 0.0379, -0.2381]]],
[[[ 0.2853, 0.0961, 0.0809],
[ 0.2526, 0.3138, -0.2243],
[-0.1627, -0.2958, -0.1995]]]]) # 没有 require_grad
conv1.bias
tensor([-0.3287, -0.0686])
bn.weight
tensor([1., 1.])
bn.bias
tensor([0., 0.])
bn.running_mean
tensor([0., 0.])
bn.running_var
tensor([1., 1.])
bn.num_batches_tracked
tensor(0)
fc1.weight
tensor([[ 0.2246, -0.1272, 0.0163, -0.3089, 0.3511, -0.0189, 0.3025, 0.0770],
[ 0.2964, 0.2050, 0.2879, 0.0237, -0.3424, 0.0346, -0.0659, -0.0115],
[ 0.1960, -0.2104, -0.2839, 0.0977, -0.2857, -0.0610, -0.3029, 0.1230],
[-0.2176, 0.2868, -0.2258, 0.2992, -0.2619, 0.3286, 0.0410, 0.0152]])
fc1.bias
tensor([-0.0623, 0.1708, -0.1836, -0.1411])
model.named_parameters()
named_parameters()
Il s'agit de regrouper layer_name et layer_param dans un tuple, puis de le stocker dans la liste.
Enregistrez uniquement les paramètres qui peuvent être appris et mis à jour. model.named_parameters() Paramètres de modèle stockés tensor 的 require_grad 属性都是True
. Il est souvent utilisé pour déterminer si les paramètres d'une certaine couche sont formés , généralement via model.named_parameters() pour obtenir des paramètres et définir l'attribut require_grad .
import torch
import torch.nn as nn
import torch.optim as optim
# 定义模型
class TheModelClass(nn.Module):
def __init__(self):
super(TheModelClass, self).__init__()
self.conv1 = nn.Conv2d(1, 2, 3)
self.bn = nn.BatchNorm2d(num_features=2)
self.act = nn.ReLU()
self.pool = nn.MaxPool2d(2, 2)
self.fc1 = nn.Linear(8, 4)
self.softmax = nn.Softmax(dim=-1)
def forward(self, x):
x = self.conv1(x)
x = self.bn(x)
x = self.act(x)
x = self.pool(x)
x = x.view(-1, 8)
x = self.fc1(x)
x = self.softmax(x)
return x
# 初始化模型
model = TheModelClass()
# 初始化优化器
optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)
for layer_name, layer_param in model.named_parameters():
print(layer_name, "\n", layer_param)
sortir:
conv1.weight
Parameter containing:
tensor([[[[ 0.2438, -0.0467, 0.0486],
[-0.1932, -0.2083, 0.3239],
[ 0.1712, 0.0379, -0.2381]]],
[[[ 0.2853, 0.0961, 0.0809],
[ 0.2526, 0.3138, -0.2243],
[-0.1627, -0.2958, -0.1995]]]], requires_grad=True) # require_grad为True
conv1.bias
Parameter containing:
tensor([-0.3287, -0.0686], requires_grad=True)
bn.weight
Parameter containing:
tensor([1., 1.], requires_grad=True)
bn.bias
Parameter containing:
tensor([0., 0.], requires_grad=True)
fc1.weight
Parameter containing:
tensor([[ 0.2246, -0.1272, 0.0163, -0.3089, 0.3511, -0.0189, 0.3025, 0.0770],
[ 0.2964, 0.2050, 0.2879, 0.0237, -0.3424, 0.0346, -0.0659, -0.0115],
[ 0.1960, -0.2104, -0.2839, 0.0977, -0.2857, -0.0610, -0.3029, 0.1230],
[-0.2176, 0.2868, -0.2258, 0.2992, -0.2619, 0.3286, 0.0410, 0.0152]],
requires_grad=True)
fc1.bias
Parameter containing:
tensor([-0.0623, 0.1708, -0.1836, -0.1411], requires_grad=True)
modèle.paramètre()
parameter()
Seuls les paramètres sont renvoyés, nom_couche n'est pas inclus . 返回结果包含 require_grad,且均为 Ture
, principalement parce que les paramètres par défaut doivent être appris lors de la création du réseau, c'est-à-dire que require_grad est entièrement défini sur True.
import torch
import torch.nn as nn
import torch.optim as optim
# 定义模型
class TheModelClass(nn.Module):
def __init__(self):
super(TheModelClass, self).__init__()
self.conv1 = nn.Conv2d(1, 2, 3)
self.bn = nn.BatchNorm2d(num_features=2)
self.act = nn.ReLU()
self.pool = nn.MaxPool2d(2, 2)
self.fc1 = nn.Linear(8, 4)
self.softmax = nn.Softmax(dim=-1)
def forward(self, x):
x = self.conv1(x)
x = self.bn(x)
x = self.act(x)
x = self.pool(x)
x = x.view(-1, 8)
x = self.fc1(x)
x = self.softmax(x)
return x
# 初始化模型
model = TheModelClass()
# 初始化优化器
optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)
for layer_param in model.parameters():
print(layer_param)
sortir:
Parameter containing:
tensor([[[[ 0.2438, -0.0467, 0.0486],
[-0.1932, -0.2083, 0.3239],
[ 0.1712, 0.0379, -0.2381]]],
[[[ 0.2853, 0.0961, 0.0809],
[ 0.2526, 0.3138, -0.2243],
[-0.1627, -0.2958, -0.1995]]]], requires_grad=True)
Parameter containing:
tensor([-0.3287, -0.0686], requires_grad=True)
Parameter containing:
tensor([1., 1.], requires_grad=True)
Parameter containing:
tensor([0., 0.], requires_grad=True)
Parameter containing:
tensor([[ 0.2246, -0.1272, 0.0163, -0.3089, 0.3511, -0.0189, 0.3025, 0.0770],
[ 0.2964, 0.2050, 0.2879, 0.0237, -0.3424, 0.0346, -0.0659, -0.0115],
[ 0.1960, -0.2104, -0.2839, 0.0977, -0.2857, -0.0610, -0.3029, 0.1230],
[-0.2176, 0.2868, -0.2258, 0.2992, -0.2619, 0.3286, 0.0410, 0.0152]],
requires_grad=True)
Parameter containing:
tensor([-0.0623, 0.1708, -0.1836, -0.1411], requires_grad=True)
modèle.named_modules()
Renvoie le nom et la structure de chaque modèle de calque
import torch
import torch.nn as nn
import torch.optim as optim
# 定义模型
class TheModelClass(nn.Module):
def __init__(self):
super(TheModelClass, self).__init__()
self.conv1 = nn.Conv2d(1, 2, 3)
self.bn = nn.BatchNorm2d(num_features=2)
self.act = nn.ReLU()
self.pool = nn.MaxPool2d(2, 2)
self.fc1 = nn.Linear(8, 4)
self.softmax = nn.Softmax(dim=-1)
def forward(self, x):
x = self.conv1(x)
x = self.bn(x)
x = self.act(x)
x = self.pool(x)
x = x.view(-1, 8)
x = self.fc1(x)
x = self.softmax(x)
return x
# 初始化模型
model = TheModelClass()
# 初始化优化器
optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)
for name, module in model.named_modules():
print(name,'\n', module)
sortir:
TheModelClass(
(conv1): Conv2d(1, 2, kernel_size=(3, 3), stride=(1, 1))
(bn): BatchNorm2d(2, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(act): ReLU()
(pool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(fc1): Linear(in_features=8, out_features=4, bias=True)
(softmax): Softmax(dim=-1)
)
conv1
Conv2d(1, 2, kernel_size=(3, 3), stride=(1, 1))
bn
BatchNorm2d(2, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
act
ReLU()
pool
MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
fc1
Linear(in_features=8, out_features=4, bias=True)
softmax
Softmax(dim=-1)
Geler certaines couches / ne laisser que certaines couches apprendre
À l'heure actuelle, il existe une telle exigence : j'ai formé un réseau avec une grande quantité de données, puis j'ai besoin d'utiliser ce réseau formé pour tester la précision de nouveaux sujets. Lorsque le modèle de réseau reste inchangé, je souhaite utiliser la migration L'idée de l'apprentissage est de prendre les paramètres formés et de n'utiliser qu'une très petite quantité de données des nouveaux sujets pour former le responsable de la classification du modèle, et les autres couches du modèle n'ont pas besoin d'être formées. De cette façon, j'ai besoin de geler certaines couches du modèle, c'est-à-dire de ne former que certaines couches du modèle.
Grâce à l'analyse ci-dessus, j'utilise pour state_dict()
lire les paramètres du modèle et les enregistrer :
model_dict = model.state_dict()
Parce que state_dict()
les paramètres de modèle obtenus à l'aide de la fonction n'ont pas d' require_grad
attributs, et l'article indique également que state_dict()
les attributs require_grad du tenseur des paramètres de modèle stockés sont tous False .
Ensuite, nous supprimons les paramètres de la couche à former dans les paramètres du modèle enregistré, car ce n'est qu'après suppression, après avoir créé un nouvel objet modèle et chargé les paramètres du modèle précédent, que les paramètres de la couche à former ne seront pas La couverture des paramètres du modèle.
model_dict.pop('fc1.weight', None)
sortir:
tensor([[ 0.2246, -0.1272, 0.0163, -0.3089, 0.3511, -0.0189, 0.3025, 0.0770],
[ 0.2964, 0.2050, 0.2879, 0.0237, -0.3424, 0.0346, -0.0659, -0.0115],
[ 0.1960, -0.2104, -0.2839, 0.0977, -0.2857, -0.0610, -0.3029, 0.1230],
[-0.2176, 0.2868, -0.2258, 0.2992, -0.2619, 0.3286, 0.0410, 0.0152]])
model_dict.pop('fc1.bias', None)
tensor([-0.0623, 0.1708, -0.1836, -0.1411])
Ensuite, nous imprimons les paramètres du modèle enregistré :
for param_tensor in model_dict:
print(param_tensor, "\n", model_dict[param_tensor])
sortir:
conv1.weight
tensor([[[[ 0.2438, -0.0467, 0.0486],
[-0.1932, -0.2083, 0.3239],
[ 0.1712, 0.0379, -0.2381]]],
[[[ 0.2853, 0.0961, 0.0809],
[ 0.2526, 0.3138, -0.2243],
[-0.1627, -0.2958, -0.1995]]]])
conv1.bias
tensor([-0.3287, -0.0686])
bn.weight
tensor([1., 1.])
bn.bias
tensor([0., 0.])
bn.running_mean
tensor([0., 0.])
bn.running_var
tensor([1., 1.])
bn.num_batches_tracked
tensor(0)
On constate que les paramètres du calque que nous avons supprimé ont disparu.
Ensuite, nous créons un nouvel objet modèle et chargeons les paramètres du modèle précédemment enregistré dans le nouvel objet modèle :
model_ = TheModelClass()
model_.load_state_dict(model_dict, strict=False)
sortir:
_IncompatibleKeys(missing_keys=['fc1.weight', 'fc1.bias'], unexpected_keys=[])
Voyons ensuite à quoi ressemblent les propriétés des paramètres du nouvel objet modèlerequire_grad
:
model_dict_ = model_.named_parameters()
pour layer_name, layer_param dans model_dict_ :
print(layer_name, "\n", layer_param)
sortir:
conv1.weight
Parameter containing:
tensor([[[[ 0.2438, -0.0467, 0.0486],
[-0.1932, -0.2083, 0.3239],
[ 0.1712, 0.0379, -0.2381]]],
[[[ 0.2853, 0.0961, 0.0809],
[ 0.2526, 0.3138, -0.2243],
[-0.1627, -0.2958, -0.1995]]]], requires_grad=True)
conv1.bias
Parameter containing:
tensor([-0.3287, -0.0686], requires_grad=True)
bn.weight
Parameter containing:
tensor([1., 1.], requires_grad=True)
bn.bias
Parameter containing:
tensor([0., 0.], requires_grad=True)
fc1.weight
Parameter containing:
tensor([[-0.2306, -0.3159, -0.3105, -0.3051, 0.2721, -0.0691, 0.2208, -0.1724],
[-0.0238, -0.1555, 0.2341, -0.2668, 0.3143, 0.1433, 0.3140, -0.2014],
[ 0.0696, -0.0250, 0.0316, -0.1065, 0.2260, -0.1009, -0.1990, -0.1758],
[-0.1782, -0.2045, -0.3030, 0.2643, 0.1951, -0.2213, -0.0040, 0.1542]],
requires_grad=True)
fc1.bias
Parameter containing:
tensor([-0.0472, -0.0569, -0.1912, -0.2139], requires_grad=True)
require_grad
Nous pouvons voir que les paramètres du modèle précédent ont été chargés dans le nouvel objet modèle, mais les attributs des nouveaux paramètres sont tous True , ce qui n'est pas ce que nous voulons.
À partir de l'analyse ci-dessus, nous pouvons voir que state_dict()
nous ne pouvons pas obtenir l'effet souhaité en lisant les paramètres du modèle, en les enregistrant, puis en les chargeant dans un nouvel objet de modèle. Nous avons également besoin d'autres opérations pour atteindre l'objectif.
Nous pouvons résoudre le problème ci-dessus de deux manières :
require_grad=Faux
Nous pouvons définir les propriétés des paramètres des couches qui n'ont pas besoin d'être apprises require_grad
sur False
model_dict_ = model_.named_parameters()
for layer_name, layer_param in model_dict_:
if 'fc1' in layer_name:
continue
else:
layer_param.requires_grad = False
Ensuite, nous regardons les paramètres du modèle :
for layer_param in model_.parameters():
print(layer_param)
sortir:
Parameter containing:
tensor([[[[ 0.2438, -0.0467, 0.0486],
[-0.1932, -0.2083, 0.3239],
[ 0.1712, 0.0379, -0.2381]]],
[[[ 0.2853, 0.0961, 0.0809],
[ 0.2526, 0.3138, -0.2243],
[-0.1627, -0.2958, -0.1995]]]])
Parameter containing:
tensor([-0.3287, -0.0686])
Parameter containing:
tensor([1., 1.])
Parameter containing:
tensor([0., 0.])
Parameter containing:
tensor([[ 0.0182, 0.1294, 0.0250, -0.1819, -0.2250, -0.2540, -0.2728, 0.2732],
[ 0.0167, -0.0969, 0.1498, -0.1844, 0.1387, 0.2436, 0.1278, -0.1875],
[-0.0408, 0.0786, 0.2352, 0.0277, 0.2571, 0.2782, 0.2505, -0.2454],
[ 0.3369, -0.0804, 0.2677, 0.0927, 0.0433, 0.1716, -0.1870, -0.1738]],
requires_grad=True)
Parameter containing:
tensor([0.1084, 0.3018, 0.1211, 0.1081], requires_grad=True)
Nous pouvons voir que les propriétés des paramètres des couches qui n'ont pas besoin d'être apprises require_grad
sont toutes passées à False .
Ensuite, ces paramètres peuvent être envoyés à l'optimiseur :
optimizer = optim.SGD(model_.parameters(), lr=0.001, momentum=0.9)
Définir les paramètres de mise à jour de l'optimiseur
Si vous ne souhaitez pas mettre à jour une certaine couche réseau, le plus simple est de ne pas mettre les paramètres de la couche réseau dans l'optimiseur :
optimizer = optim.SGD(model_.fc1.parameters(), lr=0.001, momentum=0.9)
Remarque : Les paramètres qui sont gelés à ce moment dérivent toujours pendant la rétropropagation, mais les paramètres ne sont pas mis à jour.
On peut voir que si cette méthode est adoptée, l'utilisation de la mémoire peut être réduite, et en même temps, si elle est utilisée à l'avance, require_grad=False
le modèle ignorera les paramètres qui n'ont pas besoin d'être calculés et améliorera la vitesse de calcul, donc ces deux méthodes peuvent être utilisées ensemble.
Les références
Notes d'étude PyTorch : utilisez state_dict pour enregistrer et charger des modèles