一个神经网络的典型训练过程如下:
- 定义包含一些可学习参数(或称为权重)的神经网络
- 在输入数据上迭代
- 通过网络处理输入,得到预测值
- 计算损失(预测值和正确答案的距离)
- 将梯度反向传播给网络参数
- 更新权重
定义网络
import torch
import torch.nn as nn
class Model(nn.Module):
def __init__(self):
super(Model,self).__init__()
self.conv1 = nn.Conv2d(1,20,5)
self.conv2 = nn.Conv2d(20,20,5)
def forward(self,x): #定义一个前向网络
x = nn.functional.relu(self.conv1(x))
return nn.functional.relu(self.conv2(x))
model = Model()
print(model)
在模型定义过程中,仅需定义forward函数,用于对张量进行一些操作和计算,而backward函数是在使用autograd时自动定义的,用于计算导数。
模型参数
模型的学习参数:model.parameters()
params = list(model.parameters())
print(params[0].size()) # conv1的权重
torch.nn 只支持小批量的数据处理
损失函数
torch.nn 中包含很多损失函数,例如nn.MSELoss
criterion = torch.nn.MSELoss(size_average=True) # 平方误差损失
size_average 参数表示在计算loss时是计算所有样本还是部分样本
反向传播
一般用loss.backward()计算权重,需注意每次都需要清零现有的梯度。
model.zero_grad()
loss.backward()
更新权重
最简单的权重更新方法是随机梯度下降算法,尝试用Python实现:
lr=0.1
for f in model.parameters():
f.data.sub_(f.grad.data *lr)
在torch.optim包中封装了各种不同的优化算法,如:SGD、Nesterov-SGD、Adam、RMSProp等。
import torch.optim as optim
# 创建更新函数器
optimizer = optim.SGD(model.parameters(),lr=0.1)
# 在训练的迭代中:
optimizer.zero_grad() # 清零梯度缓存
output = model(input)
loss = criterion(output, target)
loss.backward()
optimizer.step() # 更新参数
optimizer.step() 一旦梯度被计算时(backward()),优化函数即可被调用;
backward 和 optimizer 之间的交互:
loss.backward() 可以获得所有参数的梯度,而定义optimizer时将模型的参数输入至优化器中,故r每次更新optimize时均会将模型的参数做一次更新,这样就将反向梯度计算和参数更新联系起来了。
参考资料
1)https://pytorch.apachecn.org/docs/1.0/#/blitz_neural_networks_tutorial