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!
PyTorch guarda algunos parámetros del modelo y los carga en un nuevo modelo
- dictamen_estado
- Guarde el modelo en la ruta actual con el nombre test_state_dict.pth
- dictado ordenado
- Guarde algunos parámetros del modelo y cárguelos en un nuevo modelo
- La diferencia entre state_dict(), named_parameters(), model.parameter(), named_modules()
- Congele ciertas capas / deje que solo ciertas capas aprendan
- Referencias
dictamen_estado
Introducción a state_dict
state_dict
es 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_dict
el 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])
OrderedDict
dict
Una 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:
- 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;
- 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;
- 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_grad
atributos, 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_grad
Podemos 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_grad
a 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_grad
han 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=False
el 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