3.损失函数,反向传播,优化器

文章目录

  • 前言
  • 一、损失函数
    • 1.L1Loss,MSFLoss
    • 2.交叉熵函数
  • 二、反向传播、优化器
    • 2.1优化器模板
    • 2.2自适应学习率模板
  • 三、对MNIST进行模型训练
  • 总结


前言

最近学会了如何使用pytorch搭建模型和训练模型,在查找官网资料和博客中也遇到了一些坑,因此写一下关于损失函数等相关问题的研究

一、损失函数

损失函数是算法中比较重要的一部分,通常看论文比较关注的几个点就是网络模型、损失函数、创新点。常用损失函数的有

  • 平均绝对误差L1Loss
  • 均方误差MSFLoss
  • 交叉熵损失CROSSENTROPYLOSS

1.L1Loss,MSFLoss

该损失函数常用与回归问题
3.损失函数,反向传播,优化器_第1张图片
根据官方文档知道,他是结果与目标值进行相减后取绝对值。
注:input与target必须得有相同的维度

input = torch.tensor([1, 2, 3], dtype=torch.float32)
targets = torch.tensor([1, 2, 5], dtype=torch.float32)

input = torch.reshape(input, (1, 1, 1, 3))
targets = torch.reshape(targets, (1, 1, 1, 3))

loss = nn.L1Loss(reduction='mean')
#绝对值误差。'none':分别相减 'sum':相减后求和  'mean':对求和的结果再进行取平均值
result = loss(input, targets)
print(result)
--tensor(0.6667)

以上述数据均方误差结果:((1-1)2+(2-2)2+(3-5)2)/3

lose_mse = nn.MSELoss()
#平方差误差
result = lose_mse(input,targets)
print(result)
--tensor(1.3333)

2.交叉熵函数

这个在图像分类中使用最多,通常是来处理分类问题。
计算的方法如下:
在这里插入图片描述
比如举如下例子,目标检测的标签是0,loss值为
loss = -0.5 + ln(e0.5+e0.36+e0.23)= 0.9680

input = torch.tensor([0.5,0.36,0.23],dtype=torch.float32)
target = torch.tensor([0])
input = torch.reshape(input,shape=(1,3))
loss = nn.CrossEntropyLoss()
result = loss(input,target)
print(result)
--tensor(0.9680)

注:target的范围是从0开始的,其值不能超过当前分类的范围

二、反向传播、优化器

在上述损失函数中,我们均能得到当前模型的一个训练情况,通过损失值为下一步模型训练的参数进行梯度下降,找到一个合适的值,这个步骤就是反向传播,在模型训练时会用到。
使用损失函数的backward()方法即可进行反向传播,其次通常要使用优化器来优化模型参数。pytorch官网上给出的优化器一般使用模板如下:

2.1优化器模板

optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
#optimizer = optim.Adam([var1, var2], lr=0.0001)
for input, target in dataset:
    optimizer.zero_grad() #将上一步得到的参数梯度清零
    output = model(input)
    loss = loss_fn(output, target)
    loss.backward()
    optimizer.step()

在上述模型中使用的是学习率为0.01。在大多数情况下学习率不是一直不变的,特别是在训练的轮数较大时,学习率需要做出调整,一般采用自适应的学习率方法。pytorch采用的学习率方法和及其运算可以采纳这篇博客:
https://blog.csdn.net/XiaoyYidiaodiao/article/details/124678206
以下采用LambdaLR的方法进行自适应学习率算法。算法模板如下:

2.2自适应学习率模板

learning_rate = 1e-2
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)
lambda1 = lambda epoch: (epoch) // 2
scheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda=lambda1)
for epoch in range(epochs):
	train_data
	valid_data
	scheduler.step() 

通过对mnist数据集进行训练,学习率保持0.01和自适应学习率最终的loss值有不同,使用自适应学习率,该算法的收敛度更快。

三、对MNIST进行模型训练

import time
from turtle import pd

import torch.optim
import torchvision
from torch import nn, optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
import numpy as np
import matplotlib.pyplot as plt

start = time.perf_counter()

train_data = datasets.MNIST(root="./MNIST",
                            train=True,
                            transform=transforms.ToTensor(),
                            download=False)

test_data = datasets.MNIST(root="./MNIST",
                           train=False,
                           transform=transforms.ToTensor(),
                           download=False)

train_loader = DataLoader(dataset=train_data,
                          batch_size=64,
                          shuffle=True)

test_loader = DataLoader(dataset=test_data,
                         batch_size=64,
                         shuffle=True)


class mymodel(nn.Module):
    def __init__(self):
        super(mymodel, self).__init__()
        self.model1 = nn.Sequential(
            nn.Conv2d(in_channels=1, out_channels=32, kernel_size=3),
            nn.MaxPool2d(2),
            nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3),
            nn.MaxPool2d(2, stride=2),
            nn.Flatten(),
            nn.Linear(in_features=1600, out_features=64),
            nn.ReLU(),
            nn.Linear(in_features=64, out_features=10)
        )

    def forward(self, input):
        return self.model1(input)


model = mymodel()

loss = nn.CrossEntropyLoss()

iterations = 0

learning_rate = 1e-2
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)
lambda1 = lambda epoch: (epoch) // 2
scheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda=lambda1)

for epoch in range(20):
    running_loss = 0.0
    print(" -----------------the {} number of training epoch --------------".format(epoch))
    model.train()
    for data in train_loader:
        imgs, targets = data
        outputs = model(imgs)
        result_loss = loss(outputs, targets)
        optimizer.zero_grad()
        result_loss.backward()
        optimizer.step()
        running_loss += result_loss

        iterations += 1
        if iterations % 100 == 0:
            print(
                "Epoch: {} | Iteration: {} | lr: {} | loss: {} | np.mean(loss): {} "
                .format(epoch, iterations, optimizer.param_groups[0]['lr'],result_loss.item(),
                        np.mean(result_loss.item())))

    print("第", epoch, "次", running_loss)
    scheduler.step()

    if (epoch + 1) % 20 == 0:
        print("Save state, iter: {} ".format(iterations))
        torch.save(model.state_dict(), "lrmymodel{}.pth".format(epoch))


end = time.perf_counter()
runTime = end - start
print("运行时间:", runTime)

运行结果如图:
3.损失函数,反向传播,优化器_第2张图片
3.损失函数,反向传播,优化器_第3张图片

总结

本文讲解了常见的一些损失函数,对于交叉熵损失函数进行了重点描述,也讲了反向传播和优化器部分,同时采用自适应学习率算法能够加速loss的收敛情况。

你可能感兴趣的:(PyTorch笔记,深度学习,目标检测,计算机视觉,pytorch)