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,其他优化器实例、手动参数更新操作都可能导致参数变化。
结合这段代码具体分析:
- 代码里确实没把crf和fc的参数加入当前的
self.optimizer——对应crf的params字典没有被append到parameters列表里,所以这个AdamW不会处理这些参数; - 但代码只冻结了
image_model的参数,crf和fc的参数默认requires_grad=True,反向传播时会正常计算梯度; - 出现参数被训练的情况,大概率是训练流程里有其他更新逻辑:
- 项目中存在其他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
相关产品推荐
相关产品推荐

