基于安卓的虫害识别软件设计--(1)模型训练与可视化

引言

  • 简介:使用pytorch框架,从模型训练、模型部署完整地实现了一个基础的图像识别项目
  • 计算资源:使用的是Kaggle(每周免费30h的GPU)

1.创建名为“utils_1”的模块

模块中包含:训练和验证的加载器函数训练函数验证函数

import os
import sys

import torch
from torch import nn, optim
from torch.utils.data import DataLoader
from torchvision import transforms, datasets
from tqdm import tqdm

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


def get_train_loader(image_path):
    train_transform = transforms.Compose([transforms.RandomResizedCrop(224),
                                          transforms.RandomHorizontalFlip(),
                                          transforms.ToTensor(),
                                          transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])

    train_dataset = datasets.ImageFolder(root=os.path.join(image_path, "train"),
                                         transform = train_transform)
    train_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=32,
                                              shuffle=True, num_workers= 0)
    return train_loader

def get_val_loader(image_path):
    val_transform = transforms.Compose([transforms.Resize((224,224)),
                        transforms.ToTensor(),
                        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])
    val_dataset = datasets.ImageFolder(root=os.path.join(image_path, "validation"),
                                       transform = val_transform)
    val_loader = torch.utils.data.DataLoader(dataset=val_dataset, batch_size=32,
                                             shuffle = False, num_workers = 0)
    return val_loader

def train(train_loader,net):
    net.train()
    train_correct = 0.0
    train_loss = 0.0  # 初始化训练损失
    train_bar = tqdm(train_loader, file=sys.stdout)
    loss_function = nn.CrossEntropyLoss()
    loss_function = loss_function.to(device)
    optimizer = optim.Adam(net.parameters(), lr=0.001)
    for step, data in enumerate(train_bar):
        images, labels = data
        images, labels = images.to(device),labels.to(device)
        # 梯度清零
        optimizer.zero_grad()
        # 训练
        outputs = net(images)
        # 计算损失
        loss = loss_function(outputs, labels)
        # 反向传播
        loss.backward()
        # 更新权重
        optimizer.step()
        # 统计
        _, preds = outputs.max(1)
        correct = preds.eq(labels).sum()
        train_correct += correct
        train_loss += loss.item()  # 累加损失值
        train_bar.desc = 'Training Epoch:[{trained_samples}/{total_samples}]\t Loss: {:0.4f}\t Accuracy: {:0.4f}\t'.format(
                loss.item(),
                (100. * correct) / len(outputs),
                trained_samples=step * train_loader.batch_size + len(images),
                total_samples=len(train_loader.dataset))
    train_correct = (100. * train_correct) / len(train_loader.dataset)
    train_loss /= len(train_loader)  # 计算平均损失值
    return train_correct, train_loss  # 返回训练正确率和平均损失值

def val(val_loader,net):
    net.eval()
    val_correct = 0.0
    val_loss = 0.0  # 初始化验证损失
    loss_function = nn.CrossEntropyLoss()
    loss_function = loss_function.to(device)

    val_bar = tqdm(val_loader, file=sys.stdout)
    for step, data in enumerate(val_bar):
        images, labels = data
        images, labels = images.to(device), labels.to(device)
        with torch.no_grad():
            # 验证
            outputs = net(images)
            # 计算损失
            loss = loss_function(outputs, labels)
            # 统计
            _, preds = outputs.max(1)
            correct = preds.eq(labels).sum()
            val_correct += correct
            val_loss += loss.item()  # 累加损失值
            val_bar.desc = 'Valing Epoch:[{trained_samples}/{total_samples}]\t Loss: {:0.4f}\t Accuracy: {:0.4f}\t'.format(
                loss.item(),
                (100. * correct) / len(outputs),
                trained_samples=step * val_loader.batch_size + len(images),
                total_samples=len(val_loader.dataset))
    val_correct = (100. * val_correct) / len(val_loader.dataset)
    val_loss /= len(val_loader)  # 计算平均损失值
    return val_correct , val_loss  # 返回验证正确率和平均损失值

注意:若使用Kaggle,想要导入该模块,需要添加以下代码

import sys
sys.path.append(r'/kaggle/input/mycode2')

其中,模块路径如下图


2.主函数 

主函数包含:使用模型函数训练主函数画图代码

2.1使用模型函数 

【若使用其他模型,可chatgpt创建其函数】

(1)resnet101 

def get_resnet101(class_num):
    net_name = "resnet101"
    net = torchvision.models.resnet101(pretrained=True)
    net.fc = Linear(in_features=2048, out_features=class_num, bias=True)  # ResNet101's fully connected layer expects 2048 input features
    net = net.to(device)
    return net_name, net

(2)resnet34 

def get_resnet34(class_num):
    net_name = "resnet34"
    net = torchvision.models.resnet34(pretrained=True)
    net.fc = Linear(in_features=512, out_features=class_num, bias=True)
    net = net.to(device)
    return net_name,net

(3)mobilenetv2

def get_mobilenet_v2(class_num):
    net_name = "mobilenet_v2"
    net = torchvision.models.mobilenet_v2(pretrained=True)
    net.classifier[1] = Linear(in_features=1280, out_features=class_num, bias=True)
    net = net.to(device)
    return net_name,net

 2.2画图代码 

    save_path="/kaggle/working/"  
  
    plt.figure(figsize=(12, 4))
    # loss
    plt.subplot(1, 2, 1)
    plt.plot(range(1, epochs + 1), train_losses, "r-",label='Train loss')
    plt.plot(range(1, epochs + 1), val_losses, "b-",label='Val loss')
    plt.legend()
    plt.xlabel('Epoch')
    plt.ylabel('Loss')
    # acc
    plt.subplot(1, 2, 2)
    plt.plot(range(1, epochs + 1), train_accs,"r-", label='Train acc')
    plt.plot(range(1, epochs + 1), val_accs,"b-" ,label='Val acc')
    plt.legend()
    plt.xlabel('Epoch')
    plt.ylabel('Acc')
    plt.legend()
    plt.savefig(os.path.join(save_path, 'result.png')) # 保存
    plt.show()

2.3完整代码 

import torch
import torchvision.models
from matplotlib import pyplot as plt
from torch.nn import Linear
import os

# 导入自己创建的模块
from utils_1 import get_train_loader, train, val, get_val_loader

# 模型选择
def get_resnet101(class_num):
    net_name = "resnet101"
    net = torchvision.models.resnet101(pretrained=True)
    net.fc = Linear(in_features=2048, out_features=class_num, bias=True)  # ResNet101's fully connected layer expects 2048 input features
    net = net.to(device)
    return net_name, net

# def get_resnet34(class_num):
#     net_name = "resnet34"
#     net = torchvision.models.resnet34(pretrained=True)
#     net.fc = Linear(in_features=512, out_features=class_num, bias=True)
#     net = net.to(device)
#     return net_name,net

# def get_mobilenet_v2(class_num):
#     net_name = "mobilenet_v2"
#     net = torchvision.models.mobilenet_v2(pretrained=True)
#     net.classifier[1] = Linear(in_features=1280, out_features=class_num, bias=True)
#     net = net.to(device)
#     return net_name,net

# 训练主函数
if __name__ == '__main__':
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    #1 加载数据
    image_path = r"/kaggle/input/fruits3"
    train_loader = get_train_loader(image_path)
    val_loader = get_val_loader(image_path)
    #2 加载模型
    net_name,net = get_resnet34(class_num=5)
    #3 训练
    epochs = 5
    best_acc = 0
    
    train_losses = []
    val_losses = []
    train_accs = []
    val_accs = []
    
    for epoch in range(epochs):
        train_acc,train_loss = train(train_loader, net)
        val_acc,val_loss = val(val_loader, net)
        
        train_losses.append(train_loss)
        val_losses.append(val_loss)
        train_accs.append(train_acc.item())
        val_accs.append(val_acc.item())
        
        if best_acc<val_acc:
            best_acc = val_acc
            torch.save(net, os.path.join("/kaggle/working/", net_name + ".pt"))
    
    # 画图
    save_path="/kaggle/working/" # 图片保存路径
    
    plt.figure(figsize=(12, 4))
    # loss
    plt.subplot(1, 2, 1)
    plt.plot(range(1, epochs + 1), train_losses, "r-",label='Train loss')
    plt.plot(range(1, epochs + 1), val_losses, "b-",label='Val loss')
    plt.legend()
    plt.xlabel('Epoch')
    plt.ylabel('Loss')
    # acc
    plt.subplot(1, 2, 2)
    plt.plot(range(1, epochs + 1), train_accs,"r-", label='Train acc')
    plt.plot(range(1, epochs + 1), val_accs,"b-" ,label='Val acc')
    plt.legend()
    plt.xlabel('Epoch')
    plt.ylabel('Acc')
    plt.legend()
    plt.savefig(os.path.join(save_path, 'result.png')) # 保存
    plt.show()

2.4训练效果与模型文件

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zzztutu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值