简介
在进行这部分时,会存在一些疑惑,针对以下疑惑进行解答。
问题一:实际上在固定参数的时候,大家会有疑惑,既然使用这种方式固定冻结网络参数是否存在固定的高层网络,但是低层网络的参数不会更新呢?
答:实际上固定网络参数只是让需要固定的层的参数不再自己保留梯度,但是梯度值仍会计算,即进行方向传播时仍然会可以进行低层网络参数的更新。required_grad
属性只是控制是否保留梯度而已,但仍然会计算该梯度值
问题二:是否只将需要训练层的参数传播到优化器里optimter
就可以实现,不需要进行固定部分呢?
答:实际上不固定里边的梯度属性required_grad
的话,需要固定部分的参数是一直在进行变化的,虽然没有参与参数的更新。
大家在学习pytorch
时,可能想利用pytorch
进行fine-tune
,但是又烦恼于参数的加载问题。下面我将讲诉我的使用心得。
Step1: 加载预训练模型,并去除需要再次训练的层
注意:需要重新训练的层的名字要和之前的不同。
model=resnet()#自己构建的模型,以resnet为例
model_dict = model.state_dict()
pretrained_dict = torch.load('xxx.pkl')
pretrained_dict = {k: v for k, v in pretrained_dict.items() if k in model_dict}
model_dict.update(pretrained_dict)
model.load_state_dict(model_dict)
Step2: 固定部分参数
#k是可训练参数的名字,v是包含可训练参数的一个实体
#可以先print(k),找到自己想进行调整的层,并将该层的名字加入到if语句中:
for k,v in model.named_parameters():
if k!='xxx.weight' and k!='xxx.bias' :
v.requires_grad=False#固定参数
Step3:训练部分参数
#将要训练的参数放入优化器
optimizer2=torch.optim.Adam(params=[model.xxx.weight,model.xxx.bias],lr=learning_rate,betas=(0.9,0.999),weight_decay=1e-5)
Step4:检查部分参数是否固定
debug
之后,程序正常运行,最好检查一下网络的参数是否真的被固定了,如何没固定,网络的状态接近于重新训练,可能会导致网络性能不稳定,也没办法得到想要得到的性能提升。
for k,v in model.named_parameters():
if k!='xxx.weight' and k!='xxx.bias' :
print(v.requires_grad)#理想状态下,所有值都是False
需要注意的是,操作失误最大的影响是,loss
函数几乎不会发生变化,一直处于最开始的状态,这很可能是因为所有参数都被固定了。