土堆学习(3)损失函数及完整项目

损失函数

L1LOSS

image-20230420201541594

MSELoss 平方差损失

image-20230420201951733

CrossEntropyLoss 交叉熵损失

通常用于分类问题中。其计算公式为:

image-20230420202539281

反向传播利用误差计算梯度:

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

train_dataset = datasets.CIFAR100(root = "datasets",train=True,transform=transforms.ToTensor(),download=True)
train_dataloader = DataLoader(dataset=train_dataset,batch_size=1,shuffle=False,num_workers=0)

class Model(torch.nn.Module):
    def __init__(self):
        super(Model,self).__init__()
        self.models = torch.nn.Sequential(
            Conv2d(3, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 64, 5, padding=2),
            MaxPool2d(2),
            Flatten(),
            Linear(1024, 512),
            Linear(512, 100)
        )

    def forward(self,input):
        output = self.models(input)
        return output
model = Model()
#计算损失函数
result_loss = torch.nn.CrossEntropyLoss()

if __name__=="__main__":
    for data in train_dataloader:
        imgs,targets = data
        output = model(imgs)
        #计算误差
        loss = result_loss(output,targets)
        #反向传播,计算梯度
        loss.backward()

优化器

在官方文档 torch.optim 中可以查找和优化器有关的属性及使用原理。

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

train_dataset = datasets.CIFAR100(root = "datasets",train=True,transform=transforms.ToTensor(),download=True)
train_dataloader = DataLoader(dataset=train_dataset,batch_size=64,shuffle=False,num_workers=0)

class Model(torch.nn.Module):
    def __init__(self):
        super(Model,self).__init__()
        self.models = torch.nn.Sequential(
            Conv2d(3, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 64, 5, padding=2),
            MaxPool2d(2),
            Flatten(),
            Linear(1024, 512),
            Linear(512, 100)
        )

    def forward(self,input):
        output = self.models(input)
        return output
model = Model()
#计算损失函数
result_loss = torch.nn.CrossEntropyLoss()
#设置优化器
optim = torch.optim.SGD(model.parameters(),lr=0.01)

if __name__=="__main__":
    for epoch in range(20):
        running_loss = 0.0
        for data in train_dataloader:
            imgs,targets = data
            output = model(imgs)
            #计算误差
            loss = result_loss(output,targets)
            #重置优化器
            optim.zero_grad()
            # 反向传播,计算梯度
            loss.backward()
            #更新参数
            optim.step()
            running_loss = running_loss+loss
        print(running_loss)

模型的保存及加载

保存模型的两种方式:

方式一:(保存模型架构及参数)
	torch.save(model,"保存路径及保存文件名")
方式二:(仅保存模型参数)
	torch.save.(model.state_dict(),"保存路径及保存文件名")	#该方式以字典的形式保存参数

加载模型的两种方式:

from train_model(模型保存的文件) import *
方式一:(对应第一种保存方式的加载方式)
	model = torch.load("模型文件")
    
方式二:(对应第二种保存方式的加载方式)
	class model(torch.nn.Module):
        ...
        
	model.load_state_dict(torch.load("模型文件"))

python 中的字符串格式化输出:

##其中train_data_size 为一个变量
print("训练集的长度为:{}".format(train_data_size))	
#若train_data_size =10 
#则上述语句会输出: 训练集的长度为: 10 

使用GPU训练模型

方法一:

步骤:

  1. 找到模型
  2. 找到数据(输入和target)
  3. 找到损失函数
  4. 对上述东西调用**.cuda()**

伪代码:

train_datasets =  ....
if cuda.is_available():
	train_datasets = train_datasets.cuda()

class model(torch.nn.Module):
	def __init__(self):
		pass
    def forward(self,input):
    	pass
lei = model()
#将模型放到cuda中去
if cuda.is_available():
	lei = lei.cuda()

可使用Google的Colaboratory提供的免费的GPU训练

完整项目(以CIFAR10为例):

主函数(cifar-10_train.py):

在主函数中,完成了数据读取、模型训练、模型保存等步骤。同时会保存10次每次的模型参数,同时会将每个epoch中的loss值写入tensorboard。

import torch.nn
import torchvision.transforms
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
from torchvision import datasets

trian_datasets = datasets.CIFAR10(root="datasets",train=True,download=True,transform=torchvision.transforms.Compose([torchvision.transforms.ToTensor()]))
train_dataloader = DataLoader(dataset=trian_datasets,batch_size=64,shuffle=True)

'''构建模型'''
class Model(torch.nn.Module):
    def __init__(self):
        super(Model,self).__init__()
        self.conv1 = torch.nn.Conv2d(3,32,5,padding=2)
        self.pooling = torch.nn.MaxPool2d(2)
        self.conv2 = torch.nn.Conv2d(32,32,5,padding=2)
        self.conv3 = torch.nn.Conv2d(32,64,5,padding=2)
        self.flatten = torch.nn.Flatten()
        self.linear1 = torch.nn.Linear(1024,64)
        self.linear2 = torch.nn.Linear(64,10)

    def forward(self,input):
        output = self.conv1(input)
        output = self.pooling(output)
        output = self.conv2(output)
        output = self.pooling(output)
        output = self.conv3(output)
        output = self.pooling(output)
        output = self.flatten(output)
        output = self.linear1(output)
        output = self.linear2(output)
        return output
model = Model()
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)
'''优化和损失函数'''
critizer = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(),lr=0.01)

'''训练模型'''
def train(epoch):
    running_loss = 0
    steps = 0
    for data in train_dataloader:
        imgs,target = data
        imgs = imgs.to(device)
        target = target.to(device)

        output = model(imgs)
        #计算误差
        loss = critizer(output,target)
        #优化函数
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        if steps % 49 == 0 :
            print("第{}个batch训练的loss值为:{}".format(steps+1,loss))
        steps = steps + 1
    running_loss = running_loss + loss.item()
    return running_loss

if __name__ == '__main__':
    print("Train Start!")
    writer = SummaryWriter("logs")
    for epoch in range(50):
        loss = train(epoch)
        print("-----------第{}轮的loss值为:{}-------------".format(epoch+1,loss))
        torch.save(model,"chack_point/model_{}.pth".format(epoch))
        writer.add_scalar("loss",loss,epoch)
    writer.close()

得到模型的loss结果和epoch如下图所示:

image-20230509124258921

测试函数(cifar-10_test.py):

import torch

from cifar10_train import *

test_datasets = datasets.CIFAR10(root="../datasets",train=False,download=True,transform=torchvision.transforms.Compose([torchvision.transforms.ToTensor()]))
test_dataloader = DataLoader(dataset=test_datasets,batch_size=64,shuffle=False)

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

model = torch.load("chack_point/model_9.pth")

with torch.no_grad():
    for data in test_dataloader:
        imgs,target = data
        imgs = imgs.to(device)
        target = target.to(device)
        output = model(imgs)
        label = output.argmax(1)	#获取每一行的最大值,从而判断出最有可能的分类情况

在此问题中,测试函数得到的output值一个64*10的矩阵

image-20230508215036608

而此处的label也获得了每一行的最大值,即为最大可能性分类。

image-20230508215159359

分类测试(test.py):

import cv2
import torch
from torchvision import transforms, datasets

test_datasets = datasets.CIFAR10("E:/Pytorch_Study/TuDui_pytorch/NetWork/datasets")
index = test_datasets.class_to_idx
class Model(torch.nn.Module):
    def __init__(self):
        super(Model,self).__init__()
        self.conv1 = torch.nn.Conv2d(3,32,5,padding=2)
        self.pooling = torch.nn.MaxPool2d(2)
        self.conv2 = torch.nn.Conv2d(32,32,5,padding=2)
        self.conv3 = torch.nn.Conv2d(32,64,5,padding=2)
        self.flatten = torch.nn.Flatten()
        self.linear1 = torch.nn.Linear(1024,64)
        self.linear2 = torch.nn.Linear(64,10)

    def forward(self,input):
        output = self.conv1(input)
        output = self.pooling(output)
        output = self.conv2(output)
        output = self.pooling(output)
        output = self.conv3(output)
        output = self.pooling(output)
        output = self.flatten(output)
        output = self.linear1(output)
        output = self.linear2(output)
        return output
model = torch.load("../chack_point/model_9.pth",map_location="cpu")

img = cv2.imread("picture/cat4.png")
print(img.shape)
tansform = transforms.Compose([transforms.ToTensor(),transforms.Resize((32,32),antialias=True)])
imgs = tansform(img)

imgs = torch.reshape(imgs,(1,3,32,32))
output = model(imgs)
exp = torch.argmax(output)

for key,value in index.items():
    if exp == value:
        print("该图片是:{}".format(key))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值