模型引入损失函数
主要介绍三种
- L1Loss
- MSELoss(平方损失函数)
- CrossEntropyLoss(交叉熵损失函数)
L1Loss
对于训练得出的结果和实际的结果target
的作差绝对值作为损失,分为两种情况
- 求出的形式为平均值形式
mean
- 求出的形式为和的形式
sum
这个形式可以在reduction
中指定,默认为平均值mean
形式
我们可以看到其他的两个类的初始化参数已经废弃了,就reduction
还在使用了
我们可以看到需要input
和target
同维度,使用方法为
loss = nn.L1Loss()
input = torch.randn(3, 5, requires_grad=True)
target = torch.randn(3, 5)
output = loss(input, target)
output.backward()
MSELoss
为平方损失函数
具体的定义与L1Loss
相似,唯一的区别就是损失函数的计算变成了input和target差值的平方(L1是差值的绝对值)
CrossEntropyLoss
为交叉熵损失函数
具体的公式定义为
x[class]
代表预测正确的概率class
可以等同于我们之前的target
也分为平均值mean
与总和sum
的方式
使用方法为
>>> loss = nn.CrossEntropyLoss()
>>> input = torch.randn(3, 5, requires_grad=True)
>>> target = torch.empty(3, dtype=torch.long).random_(5)
>>> output = loss(input, target)
>>> output.backward()
梯度下降
当我们求得模型的损失函数后,使用backward()
方法可以计算出本次参数更新的梯度值,这时候我们就需要使用梯度下降来对我们的模型参数进行更新了,而在Pytorch
中,我们主要是通过torch.optim
中的优化器算法
来进行梯度下降的
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
optimizer = optim.Adam([var1, var2], lr=0.0001)
上面给出了优化器中的两种算法SGD
与Adam
,其中我们主要讲解一下SGD
其中两个参数是所有优化器所必需的
params
是我们创建的神经网络的参数lr
代表learn rate
,使我们梯度下降的学习率
而其他的参数都是不同的优化器算法所特有的
损失函数和梯度下降的具体代码实现
net = Net()
criterion = nn.CrossEntropyLoss() # 损失函数
optim = torch.optim.SGD(net.parameters(), lr=0.1)
# 将整个CIFAR10数据集进行20次循环训练
for epoch in range(20):
res_loss = 0.0
for data in dataLoader:
optim.zero_grad()
img, target = data
output = net(img) # 模型经过CNN后得出的概率值
loss = criterion(output, target) # 根据从模型训练出来的概率值与目标值target进行交叉熵损失函数求解
loss.backward() # 计算本次参数的梯度
optim.step()
res_loss = res_loss + loss
print(res_loss)
上面代码为训练20次的神经网络代码
加入CIFAR10模型
import torch
import torchvision
from torch import nn
from torch.utils.tensorboard import SummaryWriter
dataset = torchvision.datasets.CIFAR10('./dataset', train=False, download=True,
transform=torchvision.transforms.ToTensor())
dataLoader = torch.utils.data.DataLoader(dataset, batch_size=64)
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(3, 32, kernel_size=5, padding=2)
self.pool1 = nn.MaxPool2d(2)
self.conv2 = nn.Conv2d(32, 32, kernel_size=5, padding=2)
self.pool2 = nn.MaxPool2d(2)
self.conv3 = nn.Conv2d(32, 64, kernel_size=5, padding=2)
self.pool3 = nn.MaxPool2d(2)
self.flatten = nn.Flatten()
self.fc1 = nn.Linear(1024, 64)
self.fc2 = nn.Linear(64, 10)
def forward(self, x):
x = self.conv1(x)
x = self.pool1(x)
x = self.conv2(x)
x = self.pool2(x)
x = self.conv3(x)
x = self.pool3(x)
x = self.flatten(x)
x = self.fc1(x)
x = self.fc2(x)
return x
net = Net()
criterion = nn.CrossEntropyLoss() # 损失函数
optim = torch.optim.SGD(net.parameters(), lr=0.1)
# 将整个CIFAR10数据集进行20次循环训练
for epoch in range(20):
res_loss = 0.0
for data in dataLoader:
optim.zero_grad()
img, target = data
output = net(img) # 模型经过CNN后得出的概率值
loss = criterion(output, target) # 根据从模型训练出来的概率值与目标值target进行交叉熵损失函数求解
loss.backward() # 计算本次参数的梯度
optim.step()
res_loss = res_loss + loss
print(res_loss)
运行结果为: