PyTorch enregistre certains paramètres du modèle et les charge dans un nouveau modèle

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é!

état_dict

Introduction à state_dict

state_dictest 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_dictle 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])

OrderedDictdictUne 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 :

  1. 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 ;
  2. 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 ;
  3. 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_gradattributs, 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_gradNous 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_gradsur 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_gradsont 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=Falsele 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

Collections de conteneurs avancées Python – OrderedDict

Chargement du modèle de pré-formation Pytorch, modification de la structure du réseau et fixation d'une certaine couche de formation des paramètres, différentes couches utilisent différents taux d'apprentissage

Je suppose que tu aimes

Origine blog.csdn.net/qq_41990294/article/details/128942601
conseillé
Classement