Pytorch笔记(3)

九 损失函数和反向传播

9.1 损失函数

  1. L1loss- 直接求差
  2. MSEloss-均方差
  3. CrossEntropyLoss -交叉熵
    在这里插入图片描述
    我们定义一个分类的项目,要判断的目标为[person,dog,cat],它们组成为class[0,1,2],经过网络输出每个类别的概率x。例如,我们将dog的图片传递给网络,输出x=[0.1,0.2,0.3],对应的class=1,于是我们就可以去算交叉熵为:
    l o s s ( x , c l a s s ) = − 0.2 + l o g ( e 0.1 + e 0.2 + e 0.3 ) loss(x, class)=-0.2+log(e^{0.1}+e^{0.2}+e^{0.3}) loss(x,class)=0.2+log(e0.1+e0.2+e0.3)
    其中,loss的第一项代表:dog的概率越大,loss的值越小;loss的第二项表示:整体的概率预测不能都很大。

9.2 实践

import torch
from  torch.nn import L1Loss,MSELoss,CrossEntropyLoss


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

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

loss=L1Loss()
loss_mse=MSELoss()

result=loss(input,target)
result_mse=loss_mse(input,target)

print(result)
print(result_mse)

x=torch.tensor([0.1,0.2,0.3])
y=torch.tensor([1])
x=torch.reshape(x,(1,3))
torch_cross=CrossEntropyLoss()
result_cross=torch_cross(x,y)
print(result_cross)

9.3 反向传播
反向传播:计算每个需要优化的参数的梯度

import torch
import torchvision
from torch import nn
from torch.nn import Conv2d,MaxPool2d,Flatten,Linear,Sequential
from torch.utils.data import DataLoader

data_set=torchvision.datasets.CIFAR10(root="./CIFAR10",train=True,transform=torchvision.transforms.ToTensor(),download=True)
dataloader=DataLoader(data_set,batch_size=1)


class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.model1=Sequential(
            Conv2d(in_channels=3, out_channels=32, kernel_size=5, padding=2),
            MaxPool2d(kernel_size=2),
            Conv2d(in_channels=32, out_channels=32, kernel_size=5, padding=2),
            MaxPool2d(kernel_size=2),
            Conv2d(in_channels=32, out_channels=64, kernel_size=5, padding=2),
            MaxPool2d(kernel_size=2),
            Flatten(),
            Linear(in_features=1024, out_features=64),
            Linear(in_features=64, out_features=10)
        )
    def forward(self,x):
        x=self.model1(x)
        return x

loss=nn.CrossEntropyLoss()
tudui=Tudui()
for data in dataloader:
    imgs,target=data
    output=tudui(imgs)
    result_loss=loss(output,target)
    result_loss.backward()#对损失函数进行反向传播,计算每个参数的梯度


十 优化器

10.1 简介

  1. 构造对象
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)#传入参数,学习速率
optimizer = optim.Adam([var1, var2], lr=0.0001)
  1. 使用
for input, target in dataset:
    optimizer.zero_grad()#每次优化时,要把上一步计算的梯度归零
    output = model(input)
    loss = loss_fn(output, target)#计算损失函数
    loss.backward()#计算梯度
    optimizer.step()#根据梯度进行优化
  1. 实践
loss=nn.CrossEntropyLoss()
tudui=Tudui()
optim=torch.optim.SGD(tudui.parameters(),lr=0.01)

for epoch in range(20):
    running_loss=0.0
    for data in dataloader:
        imgs,target=data
        output=tudui(imgs)
        result_loss=loss(output,target)
        optim.zero_grad()
        result_loss.backward()#对损失函数进行反向传播,计算每个参数的梯度
        optim.step()
        running_loss+=result_loss
    print(running_loss)

十一 网络模型

10.1 导入网络模型

import torchvision
from torch import nn

#导入没有经过预训练的模型
vgg16=torchvision.models.vgg16(pretrained=False)
print(vgg16)

#在现有的模型上增加层数
vgg16.classifier.add_module("add_linear",nn.Linear(1000,100))
vgg16.add_module("add_linear2",nn.Linear(100,10))
print(vgg16)

#修改现有的模型
vgg16.classifier[6]=nn.Linear(4096,10)
print(vgg16)

10.2 模型的保存与加载
注意:在用方式一进行保存自己写的模型时,必须导入自己模型的定义,才能够加载模型。或者使用from model_save import * 将模型的定义导入,model_save 是.py的文件名

import torch
import torchvision
from model_save import *
vgg16=torchvision.models.vgg16(pretrained=False)

#保存方式一:保存模型结构和参数
torch.save(vgg16,"vgg16_method.pth")

#保存方式一的加载
vgg16_loader=torch.load("vgg16_method.pth")
#保存方式二的缺点:在加载自己写的模型时,必须将类的定义一起写上,才能够加载模型


#保存方式二:只保存模型参数(官方推荐)
torch.save(vgg16.state_dict(),"vgg16_method2.pth")#把模型参数保存成字典形式

#保存方式二的加载
vgg16.load_state_dict(torch.load("vgg16_method2.pth"))

十二 完整的模型训练套路

  1. 将我们之前定义好的网络保存成文件,训练的时候方便导入。同时,在写模型时会创建一个1的输入,查看输出的是否为我们需要的格式
import torch
from torch import nn, tensor
from torch.nn import Conv2d,MaxPool2d,Flatten,Linear,Sequential

#搭建神经网络
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.model1=Sequential(
            Conv2d(in_channels=3, out_channels=32, kernel_size=5, padding=2),
            MaxPool2d(kernel_size=2),
            Conv2d(in_channels=32, out_channels=32, kernel_size=5, padding=2),
            MaxPool2d(kernel_size=2),
            Conv2d(in_channels=32, out_channels=64, kernel_size=5, padding=2),
            MaxPool2d(kernel_size=2),
            Flatten(),
            Linear(in_features=1024, out_features=64),
            Linear(in_features=64, out_features=10)
        )
    def forward(self,x):
        x=self.model1(x)
        return x

if __name__ == '__main__':
    tudui=Tudui()
    intput=torch.ones([64,3,32,32])
    output=tudui(intput)
    print(output.shape)#输出torch.Size([64, 10])
  1. 完整训练
import  torchvision
import torch
from torch import nn
from torch.utils.data import DataLoader
from torch.nn import Conv2d,MaxPool2d,Flatten,Linear,Sequential
from torch.utils.tensorboard import  SummaryWriter
from  model_Tudui import *

#准备数据集
train_set=torchvision.datasets.CIFAR10(root="./CIFAR10",train=True,transform=torchvision.transforms.ToTensor(),download=True)
test_set=torchvision.datasets.CIFAR10(root="./CIFAR10",train=False,transform=torchvision.transforms.ToTensor(),download=True)


#length
train_length=len(train_set)
test_length=len(test_set)
print("训练集的长度为:{}".format(train_length))
print("测试集的长度为:{}".format(test_length))

#加载数据集
train_dataloder=DataLoader(train_set,batch_size=64)
test_dataloder=DataLoader(test_set,batch_size=64)

#创建网络模型
tudui=Tudui()


#创建损失函数
loss_fn=nn.CrossEntropyLoss()

#定义优化器
learning_rate=1e-2
optimizer=torch.optim.SGD(tudui.parameters(),learning_rate)

#设置训练网络的参数
total_train_step=0
total_test_step=0
epoch=10

#添加tensorboard
writer=SummaryWriter("logs")

for i in range(epoch):
    print("----第{}轮开始----".format(i+1))

    #训练步骤开始
    for data in train_dataloder:
        imgs, targets=data
        outputs=tudui(imgs)
        loss=loss_fn(outputs,targets)

        #优化器优化模型
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        total_train_step+=1
        if total_train_step %100==0:
            print("训练次数:{},LOSS:{}".format(total_train_step,loss.item()))#加item的时候不会出现类型
            writer.add_scalar("train_loss",loss.item(),total_train_step)#保存训练的loss

    #测试步骤开始
    total_test_loss=0
    with torch.no_grad():
        for data in test_dataloder:
            imgs,targets=data
            outputs=tudui(imgs)
            loss=loss_fn(outputs,targets)
            total_test_loss+=loss.item()
    print("整体测试集上的loss为:{}".format(total_test_loss))
    writer.add_scalar("test_loss",total_test_loss,total_test_step)
    total_test_step+=1

    torch.save(tudui,"./Tuduimodel/Tuduimodel{}.pth".format(i))
    print("模型已保存")

writer.close()
  1. 分类问题的正确率
    在分类问题上,从网络上输出的是每个类别的概率。例如二分类问题,有两张图片: o u t p u t = [ 0.1 , 0.3 ] , [ 0.2 , 0.4 ] output=[0.1,0.3],[0.2,0.4] output=[0.1,0.3][0.2,0.4]代表这两张图片是第二类的可能性大,它预测的类别为: p r e d s = [ 1 , 1 ] preds=[1,1] preds=[1,1]而它的实际类别为: t a r g e t = [ 0 , 1 ] target=[0,1] target=[0,1]那么它预测的成功率就是50% p r e d = = t a r g e t − − > [ f a l s e , t r u e ] pred==target -->[false,true] pred==target>[false,true]要实现从概率到类别的转换,就要利用 p r e d s = o u t p u t . a r g m a x ( 1 ) preds=output.argmax(1) preds=output.argmax(1)1代表是横向的比较,0代表纵向比较。
 #测试步骤开始
    total_test_loss=0
    total_accuracy=0
    with torch.no_grad():
        for data in test_dataloder:#一个data是一个batch,一个dataloader是全部的数据
            imgs,targets=data
            outputs=tudui(imgs)

            loss=loss_fn(outputs,targets)
            total_test_loss+=loss.item()
            accuracy=(outputs.argmax(1)==targets).sum()#accuracy保存一个batch里面配对的个数
            total_accuracy+=accuracy#保存全部数据配对的个数

    print("整体测试集上的loss为:{}".format(total_test_loss))
    print("整体测试集上的正确率为:{}".format(total_accuracy/test_length))
    writer.add_scalar("test_loss",total_test_loss,total_test_step)
    total_test_step+=1
  1. 利用GPU进行训练一
#网络模型
tudui=Tudui()
tudui.cuda()

#损失函数
loss_fn=loss_fn.cuda()

#数据
imgs,target=data
imgs=imgs.cuda()
target=target.cuda()

  1. 利用GPU训练二
devcie=torch.device("cuda")

#网络模型
tudui=Tudui()
tudui.to(device)

#损失函数
loss_fn=loss_fn.to(device)

#数据
imgs,target=data
imgs=imgs.to(device)
target=target.to(device)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值