详解迁移学习,模型参数冻结,优化器参数定义

前言

在使用预训练模型的时候能因为某些原因无需对模型的参数进行全部更新,这时候我们可能希望将其部分参数或者全部参数进行冻结。这里简单总结一些冻结模型参数的方法。

冻结参数的原理

requires_grad 属性的作用
在 PyTorch 中,每个 torch.Tensor 都有一个 requires_grad 属性,这个属性决定了该张量在反向传播过程中是否需要计算梯度。当 requires_gradTrue 时,PyTorch 会跟踪该张量上的所有操作,并在调用 backward() 方法时计算其梯度;当 requires_gradFalse 时,PyTorch 不会跟踪该张量的操作,也就不会计算其梯度。
在神经网络中,模型的参数本质上就是 torch.Tensor 对象,通过设置参数的 requires_grad 属性,我们可以控制哪些参数参与训练(即计算梯度并更新),哪些参数不参与训练(即冻结)。

模型参数全部冻结

import torch
import torch.nn as nn

model = nn.Sequential(
    nn.Linear(10, 20),
    nn.ReLU(),
    nn.Linear(20, 1)
)

for param in model.parameters():
    param.requires_grad = False
  • 原理:model.parameters() 是一个生成器,返回的是一个生成器对象,它会迭代返回模型中所有需要计算梯度的参数(即 requires_grad 为 True 的参数)。通过遍历这个生成器,将每个参数的 requires_grad 属性设置为 False,就可以实现整体冻结模型参数的目的。

模型参数部分冻结

import torch
import torch.nn as nn

class MyModel(nn.Module):
    def __init__(self):
        super(MyModel, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, kernel_size=3)
        self.fc1 = nn.Linear(16 * 10 * 10, 10)

    def forward(self, x):
        x = self.conv1(x)
        x = x.view(-1, 16 * 10 * 10)
        x = self.fc1(x)
        return x

model = MyModel()
for name, param in model.named_parameters():
    if 'conv' in name:
        param.requires_grad = False
  • 原理:model.named_parameters() 也是一个生成器,返回的也是一个生成器对象,每次迭代返回一个元组 (name, param),其中 name 是参数的名称(字符串类型),param 是对应的参数张量(torch.Tensor 类型)。通过检查参数名称中是否包含特定的字符串(如 ‘conv’),我们可以筛选出需要冻结的参数,并将其 requires_grad 属性设置为 False

冻结预训练模型部分层并修改最后一层

from torchvision.models import resnet18
import torch.nn as nn

model = resnet18(pretrained=True)

for param in model.parameters():
    param.requires_grad = False

num_ftrs = model.fc.in_features
model.fc = nn.Linear(num_ftrs, 1)
  • 原理:首先,通过遍历 model.parameters() 并将所有参数的 requires_grad 属性设置为 False,冻结了整个预训练模型的参数。然后,我们获取原最后一层全连接层的输入特征数 num_ftrs,并创建一个新的全连接层 nn.Linear(num_ftrs, 1) 替换原最后一层。新创建的层的参数的 requires_grad 属性默认是 True,因此只有这一层的参数会在训练时计算梯度并更新。

优化器

上面介绍了怎么冻结模型参数,冻结参数之后需要对模型的参数进行优化,常见的有两种参数方式,下面也一并介绍下。

优化器的作用

优化器的作用是根据计算得到的梯度来更新模型的参数,以最小化损失函数。在 PyTorch 中,常见的优化器有 SGD、Adam
等,它们都需要传入需要更新的参数。

直接传入参数生成器或参数列表

import torch
import torch.nn as nn
import torch.optim as optim

model = nn.Sequential(
    nn.Linear(10, 20),
    nn.ReLU(),
    nn.Linear(20, 1)
)

optimizer = optim.SGD(model[-1].parameters(), lr=0.001, momentum=0.9)
  • 原理:当我们直接将参数生成器(如 model[-1].parameters())或参数列表传递给优化器时,优化器会将这些参数视为一组,并使用相同的优化超参数(如学习率、动量等)来更新这些参数。在这个例子中,我们只传递了模型最后一层的参数,因此优化器只会更新最后一层的参数。
  • 注意:model[-1].parameters() 返回一个生成器对象,它会迭代返回模型最后一层的所有参数。

传入参数组字典列表

import torch
import torch.nn as nn
import torch.optim as optim

model = nn.Sequential(
    nn.Linear(10, 20),
    nn.ReLU(),
    nn.Linear(20, 1)
)

first_layer_params = list(model[0].parameters())
last_layer_params = list(model[2].parameters())

param_list = [
    {'params': first_layer_params, 'lr': 0.0001},
    {'params': last_layer_params, 'lr': 0.001}
]

optimizer = optim.Adam(param_list)
  • 原理:当我们需要为不同的参数组设置不同的优化超参数时,可以传入一个包含参数组字典的列表。每个字典代表一个参数组,其中 ‘params’ 键对应的值是该参数组的参数列表或参数生成器,还可以包含其他键值对来指定该参数组的特定超参数(如学习率、权重衰减等)。优化器会根据这些参数组的设置,对不同的参数组使用不同的超参数进行优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

I松风水月

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值