训练篇:使用pytorch实现垃圾分类并部署使用,浏览器访问,前端Vue,后台Flask

训练篇:使用pytorch实现垃圾分类并部署使用,浏览器访问,前端Vue,后台Flask

1.数据集准备

1.1数据集下载

在百度的AI Studio中有公开数据集,里面有很多不错的数据集可以给我们免费下载使用,下载速度也很快
其中这个数据集就是本文所使用的的数据集,下载链接如下

https://aistudio.baidu.com/aistudio/datasetdetail/30982

在这里插入图片描述
数据集下载好之后,新建python工程,将数据放入工程文件夹

1.2 数据集划分

之前学习深度学习的时候,大部分人都是从手写数字识别开始的吧,手写数字的数据集都是直接使用pytorch中的datasets.MNIST方法下载使用的,不需要自己去整理划分训练集和测试集,但是,如果使用自己的数据集做训练的时候,就需要自己去实现datasets方法.
在此之前,我们还需要写个脚本,将图片地址和标签写入txt文件并分为训练集和测试集,方便训练的时候调用。
在工程根目录下新建一个python文件,用来生成train.txt,test.txt,label.txt三个文件

import os
def generate(dir,label):
    path = './' # 生成文件存放的位置
    files = os.listdir(dir)
    files.sort()
    trainListText = open(path+'train.txt','a')
    testListText = open(path + 'test.txt', 'a')
    index = 0
    proportion = 0.8 # 训练集所占比例
    for file in files:
        if index < int(len(files)*proportion):
            if(os.path.splitext(file)[1]=='.jpeg' or os.path.splitext(file)[1]=='.jpg'):
                name = dir + '/' + file + '**' + str(int(label))+'\n'
                trainListText.write(name)
                index +=1
        else:
            if(os.path.splitext(file)[1]=='.jpeg' or os.path.splitext(file)[1]=='.jpg'):
                name = dir + '/' + file + '**' + str(int(label)) + '\n'
                testListText.write(name)
                index += 1
    trainListText.close()
    testListText.close()


if __name__ == '__main__':
    dirs = os.listdir('data/train_data/train_data') # 数据集所在位置
    dirs.sort()
    label = 0
    labelText = open('./label.txt', 'a')
    for dir in dirs:
        if dir != '.DS_Store':
            labelText.write(dir + '**' + str(label) + '\n')
            generate('data/train_data/train_data/' + dir, label)
            label += 1
    labelText.close()
    print("down!")

运行该脚本后,会在工程的根目录生成三个txt文件

1.3实现自己的Dataset

新建一个python文件,命名为Garbage_Loader,新建一个Garbage_Loader类继承Dataset,要实现自己的dataset类,我们至少需要重写三个方法,init,__getitem__和__len__方法,__init__方法是实例化dataset类的时候初始化一些参数,__getitem__方法是获取第index个数据的图片和标签,__len__方法返回数据集的大小,具体的实现如下:

class Garbage_Loader(Dataset):
    def __init__(self, txt_path, train_flag=True):
        self.imgs_info = self.get_images(txt_path)
        self.train_flag = train_flag

        self.train_tf = transforms.Compose([
            transforms.Resize(224),
            transforms.RandomHorizontalFlip(),
            transforms.RandomVerticalFlip(),
            transforms.ToTensor(),

        ])
        self.val_tf = transforms.Compose([
            transforms.Resize(224),
            transforms.ToTensor(),
        ])

    def get_images(self, txt_path):
        with open(txt_path, 'r', encoding='utf-8') as f:
            imgs_info = f.readlines()
            imgs_info = list(map(lambda x: x.strip().split('**'), imgs_info))
        return imgs_info

    def padding_black(self, img):

        w, h = img.size

        scale = 224. / max(w, h)
        img_fg = img.resize([int(x) for x in [w * scale, h * scale]])

        size_fg = img_fg.size
        size_bg = 224

        img_bg = Image.new("RGB", (size_bg, size_bg))

        img_bg.paste(img_fg, ((size_bg - size_fg[0]) // 2,
                              (size_bg - size_fg[1]) // 2))

        img = img_bg
        return img

    def __getitem__(self, index):
        img_path, label = self.imgs_info[index]
        img = Image.open(img_path)
        img = img.convert('RGB')
        img = self.padding_black(img)
        if self.train_flag:
            img = self.train_tf(img)
        else:
            img = self.val_tf(img)
        label = int(label)

        return img, label

    def __len__(self):
        return len(self.imgs_info)

2.开始训练数据

2.1 实现训练方法和测试方法

新建python文件,实现训练方法和测试方法,代码如下

def accuracy(output, target, topk=(1,)):
    """
        计算topk的准确率
    """
    with torch.no_grad():
        maxk = max(topk)
        batch_size = target.size(0)

        _, pred = output.topk(maxk, 1, True, True)
        pred = pred.t()
        correct = pred.eq(target.view(1, -1).expand_as(pred))

        class_to = pred[0].cpu().numpy()

        res = []
        for k in topk:
            correct_k = correct[:k].contiguous().view(-1).float().sum(0, keepdim=True)
            res.append(correct_k.mul_(100.0 / batch_size))
        return res, class_to


def save_checkpoint(state, is_best, filename='checkpoint.pth.tar'):
    """
        根据 is_best 存模型,一般保存 valid acc 最好的模型
    """
    torch.save(state, filename)
    if is_best:
        shutil.copyfile(filename, 'model_best_' + filename)


def train(train_loader, model, criterion, optimizer, epoch, writer):
    """
        训练代码
        参数:
            train_loader - 训练集的 DataLoader
            model - 模型
            criterion - 损失函数
            optimizer - 优化器
            epoch - 进行第几个 epoch
            writer - 用于写 tensorboardX
    """
    batch_time = AverageMeter()
    data_time = AverageMeter()
    losses = AverageMeter()
    top1 = AverageMeter()
    top5 = AverageMeter()

    # switch to train mode
    model.train()

    end = time.time()
    for i, (input, target) in enumerate(train_loader):
        # measure data loading time
        data_time.update(time.time() - end)

        input = input.cuda()
        target = target.cuda()

        # compute output
        output = model(input)
        loss = criterion(output, target)

        # measure accuracy and record loss
        [prec1, prec5], class_to = accuracy(output, target, topk=(1, 5))
        losses.update(loss.item(), input.size(0))
        top1.update(prec1[0], input.size(0))
        top5.update(prec5[0], input.size(0))

        # compute gradient and do SGD step
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        # measure elapsed time
        batch_time.update(time.time() - end)
        end = time.time()

        if i % 10 == 0:
            print('Epoch: [{0}][{1}/{2}]\t'
                  'Time {batch_time.val:.3f} ({batch_time.avg:.3f})\t'
                  'Data {data_time.val:.3f} ({data_time.avg:.3f})\t'
                  'Loss {loss.val:.4f} ({loss.avg:.4f})\t'
                  'Prec@1 {top1.val:.3f} ({top1.avg:.3f})\t'
                  'Prec@5 {top5.val:.3f} ({top5.avg:.3f})'.format(
                epoch, i, len(train_loader), batch_time=batch_time,
                data_time=data_time, loss=losses, top1=top1, top5=top5))
    writer.add_scalar('loss/train_loss', losses.val, global_step=epoch)


def validate(val_loader, model, criterion, epoch, writer, phase="VAL"):
    """
        验证代码
        参数:
            val_loader - 验证集的 DataLoader
            model - 模型
            criterion - 损失函数
            epoch - 进行第几个 epoch
            writer - 用于写 tensorboardX
    """
    batch_time = AverageMeter()
    losses = AverageMeter()
    top1 = AverageMeter()
    top5 = AverageMeter()

    # switch to evaluate mode
    model.eval()

    with torch.no_grad():
        end = time.time()
        for i, (input, target) in enumerate(val_loader):
            input = input.cuda()
            target = target.cuda()
            # compute output
            output = model(input)
            loss = criterion(output, target)

            # measure accuracy and record loss
            [prec1, prec5], class_to = accuracy(output, target, topk=(1, 5))
            losses.update(loss.item(), input.size(0))
            top1.update(prec1[0], input.size(0))
            top5.update(prec5[0], input.size(0))

            # measure elapsed time
            batch_time.update(time.time() - end)
            end = time.time()

            if i % 10 == 0:
                print('Test-{0}: [{1}/{2}]\t'
                      'Time {batch_time.val:.3f} ({batch_time.avg:.3f})\t'
                      'Loss {loss.val:.4f} ({loss.avg:.4f})\t'
                      'Prec@1 {top1.val:.3f} ({top1.avg:.3f})\t'
                      'Prec@5 {top5.val:.3f} ({top5.avg:.3f})'.format(
                    phase, i, len(val_loader),
                    batch_time=batch_time,
                    loss=losses,
                    top1=top1, top5=top5))

        print(' * {} Prec@1 {top1.avg:.3f} Prec@5 {top5.avg:.3f}'
              .format(phase, top1=top1, top5=top5))
    writer.add_scalar('loss/valid_loss', losses.val, global_step=epoch)
    return top1.avg, top5.avg


class AverageMeter(object):
    """Computes and stores the average and current value"""

    def __init__(self):
        self.reset()

    def reset(self):
        self.val = 0
        self.avg = 0
        self.sum = 0
        self.count = 0

    def update(self, val, n=1):
        self.val = val
        self.sum += val * n
        self.count += n
        self.avg = self.sum / self.count

2.2 开始训练

在前面的文件中的if __name__ == '__main__':中实现训练流程

  • 加载数据
  • 定义网络
  • 定义损失函数和优化器等
  • 训练
if __name__ == '__main__':
    os.environ["CUDA_VISIBLE_DEVICES"] = "0"
    # -------------------------------------------- step 1/4 : 加载数据 ---------------------------
    train_dir_list = './train.txt'
    valid_dir_list = './test.txt'
    batch_size = 32 
    epochs = 100
    num_classes = 123 # 类别个数
    train_data = Garbage_Loader(train_dir_list, train_flag=True)
    valid_data = Garbage_Loader(valid_dir_list, train_flag=False)
    train_loader = DataLoader(dataset=train_data, num_workers=0, pin_memory=True, batch_size=batch_size, shuffle=True)
    valid_loader = DataLoader(dataset=valid_data, num_workers=0, pin_memory=True, batch_size=batch_size)
    train_data_size = len(train_data)
    print('训练集数量:%d' % train_data_size)
    valid_data_size = len(valid_data)
    print('验证集数量:%d' % valid_data_size)
    # ------------------------------------ step 2/4 : 定义网络 ------------------------------------
    model = models.resnet50(pretrained=True)
    fc_inputs = model.fc.in_features
    model.fc = nn.Linear(fc_inputs, num_classes)
    model = model.cuda()
    # ------------------------------------ step 3/4 : 定义损失函数和优化器等 -------------------------
    lr_init = 0.0001
    lr_stepsize = 20
    weight_decay = 0.001
    criterion = nn.CrossEntropyLoss().cuda()
    optimizer = optim.Adam(model.parameters(), lr=lr_init, weight_decay=weight_decay)
    scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=lr_stepsize, gamma=0.1)

    writer = SummaryWriter('./runs/resnet50')
    # ------------------------------------ step 4/4 : 训练 -----------------------------------------
    best_prec1 = 0
    for epoch in range(epochs):
        scheduler.step()
        train(train_loader, model, criterion, optimizer, epoch, writer)
        # 在验证集上测试效果
        valid_prec1, valid_prec5 = validate(valid_loader, model, criterion, epoch, writer, phase="VAL")
        is_best = valid_prec1 > best_prec1
        best_prec1 = max(valid_prec1, best_prec1)
        save_checkpoint({
            'epoch': epoch + 1,
            'arch': 'resnet50',
            'state_dict': model.state_dict(),
            'best_prec1': best_prec1,
            'optimizer': optimizer.state_dict(),
        }, is_best,
            filename='checkpoint_resnet50.pth.tar')
    writer.close()

看到这个说明已经开始进行训练了,接下来就是漫长的等待。
在这里插入图片描述
训练的过程,会自动将最好的模型保存下来,以及训练过程的loss,通过tensorboard可以进行查看,终端进入工程目录,运行下面命令

tensorboard --logdir=runs

浏览器输入http://localhost:6006/ 即可查看训练过程
在这里插入图片描述

  • 6
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
【课程介绍】      Pytorch项目实战 垃圾分类课程从实战的角度出发,基于真实数据集与实际业务需求,结合当下最新话题-垃圾分类问题为实际业务出发点,介绍最前沿的深度学习解决方案。    从0到1讲解如何场景业务分析、进行数据处理,模型训练与调优,最后进行测试与结果展示分析。全程实战操作,以最接地气的方式详解每一步流程与解决方案。    课程结合当下深度学习热门领域,尤其是基于facebook 开源分类神器ResNext101网络架构,对网络架构进行调整,以计算机视觉为核心讲解各大网络的应用于实战方法,适合快速入门与进阶提升。【课程要求】 (1)开发环境:python版本:Python3.7+; torch版本:1.2.0+; torchvision版本:0.4.0+ (2)开发工具:Pycharm;(3)学员基础:需要一定的Python基础,及深度学习基础;(4)学员收货:掌握最新科技图像分类关键技术;(5)学员资料:内含完整程序源码和数据集;(6)课程亮点:专题技术,完整案例,全程实战操作,徒手撸代码【课程特色】 阵容强大讲师一直从事与一线项目开发,高级算法专家,一直从事于图像、NLP、个性化推荐系统热门技术领域。仅跟前沿基于当前热门讨论话题:垃圾分类,课程采用学术届和工业届最新前沿技术知识要点。实战为先根据实际深度学习工业场景-垃圾分类,从产品需求、产品设计和方案设计、产品技术功能实现、模型上线部署。精心设计工业实战项目保障效果项目实战方向包含了学术届和工业届最前沿技术要点项目包装简历优化课程内垃圾分类图像实战项目完成后可以直接优化到简历中【课程思维导图】 【课程实战案例】

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

_-CHEN-_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值