【PyTorch基础】
文章目录
参考教程 https://www.jianshu.com/p/aee6a3d72014
搭建一个简单的网络
import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
class mymodel(nn.Module):
def __init__(self):
super(mymodel, self).__init__()
self.conv1 = nn.Conv2d(3, 6, 5) # in_channels, out_channels, kernel_size
self.pool = nn.MaxPool2d(2,2)
self.conv2 = nn.Conv2d(6, 16, 5)
self.fc = nn.Linear(16*5*5, 120)
def forward(self, x):
out = self.pool(F.relu(self.conv1(x)))
out = self.pool(F.relu(self.conv2(out)))
print(out.shape)
out = out.view(-1, 16*5*5)
out = F.relu(self.fc(out))
return out
model = mymodel() # 初始化模型
print(model.parameters()) # 打印模型参数(是一个生成器)
for param in model.state_dict():
print(param, "\t", model.state_dict()[param].size()) # 打印模型参数
optimizer = optim.SGD(model.parameters(),lr=0.001, momentum=0.9) # 初始化优化器
for var in optimizer.state_dict(): # 打印优化器参数
print(var, "\t", optimizer.state_dict()[var])
使用优化器是用来训练网络的,optim优化器的定义在 https://github.com/pytorch/pytorch/tree/master/torch/optim 可以使用Adam,SGD等多种优化器。
构造优化器
https://blog.csdn.net/gdymind/article/details/82708920
要构造一个optimizer,需要使用一个用来包含所有参数(Tensor形式)的iterable,把相关参数(如learning rate、weight decay等)装进去。
注意,如果想要使用.cuda()方法来将model移到GPU中,一定要确保这一步在构造Optimizer之前。因为调用.cuda()之后,model里面的参数已经不是之前的参数了。
将需要训练的参数加入优化器
optimizer = optim.SGD(params=model.parameters(), lr = 0.01, momentum = 0.9) # 将模型的所有参数都加进去
optimizer = optim.SGD(params=model.classifier.parameters(), lr = 0.01, momentum = 0.9) # 指定模型的classifier层的参数,加入优化器
optimizer = optim.Adam(params=[var1, var2], lr = 0.0001) # 加入[var1, var2]
单独指定参数
也可以用一个dict的iterable指定参数。这里的每个dict都必须要params这个key,params包含它所属的参数列表。除此之外的key必须它的Optimizer(如SGD)里面有的参数。
这在针对特定部分进行操作时很有用。比如只希望给指定的几个层单独设置学习率:
optim.SGD([
{'params': model.base.parameters()},
{'params': model.classifier.parameters(), 'lr': 0.001}
],
lr = 0.01, momentum = 0.9)
在上面这段代码中model.base将会使用默认学习率0.01,而model.classifier的参数蒋欢使用0.001的学习率。
使用optimizer.step()进行单次优化
所有optimizer都实现了step()方法,调用optimizer.step()方法可以更新参数:
for input, target in dataset:
optimizer.zero_grad() # 每个mini-batch使用之前,optimzier使用之前需要zero清零一下,因为如果不清零,那么使用的这个grad就得同上一个mini-batch有关
output = model(input)
loss = cal_loss(target, output) # 计算损失函数
loss.backward()
optimizer.step() # optimizer更新参数空间需要基于反向梯度,因此要先进行loss.backward()这个回传操作
关于loss.backward()
参考 https://blog.csdn.net/douhaoexia/article/details/78821428 讲的十分详细
这里需要注意:
- 只有标量才可以使用backward()
- 对于需要backward()的变量,必须满足requires_grad = True,否则会报错。
- 创建的tensor默认requires_grad = False,需要在创建时指定,例如
my_tensor = torch.zeros(3, 4, requires_grad=True)
,也可以在创建后对其修改,例如existing_tensor.requires_grad_()
或existing_tensor.requires_grad()
。 - 对于继承自 nn.Module 的某一网络 net 或网络层,定义好后,发现 默认情况下,net.paramters 的 requires_grad 就是 True 的
pytorch0.4开始合并Tensor和Variable,torch.Tensor 能够像之前的Variable一样追踪历史和反向传播。Variable仍能够正常工作,但是返回的是Tensor。所以在0.4的代码中,不需要使用Variable了。(参考 )
optimizer.step() 和scheduler.step()的区别
https://blog.csdn.net/qq_20622615/article/details/83150963
https://blog.csdn.net/xiaoxifei/article/details/87797935
optimizer.step()通常用在每个mini-batch之中,而scheduler.step()通常用在epoch大循环里面。
只有用了optimizer.step(),模型才会更新,而scheduler.step()是对lr进行调整。
在scheduler的step_size表示scheduler.step()每调用step_size次,对应的学习率就会按照策略调整一次。所以如果scheduler.step()是放在mini-batch里面,那么step_size指的是经过这么多次迭代,学习率改变一次。
模型保存和读取
参考这里 https://blog.csdn.net/aaon22357/article/details/82696938
加载不同的模型
加载他人训练的模型,可能需要忽略部分层。则将load_state_dict方法的strict参数设置为False。(strict参数的意思是,参数名字必须完全对应才能加载)例如:
torch.save(model1.state_dict(),PATH) # 把model1的参数保存到PATH中(只存了参数,没有存模型)
model2.load_state_dict(torch.load(PATH), strict=False) # 将model1模型的参数导入到model2中
加载不同设备的模型
将GPU保存的模型加载到CPU上
将torch.load()函数中的map_location参数设置为torch.device(‘cpu’),例如:
device = torch.device('cpu')
model.load_state_dict(torch.load(PATH, map_location=device))
将由GPU保存的模型加载到GPU上
确保对输入的tensors调用input = input.to(device)方法
device = torch.device("cuda")
model.load_state_dict(torch.load(PATH))
model.to(device) # 将模型 load进来后要转到cuda上去
上一篇: 卷积神经网络:定义卷积层
下一篇: Pytorch基础