1. python for循环的坑
无法修改for中i的值
for i in range(4):
print(i)
i=i+1
实际输出还是0,1,2,3
只能通过变成while语句来实现
2.Pytorch设置不同学习率
我在看论文的过程中,发现了大多数作者针对模型刚开始会采用大的学习率,随着epoch或者层数的增加,而不断改变学习率的大小,我就很感兴趣(离全职调参又近了一步)。
2.1针对不同层
Pytorch不同层设置不同学习率_呆呆象呆呆的博客-CSDN博客_pytorch 不同学习率
这是简单的网络层
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.net1 = nn.Linear(2,10)
self.net2 = nn.Linear(10,1)
def forward(self, x):
x = self.net1(x)
x = self.net2(x)
return x
net = Net()
# 以字典的形式进行对不同参数组的所需要的优化参数定义
optimizer = optim.SGD([
{"params":net.net1.parameters()},
{"params":net.net1.parameters(),"lr":1e-5},],
lr=1e-2, #默认参数
)
针对resnet101
model = torchvision.models.resnet101(pretrained=True)
large_lr_layers = list(map(id,model.fc.parameters()))
small_lr_layers = filter(lambda p:id(p) not in large_lr_layers,model.parameters())
optimizer = torch.optim.SGD([
{"params":large_lr_layers},
{"params":small_lr_layers,"lr":1e-4}
],lr = 1e-2,momenum=0.9)
针对卷积层
class net(nn.Module):
def __init__(self):
super(net, self).__init__()
self.conv1 = nn.Conv2d(3, 64, 1)
self.conv2 = nn.Conv2d(64, 64, 1)
self.conv3 = nn.Conv2d(64, 64, 1)
self.conv4 = nn.Conv2d(64, 64, 1)
self.conv5 = nn.Conv2d(64, 64, 1)
def forward(self, x):
out = conv5(conv4(conv3(conv2(conv1(x)))))
return out
net = net()
lr = 0.001
conv5_params = list(map(id, net.conv5.parameters()))
conv4_params = list(map(id, net.conv4.parameters()))
base_params = filter(lambda p: id(p) not in conv5_params + conv4_params,
net.parameters())
optimizer = torch.optim.SGD([
{'params': base_params},
{'params': net.conv5.parameters(), 'lr': lr * 100},
{'params': net.conv4.parameters(), 'lr': lr * 100},
, lr=lr, momentum=0.9)
2.2针对不同epoch
更多细节可以查阅:Pytorch中的学习率调整方法_卡卡南安的博客-CSDN博客_pytorch 学习率调整
这边简单罗列两个
更新策略:每过step_size个epoch,做一次学习率更新,更新后的学习率为:new_lr = initial_lr *gamma
其中optimizer参数为优化器,需要提前设定,例如:SGD、Adam等
from torch.optim import lr_scheduler
exp_lr_scheduler = lr_scheduler.StepLR(optimizer, step_size=step_size, gamma=0.1)
更新策略:每遇到milestones中的epoch,做一次学习率更新,更新后的学习率为:
new_lr = initial_lr *gamma
from torch.optim import lr_scheduler
milestones = [40,60,80]
exp_lr_scheduler = lr_scheduler.MultiStepLR(optimizer, milestones, gamma=0.1)
3.GFLOPs
我看到论文会出现GFLOPs这个数值,在我印象中应该是用来表示运算的,也确实表示每秒10亿次的浮点运算数,应该是用来观察GPU的功耗情况!
4.迁移学习大致步骤
迁移学习就是通过别人训练好的大规模大Epoch的模型参数,来直接跑自己的数据,一般调节是针对模型的结构微调,以及最后的fc,改成自己最终想要分的类的个数,我这边按照cifar-10为例子大致过一下流程,代码还是很多的,自己找一下就行。
4.1下载数据集
4.2下载model.pth
比如resnet18.pth 里面应该放的是resnet18各个参数的权重比
resnet18总参数个数就达到了11181642
但是如果去最后一个fc,就可以降到5130
4.3冻结层,修改fc
就像之前提及的,需要在训练过程中只修改最后的fc即可
# 使用预训练模型
resnet = models.resnet18(pretrained=True)
# 冻结模型参数
for param in resnet.parameters():
param.requires_grad = False
# 修改最后的全连接层改为十分类
resnet.fc = nn.Linear(512, 10)
同样优化器也是只针对最后一层
optimizer = torch.optim.SGD(resnet.fc.parameters(), lr=1e-3, weight_decay=1e-3, momentum=0.9) # 优化器
别的内容都是正常训练过程!
5.划分训练集验证集
利用sklearn里面的函数
from sklearn.model_selection import train_test_split
train_data, test_data = train_test_split(train_data, test_size=0.2, random_state=3407)