个人做法是用hotdog_w代替finetune_net.fc的第一行权重
for _ in range(0):
with torch.no_grad():
finetune_net.fc.weight[0] = hotdog_w.reshape(-1)
训练结果:loss 0.135, train acc 0.945, test acc 0.948
729.7 examples/sec on [device(type=‘cuda’, index=0)]
原始finetune结果:loss 0.170, train acc 0.940, test acc 0.929
614.3 examples/sec on [device(type=‘cuda’, index=0)]
1 Like
1.使用4e-4的学习率,速度变快了(176.2->190.3 examples/sec),准确度提升了(train acc 0.933->0.951)
2.更改了超参数:weight decay(0.001->0.01)
速度提升明显,泛化能力提升了,但是在训练集上的精确度下降了。
我觉得这样子是合理的,提升L2重要性,即降低了过拟合可能性,即提升了泛化能力
3.我尝试了给出的代码,但是报错element 0 of tensors does not require grad and does not have a grad_fn,这是说在d2l.train_batch_ch13中,反向传播时候遇到了没有梯度的张量
我猜想需要自己构建训练函数
4.单独切割出来热狗参数,em,我不会
检查将模型移动到gpu的代码是否在,没有的话显式地进行移动:
device = torch.device("cuda:0" is torch.cuda.is_available() else "cpu")
model.to(device)
如果已经如上面显式地进行了移动,还在cpu上的话。检查你的torch是否安装了支持gpu版本的,安装是否正确 ,命令行输入以下指令测试,返回True
的话就已经正确安装:
torch.cuda.is_available()
我是直接把训练函数的学习率调为0了,这样就不会更新了。你的报错应该是在train_batch_ch13中计算l.sum().backward()的时候报错了,我们已经把requires_grad参数设置为False了,如果还试图求backward的话,自然会报错。另一种方法就是去修改train_batch_ch13。
因为预训练模型是在 imagenet 上训练的,然后 imagenet 的 transform 中进行了这样的一个 normalize,所以在这个数据集也进行了同样参数的 normalize.
预训练模型本就是希望迁移原来学好的东西,提取特征的部分尽量不要改变.
所以进行同样的 normalize 也是希望对源模型减少扰动
1 Like
请问把这里的learning_rate改为0是不是就是不更新fc层前的参数?
关于练习第四题,事实上,ImageNet
数据集中有一个“热狗”类别。我们可以通过以下代码获取其输出层中的相应权重参数,但是我们怎样才能利用这个权重参数?
我是这样处理的,把热狗的[1,512]权重拿出来,再用xavier_uniform获得一个[1,512]的tensor,两者拼接成[2,512]的weight给微调模型
按理说精度应该会很高才对,但我的测试结果很差,我是哪一步操作不对吗,我尝试过互换两个[1,512]权重的位置,结果也是很差
Xiyu
November 21, 2023, 1:17pm
30
关于第四题,事实上我猜想应该通过修改fine-tuning中得最后一个全连接层来实现权重参数的利用,
即:
weight = pretrained_net.fc.weight
hotdog_w = torch.split(weight.data, 1, dim=0)[934]
finetune_net = torchvision.models.resnet18(pretrained=True)
finetune_net.fc = nn.Linear(hotdog_w.shape[1], 2)
nn.init.xavier_uniform_(finetune_net.fc.weight);
通过这个方法,最后的参数在训练集上略有上升。
hotdog & not-hotdog的想法是来自美剧硅谷里面的梗吧,哈哈哈哈
用pretrained加hotdog fc+微調 的結果最好,有0.934.
下面是我自己对于冻结除最后一层所有层参数进行finetune的代码,不知道对不对,lr=5e-5,内部不乘10,就是5e-5
先冻结所有参数,再替换最后一层
froze_net = torchvision.models.resnet18()
for param in froze_net.parameters():
param.requires_grad = False
froze_net.fc = nn.Linear(froze_net.fc.in_features, 2)
nn.init.xavier_uniform_(froze_net.fc.weight)
train_fine_tuning_with_froze(froze_net, 5e-5)
结果不是很好,lr我也用5e-4试过,loss太大了
element 0 of tensors does not require grad and does not have a grad_fn
的原因可能是你把全部的参数都给冻结了,那pytorch反向传播也很无奈啊:“你都冻结了我传播个啥”,我的修改方案是:
# 如何冻结预训练的参数?
# # 以下代码放在更改fc之前,或者主动声明fc的参数需要更新
# for param in finetune_net.parameters():
# param.requires_grad = False
# # 解冻fc的参数(非必要):
# finetune_net.fc.weight.requires_grad = True
# finetune_net.fc.bias.requires_grad = True
# 效果与微调模型相似,但是速度更快。
如果你在finetune_net.fc = nn.Linear(finetune_net.fc.in_features, 2)
前面用param.requires_grad = False
,此时fc因为你要更改他所以他的.requires_grad = True,但是如果你先更改了finetune_net.fc
然后又for循环把他冻结了那肯定没有参数可以被更新了,所以我就使用
finetune_net.fc.weight.requires_grad = True
finetune_net.fc.bias.requires_grad = True
来解冻fc了
预训练的热狗权重:
# 使用预训练的模型的热狗权重(acc比xavier初始化高多了)
weight = finetune_net.fc.weight
hotdog_w = torch.split(weight.data, 1, dim=0)[934] # torch.Size([1, 512])
finetune_net.fc = nn.Linear(finetune_net.fc.in_features, 2)
not_hotdog_w = torch.randn_like(hotdog_w)
finetune_net.fc.weight.data = torch.cat((hotdog_w, not_hotdog_w), dim=0)
finetune_net.fc.bias.data.fill_(0)
Saminey
September 25, 2024, 3:36pm
37
finetune_net = torchvision.models.resnet18(pretrained = True)当从torchviion中导入与训练模型时,python会提示 Arguments other than a weight enum or None
for ‘weights’ are deprecated,因为pretrained在0.15以后的版本后会被删除,避免以上err,可以使用’‘weights= torchvision.models.ResNet18_Weights.DEFAULT’‘或者’‘weights=‘DEFAULT’’'来进行代替,参考资料如上:[1]. 模型和预训练权重 - Torchvision 0.19 文档 - PyTorch 中文 [2]. resnet18 — Torchvision main documentation (pytorch.org)