You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyTorch中未加入Optimizer的模型参数为何仍可训练?

为什么未加入Optimizer的模型参数仍能被训练?

我一直以为模型参数如果不加入Optimizer就没法训练,但最近运行一个项目时发现,明明没把crf和fc的参数加入Optimizer的参数列表,这些参数居然还能被更新。相关代码如下:

def multiModal_before_train(self):
    # bert lr
    parameters = []
    params = {'lr':self.args.lr, 'weight_decay':1e-2}
    params['params'] = []
    for name, param in self.model.named_parameters():
        if 'bert' in name:
            params['params'].append(param)
    parameters.append(params)

    # prompt lr
    params = {'lr':self.args.lr, 'weight_decay':1e-2}
    params['params'] = []
    for name, param in self.model.named_parameters():
        if 'encoder_conv' in name or 'gates' in name:
            params['params'].append(param)
    parameters.append(params)

    # crf lr
    params = {'lr':5e-2, 'weight_decay':1e-2}
    params['params'] = []
    for name, param in self.model.named_parameters():
        if 'crf' in name or name.startswith('fc'):
            params['params'].append(param)

    self.optimizer = optim.AdamW(parameters)

    for name, par in self.model.named_parameters(): # freeze resnet
        if 'image_model' in name:   par.requires_grad = False

    self.scheduler = get_linear_schedule_with_warmup(optimizer=self.optimizer, 
                                                        num_warmup_steps=self.args.warmup_ratio*self.train_num_steps, 
                                                        num_training_steps=self.train_num_steps)
    self.model.to(self.args.device)

核心原因

PyTorch里参数是否会被更新,核心看两个点:

  • 参数的requires_grad是否为True:只要这个属性是True,反向传播时就会计算并存储梯度;
  • 是否有逻辑触发了参数更新:不一定是你当前的这个Optimizer,其他优化器实例、手动参数更新操作都可能导致参数变化。

结合这段代码具体分析:

  1. 代码里确实没把crf和fc的参数加入当前的self.optimizer——对应crf的params字典没有被append到parameters列表里,所以这个AdamW不会处理这些参数;
  2. 但代码只冻结了image_model的参数,crf和fc的参数默认requires_grad=True,反向传播时会正常计算梯度;
  3. 出现参数被训练的情况,大概率是训练流程里有其他更新逻辑:
    • 项目中存在其他Optimizer实例,不小心包含了crf和fc的参数;
    • 训练循环里有手动更新参数的代码(比如直接执行param.data -= learning_rate * param.grad这类操作);
    • 模型结构有嵌套,子模块的参数被其他优化器接管了。

验证方法

你可以在训练循环中添加代码,验证这些参数的梯度状态和数值变化:

# 训练循环内,loss.backward()之后添加
for name, param in self.model.named_parameters():
    if 'crf' in name or name.startswith('fc'):
        print(f"{name} 梯度是否存在: {param.grad is not None}")
        print(f"{name} 参数样本值: {param.data[0][0]}")

内容的提问来源于stack exchange,提问作者ShiZhou Huang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 09:18:29