PyTorch guarda algunos parámetros del modelo y los carga en un nuevo modelo

Hace poco leí el artículo y vi que algunos programas primero entrenan un modelo, luego toman parte de la estructura del modelo entrenado en el nuevo modelo y luego usan los nuevos datos para entrenar el nuevo modelo, pero los parámetros de esa parte son Para mantenerlo, al principio pensé que era muy similar al aprendizaje por transferencia, porque no lo había estudiado en detalle, así que no estaba seguro, así que primero aprendí cómo realizar el plan de la tesis, y lo grabé aquí. Para futura referencia. En cuanto al aprendizaje por transferencia, estudiemos en el futuro, ¡debería usarse!

dictamen_estado

Introducción a state_dict

state_dictes un objeto de diccionario de Python que se puede usar para guardar parámetros de modelo, hiperparámetros e información de estado del optimizador (torch.optim). Cabe señalar que solo las capas con parámetros de aprendizaje (como capas convolucionales, capas lineales, etc.) tienen un state_dict.

Da una castaña para ilustrar el uso 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())

producción:

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

producción:

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]}]

Guardar y cargar state_dict

El state_dict del modelo puede torch.save()ser guardado por , es decir, solo se guardan los parámetros aprendidos del modelo, y los load_state_dict()parámetros del modelo pueden ser cargados y restaurados por . Las extensiones de guardado de modelos más comunes en PyTorch son ' .pt ' o ' .pth '.

Guarde el modelo en la ruta actual con el nombre 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()

Nota : la función load_state_dict() solo acepta 字典对象y no puede pasar directamente en la ruta del modelo, por lo que primero debe usar torch.load() para deserializar el state_dict guardado.

Guardar y cargar modelos completos

# 保存完整模型
torch.save(model, PATH)
 
# 加载完整模型
model = torch.load(PATH)
model.eval()

Aunque el código de este método parece más conciso que el del método state_dict, es menos flexible. Porque la función torch.save() usa el módulo pickle de Python para la serialización, pero pickle no puede guardar el modelo en sí, pero guarda la ruta del archivo que contiene la clase, que se usará cuando se cargue el modelo. Entonces, cuando el modelo se refactoriza en otros proyectos, pueden aparecer errores inesperados.

dictado ordenado

Si imprimimos state_dictel tipo de datos, obtendremos el siguiente resultado:

print(type(model.state_dict()))

producción:

<class 'collections.OrderedDict'>

El módulo de colecciones implementa contenedores específicos de objetos para proporcionar una alternativa a los contenedores integrados estándar de Python dict , list , set y tuple .

class collections.OrderedDict([items])

OrderedDictdictUna instancia de una subclase , un diccionario ordenado es como un diccionario normal, pero con algunas funciones adicionales relacionadas con las operaciones de clasificación.

Vale la pena mencionar que después de python3.7 , la clase dict incorporada obtuvo la capacidad de recordar el orden de inserción, por lo que este contenedor no es tan importante.

Algunas diferencias de dict:

  1. Los dictados regulares están diseñados para ser muy buenos en las operaciones de mapeo. El seguimiento del pedido de inserción es secundario;
  2. OrderedDict está diseñado para ser bueno en operaciones de reordenación. La eficiencia del espacio, la velocidad de iteración y el rendimiento de las operaciones de actualización son secundarios;
  3. Algorítmicamente, OrderedDict puede manejar operaciones de reordenación frecuentes mejor que dict. Esto lo hace adecuado para realizar un seguimiento de los accesos recientes (por ejemplo, en un caché LRU);

Guarde algunos parámetros del modelo y cárguelos en un nuevo modelo

Para el modelo anterior, el diccionario de estado del modelo es:

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 solo queremos guardar los parámetros entrenados de conv1 , podemos hacer esto:

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())

Aquí, para la conveniencia de demostraciones posteriores, nuestra oración clave está escrita así:

save_state.update({
    
    param_tensor:torch.ones((model.state_dict()[param_tensor].size()))})

Pero cuando realmente guardamos, deberíamos escribir así:

save_state.update({
    
    param_tensor:model.state_dict()[param_tensor]})

Luego guarde el diccionario save_state :

PATH = './test_state_dict.pth'
torch.save(save_state, PATH)

Luego cargue el nuevo modelo y asigne los parámetros guardados al nuevo modelo:

model = TheModelClass()    # 首先通过代码获取模型结构
model.load_state_dict(torch.load(PATH), strict=False)   # 然后加载模型的state_dict

producción:

_IncompatibleKeys(missing_keys=['conv2.weight', 'conv2.bias', 'fc1.weight', 'fc1.bias', 'fc2.weight', 'fc2.bias', 'fc3.weight', 'fc3.bias'], unexpected_keys=[])

Aquí está el modo de inicio en caliente, configurando el parámetro estricto en Falso en la función load_state_dict() para ignorar los parámetros de las claves que no coinciden.

Veamos nuevamente los parámetros del nuevo modelo:

model.state_dict()['conv1.bias']

producción:

tensor([1., 1., 1., 1., 1., 1.])

Los parámetros guardados entre descubrimientos se han cargado en el nuevo modelo.

Mire los otros parámetros en el modelo:

model.state_dict()['conv2.bias']

producción:

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

¡Puedes ver que otros parámetros son normales!

La diferencia entre state_dict(), named_parameters(), model.parameter(), named_modules()

modelo.state_dict()

state_dict()Es para almacenar layer_name y layer_param como claves en forma de dict . Contiene los nombres y parámetros de todas las capas, los parámetros del modelo almacenado tensor 的 require_grad 属性都是 False. El valor de salida no incluye require_grad. No puede usar model.state_dict() para obtener parámetros y establecer el atributo require_grad al arreglar una determinada capa .

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

producción:

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

modelo.named_parameters()

named_parameters()Es empaquetar nombre_capa y parámetro_capa en una tupla y luego almacenarla en la lista.
Guarde solo los parámetros que se pueden aprender y actualizar. model.named_parameters() Parámetros del modelo almacenados tensor 的 require_grad 属性都是True. A menudo se usa para corregir si los parámetros de una determinada capa están entrenados , generalmente a través de model.named_parameters() para obtener parámetros y establecer el atributo 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)

producción:

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)

modelo.parámetro()

parameter()Solo se devuelven los parámetros, no se incluye layer_name . 返回结果包含 require_grad,且均为 Ture, que se debe principalmente a que los parámetros predeterminados deben aprenderse cuando se crea la red, es decir, require_grad es todo 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)

producción:

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)

modelo.módulos_nombrados()

Devuelve el nombre y la estructura de cada modelo de capa.

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)

producción:

 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)

Congele ciertas capas / deje que solo ciertas capas aprendan

En la actualidad, existe tal requisito: he entrenado una red con una gran cantidad de datos, y luego necesito usar esta red entrenada para probar la precisión de nuevos sujetos. Cuando el modelo de red permanece sin cambios, quiero usar la migración La idea de aprender es tomar los parámetros entrenados y solo necesita usar una cantidad muy pequeña de datos de los nuevos sujetos para entrenar el cabezal de clasificación del modelo, y las otras capas del modelo no necesitan ser entrenadas. De esta manera necesito congelar algunas capas del modelo, es decir, solo entrenar algunas capas del modelo.

A través del análisis anterior, suelo state_dict()leer los parámetros del modelo y guardarlos:

model_dict = model.state_dict()

Porque state_dict()los parámetros del modelo obtenidos mediante el uso de la función no tienen require_gradatributos, y el artículo también decía que state_dict()los atributos require_grad del tensor de parámetros del modelo almacenado son todos False .

Luego eliminamos los parámetros de la capa a entrenar en los parámetros del modelo guardado, porque solo después de la eliminación, después de crear un nuevo objeto de modelo y cargar los parámetros del modelo anterior, los parámetros de la capa a entrenar no serán eliminado La cobertura de parámetros del modelo.

model_dict.pop('fc1.weight', None)

producción:

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

Luego imprimimos los parámetros del modelo guardado:

for param_tensor in model_dict:
    print(param_tensor, "\n", model_dict[param_tensor])

producción:

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)

Se encuentra que los parámetros de la capa que eliminamos se han ido.

Luego creamos un nuevo objeto de modelo y cargamos los parámetros del modelo previamente guardado en el nuevo objeto de modelo:

model_ = TheModelClass()
model_.load_state_dict(model_dict, strict=False)

producción:

_IncompatibleKeys(missing_keys=['fc1.weight', 'fc1.bias'], unexpected_keys=[])

Luego, veamos cómo se ven las propiedades de los parámetros del nuevo objeto modelo require_grad:

model_dict_ = model_.named_parameters()
for nombre_capa, parámetro_capa en modelo_dict_ :
print(nombre_capa, “\n”, parámetro_capa)

producción:

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_gradPodemos ver que los parámetros del modelo anterior se han cargado en el objeto del nuevo modelo, pero los atributos de los nuevos parámetros son todos True , que no es lo que queremos.

Del análisis anterior, podemos ver que state_dict()no podemos lograr el efecto que queremos leyendo los parámetros del modelo, guardándolos y luego cargándolos en un nuevo objeto de modelo. También necesitamos algunas otras operaciones para completar el objetivo.

Podemos resolver el problema anterior de dos maneras:

require_grad=Falso

Podemos establecer las propiedades de los parámetros de las capas que no necesitan aprenderse require_grada 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

Luego nos fijamos en los parámetros del modelo:

for layer_param in model_.parameters():
    print(layer_param)

producción:

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)

Podemos ver que las propiedades de los parámetros de las capas que no necesitan aprenderse require_gradhan cambiado todas a False .

Entonces estos parámetros se pueden enviar al optimizador:

optimizer = optim.SGD(model_.parameters(), lr=0.001, momentum=0.9)

Establecer parámetros de actualización del optimizador

Si no desea actualizar una determinada capa de red, la forma más sencilla es no poner los parámetros de la capa de red en el optimizador:

optimizer = optim.SGD(model_.fc1.parameters(), lr=0.001, momentum=0.9)

Nota: Los parámetros que están congelados en este momento todavía se derivan durante la retropropagación, pero los parámetros no se actualizan.

Se puede ver que si se adopta este método, se puede reducir el uso de memoria y, al mismo tiempo, si se usa con anticipación, require_grad=Falseel modelo saltará parámetros que no necesitan ser calculados y mejorará la velocidad de cálculo, por lo que estos Se pueden usar dos métodos juntos.

Referencias

Notas de estudio de PyTorch: use state_dict para guardar y cargar modelos

Colecciones de contenedores avanzados de Python – OrderedDict

Carga del modelo de preentrenamiento de Pytorch, modificación de la estructura de la red y fijación de una cierta capa de entrenamiento de parámetros, diferentes capas usan diferentes tasas de aprendizaje

Supongo que te gusta

Origin blog.csdn.net/qq_41990294/article/details/128942601
Recomendado
Clasificación