参考资料:
https://pytorch.org/tutorials/beginner/deep_learning_60min_blitz.html
第一部分 tensor + operator
第二部分 autograd
torch.Tnesor是包中的核心类,
.requires_grad = True,那么会自动跟踪所有运算,
.backward() 当你结束运算调用这个函数,就会自动计算梯度。
.grad 梯度会计算放到这里
.detach() 可以停止跟踪
with torch.no_grad(): 停止跟踪
上面的在评估模型的时候非常有用
Function类也是一个很重要的类别。
.grad_fn 是一个tensor被一个函数建立
随机数初始化:
在神经网络中,参数默认是进行随机初始化的,不同的初始化参数往往会导致不同的结果,当得到比较好的结果的时候,我们希望结果可以复现,在torch中,通过设置随机数种子可以达到这个目的:
1 2 3 4 5 6 7 8 9 10 11
| def set_seed(seed): torch.manual_seed(seed) torch.cuda.manual_seed(seed) torch.backends.cudnn.deterministic = True np.random.seed(seed) random.seed(seed)
|
在程序的入口处设置随机数种子
1.当我们训练了一个模型之后,需要将训练得到的模型进行保存。
1 2
| PATH = './cifar_net.pth' torch.save(net.state_dict(),PATH)
|
2.测试网络
1 2 3
| net = Net() net.load_state_dict(torch.load(PATH))
|
保存模型的方式不同。会导致模型有可能不同
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| torch.save(net,'./model.pth') torch.save(net.state_dict(),'./model-dict.pth')
net=torch.load('./model.pth') net.load_state_dict(torch.load('./model-dict.pth'))
net=net.eval() torch.save(net,'./model.pth') torch.save(net.state_dict(),'./model-dict.pth')
net_load1=torch.load('./model.pth') net_load1=net_load1.eval()
net_load2.load_state_dict(torch.load('./model-dict.pth')) net_load2=net_load2.eval()
|
model.state_dict()是浅拷贝,返回的参数依然会随着网络的训练而变化,需要deepcopy或者拷贝到硬盘中。
在state_dict中有下面四个内容:
1._paramters
nn.parameter.Paramter,也就是组成Module的参数。例如一个nn.Linear通常由weight和bias参数组成。它的特点是默认requires_grad=True,也就是说训练过程中需要反向传播的
2._buffers
不需要参与反向传播的参数
3._modules
torch.nn.Module类,你定义的所有网络结构都必须继承这个类。
4._state_dict_hooks
最后一种就是在读取state_dict时希望执行的操作,一般为空,所以不做考虑。
关于NLLLoss的代码说明:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import torch import torch.nn as nn import torch.nn.functional as F
torch.manual_seed(2019)
output = torch.randn(1, 3) target = torch.ones(1, dtype=torch.long).random_(3) print(output) print(target)
loss = F.nll_loss(output, target) print(loss)
criterion = nn.NLLLoss() loss = criterion(output, target) print(loss)
|
计算公式:loss(input, class) = -input[class]
公式理解:input = [-0.1187, 0.2110, 0.7463],target = [1],那么 loss = -0.2110
个人理解:感觉像是把 target 转换成 one-hot 编码,然后与 input 点乘得到的结果
如果 input 维度为 M x N,那么 loss 默认取 M 个 loss 的平均值,reduction=’none’ 表示显示全部 loss
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| import torch import torch.nn as nn import torch.nn.functional as F
torch.manual_seed(2019)
output = torch.randn(2, 3) target = torch.ones(2, dtype=torch.long).random_(3) print(output) print(target)
loss = F.nll_loss(output, target) print(loss)
criterion = nn.NLLLoss(reduction='none') loss = criterion(output, target) print(loss)
""" tensor([[-0.1187, 0.2110, 0.7463], [-0.6136, -0.1186, 1.5565]]) tensor([2, 0]) tensor(-0.0664) tensor([-0.7463, 0.6136]) """
|
那么CrossEntropyLoss和NLLLoss区别在于
CrossEntropyLoss = Softmax+Log+NLLLoss
还有
ignore_index 就是计算的时候忽略的标签的数值
梯度计算以及backward方法
tensor在torch中是一个n维数组,我们通过指定参数requires_grad = True来建立一个反向传播图,从而可以计算梯度。被称之为动态计算图Dynamic Computation Graph。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import torch import numpy as np
x = torch.randn(2,2,requires_grad=True)
x = torch.autograd.Variable(torch.Tensor([2,3]),requires_grad=True)
x = torch.tensor([2,3],requires_grad=True,dtype=torch.float64)
x = np.array([1,2,3],dtype=np.float64) x = torch.from_numpy(x) x.requires_grad = True
|
attention:
1.只有浮点型数据才有梯度,
tensor是PyTorch中的组建,Variable是对tensor的封装,操作和tensor一样,但是每个variable都有三个属性,包含了
1 2 3
| .data 数据 .grad 梯度 .grad_fn 变量的得到方式
|