图像分类猫狗分类实战—基于pytorch框架的迁移学习(resnet50模型实现分类实战)(代码片段)

AI小杨 AI小杨     2023-04-06     249

关键词:

说明:

ResNet50模型实现分类实战,数据集是猫狗分类数据集,讲解的特别详细,适合零基础入门。

一、前置准备

1、pytorch环境搭建

pytorch环境安装:Start Locally | PyTorch

复制这个代码到pytorch到pycharm环境进行安装:

2、数据集介绍

在当前目录创建一个dataset文件夹,用来存放数据集。
在dataset文件夹下创建train、val、test文件夹。
在train文件夹下创建cat(🐱)、dog(🐕)文件夹,这是当前猫狗实验分类创建的,假如是猫狗猪分类还需要创建一个pig文件夹,以此类推,对应的文件夹下放对应的图片,比如说cat文件夹下放的都是猫的图片。
val、test文件夹与train文件夹相同。
文件夹结构如下:

dataset
	|——train
		 |——dog
		 |——cat	
	|——val
		 |——dog
		 |——cat	
	|——test
	     |——dog
		 |——cat	

我实验的数据集放置在此处:
链接:https://pan.baidu.com/s/1QrNFBdOhdPVic_fn38PFmA?pwd=h6sb
提取码:h6sb

3、创建jupyter notebook实验环境

本次实验是用jupyter notebook环境运行的

(1)、pycharm终端输入jupyter notebook启动notebook实验环境

(2)、jupyter notebook中上传数据集,和创建的.ipynb

二、ResNet50模型代码实现

1、导包

import torch.optim as optim
import torch
import torch.nn as nn
import torch.nn.parallel
import torch.optim
import torch.utils.data
import torch.utils.data.distributed
import torchvision.transforms as transforms
import torchvision.datasets as datasets
import torchvision.models
from torch.autograd import Variable
from tqdm import tqdm

import os
from PIL import Image
import cv2

#判断环境是CPU运行还是GPU
DEVICE = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
DEVICE
  • 运行截图:

2、数据增强

建好的数据集在输入网络之前先进行数据增强,包括随机 resize 裁剪到 256 x 256,随机旋转,随机水平翻转,中心裁剪到 224 x 224,转化成 Tensor,正规化等。

transform111 = 
    'train': transforms.Compose([
        transforms.RandomResizedCrop(size=256, scale=(0.8, 1.0)),
        transforms.RandomRotation(degrees=15),
        transforms.RandomHorizontalFlip(),
        transforms.CenterCrop(size=224),
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406],
                             [0.229, 0.224, 0.225])
    ]),
    'val': transforms.Compose([
        transforms.Resize(size=256),
        transforms.CenterCrop(size=224),
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406],
                             [0.229, 0.224, 0.225])
    ])

transform111
  • 运行截图:

3、加载数据

torchvision.transforms包DataLoader是 Pytorch 重要的特性,它们使得数据增加和加载数据变得非常简单。 使用 DataLoader 加载数据的时候就会将之前定义的数据 transform 就会应用的数据上了。

import shutil
modellr = 1e-3
BATCH_SIZE = 64
EPOCHS = 100

# 删除隐藏文件/文件夹
for root, dirs, files in os.walk('./dataset'):
    for file in files:
        if 'ipynb_checkpoints' in file:
            os.remove(os.path.join(root, file))
    if 'ipynb_checkpoints' in root:
        shutil.rmtree(root)

# 读取数据
dataset_train = datasets.ImageFolder('dataset/train', transform111)
print(dataset_train.imgs)
# 对应文件夹的label
print(dataset_train.class_to_idx)
dataset_test = datasets.ImageFolder('dataset/val', transform111)
# 对应文件夹的label
print(dataset_test.class_to_idx)

dataset = './dataset'
train_directory = os.path.join(dataset, 'train')
valid_directory = os.path.join(dataset, 'val')

batch_size = 32
num_classes = 6
print(train_directory)
data = 
    'train': datasets.ImageFolder(root=train_directory, transform=transform111['train']),
    'val': datasets.ImageFolder(root=valid_directory, transform=transform111['val'])



train_data_size = len(data['train'])
valid_data_size = len(data['val'])

train_loader = torch.utils.data.DataLoader(data['train'], batch_size=batch_size, shuffle=True, num_workers=8)
test_loader = torch.utils.data.DataLoader(data['val'], batch_size=batch_size, shuffle=True, num_workers=8)

print(train_data_size, valid_data_size)

  • 运行截图:

4、迁移学习

# 下载预训练模型
model = torchvision.models.resnet50(pretrained=False)#不使用训练好的预训练模型
model

  • 运行截图:

5、模型调优

为了适应自己的数据集,将ResNet-50的最后一层替换为,将原来最后一个全连接层的输入喂给一个有256个输出单元的线性层,接着再连接ReLU层和Dropout层,然后是256 x 6的线性层,输出为 6 通道的softmax层。

# 实例化模型并且移动到GPU
criterion = nn.CrossEntropyLoss()
num_ftrs = model.fc.in_features
# model.fc = nn.Linear(num_ftrs, 10)
model.fc = nn.Sequential(
    nn.Linear(num_ftrs, 256),
    nn.ReLU(),
    nn.Dropout(0.4),
    nn.Linear(256, 6),
    nn.LogSoftmax(dim=1)
)
model.to(DEVICE)
# 选择简单暴力的Adam优化器,学习率调低
optimizer = optim.Adam(model.parameters(), lr=modellr)

def adjust_learning_rate(optimizer, epoch):
    modellrnew = modellr * (0.1 ** (epoch // 50))
    print("lr:", modellrnew)
    for param_group in optimizer.param_groups:
        param_group['lr'] = modellrnew
  • 运行截图:

6、定义训练过程和验证过程

# 定义训练过程


def train(model, device, train_loader, optimizer, epoch):
    model.train()
    sum_loss = 0
    train_acc = 0
    total_num = len(train_loader.dataset)
    # print(total_num, len(train_loader))
    for batch_idx, (data, target) in enumerate(tqdm(train_loader)):
        data, target = Variable(data).to(device), Variable(target).to(device)
        im = Variable(data)
        output = model(data)
        loss = criterion(output, target)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        print_loss = loss.data.item()
        sum_loss += print_loss
        
        out_t = output.argmax(dim=1) #取出预测的最大值
        num_correct = (out_t == target).sum().item()
        acc = num_correct / im.shape[0]
        train_acc += acc
        
        if (batch_idx + 1) % 50 == 0:
            print('Train Epoch:  [/ (:.0f%)]\\tLoss: :.6f'.format(
                epoch, (batch_idx + 1) * len(data), len(train_loader.dataset),
                       100. * (batch_idx + 1) / len(train_loader), loss.item()))
            
    ave_loss = sum_loss / len(train_loader)
    ave_acc = train_acc / len(train_loader)
    print('epoch:, train_acc: , loss:'.format(epoch, ave_acc, ave_loss))
    return ave_acc, ave_loss

def val(model, device, test_loader):
    model.eval()
    test_loss = 0
    correct = 0
    total_num = len(test_loader.dataset)
    # print(total_num, len(test_loader))
    with torch.no_grad():
        for data, target in test_loader:
            data, target = Variable(data).to(device), Variable(target).to(device)
            output = model(data)
            loss = criterion(output, target)
            _, pred = torch.max(output.data, 1)
            correct += torch.sum(pred == target)
            print_loss = loss.data.item()
            test_loss += print_loss
        correct = correct.data.item()
        acc = correct / total_num
        avgloss = test_loss / len(test_loader)
        print('Val set: Average loss: :.4f, Accuracy: / (:.0f%)\\n'.format(
            avgloss, correct, len(test_loader.dataset), 100 * acc))
    return acc, avgloss


7、模型训练

train_acc_list, train_loss_list, val_acc_list, val_loss_list = [], [], [], []

for epoch in range(1, EPOCHS + 1):
    adjust_learning_rate(optimizer, epoch)
    train_acc, train_loss = train(model, DEVICE, train_loader, optimizer, epoch)
    val_acc, val_loss = val(model, DEVICE, test_loader)
    train_acc_list.append(train_acc)
    val_acc_list.append(val_acc)
    train_loss_list.append(train_loss)
    val_loss_list.append(val_loss)
torch.save(model, 'model.pth')
  • 运行截图

8、模型评估

import matplotlib.pyplot as plt

epochs_range = range(EPOCHS)
print(epochs_range, train_acc_list)

plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.plot(epochs_range, train_acc_list, label='Training Accuracy')
plt.plot(epochs_range, val_acc_list, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')

plt.subplot(1, 2, 2)
plt.plot(epochs_range, train_loss_list, label='Training Loss')
plt.plot(epochs_range, val_loss_list, label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.savefig('./acc-loss.jpg')


  • 运行截图:

9、模型推理预测

import torch.utils.data.distributed
import torchvision.transforms as transforms
import torchvision.datasets as datasets
from torch.autograd import Variable
from pathlib import Path

classes = ('cat', 'dog')
transform_test = transforms.Compose([
    transforms.Resize((224, 224)),
    transforms.ToTensor(),      
    transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
])

DEVICE = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
model = torch.load("model.pth")
model.eval()
model.to(DEVICE)

dataset_test = datasets.ImageFolder('dataset/test', transform_test)
print(len(dataset_test))
# 对应文件夹的label

y_true, y_sore = [], []
for index in range(len(dataset_test)):
    item = dataset_test[index]
    img, label = item
    img.unsqueeze_(0)
    data = Variable(img).to(DEVICE)
    output = model(data)
    _, pred = torch.max(output.data, 1)
    y_true.append(label)
    y_sore.append(pred.data.item())
    print('Image Name:, label:, predict:'.format(dataset_test.imgs[index][0], classes[label], classes[pred.data.item()]))
    index += 1
  • **运行截图:

pytorch深度学习实战|搭建卷积神经网络进行图像分类与图像风格迁移

PyTorch是当前主流深度学习框架之一,其设计追求最少的封装、最直观的设计,其简洁优美的特性使得PyTorch代码更易理解,对新手非常友好。本文为实战篇,介绍搭建卷积神经网络进行图像分类与图像风格迁移。1... 查看详情

图像分类---利用pytorch搭建alexnet网络模型训练自己的数据集(猫狗分类)(代码片段)

1数据准备    很多例子做图像分类的时候都喜欢用手写数字作为例子来讲解图像分类,这是一个及其不负责任的教学,我个人认为做深度学习有时候是要在数据集上下功夫的,而且因为很多框架都内置了手写数字数... 查看详情

pytorch深度学习实战|猫狗分类

本文内容使用TensorFlow和Keras建立一个猫狗图片分类器。图1猫狗图片01、安装TensorFlow和Keras库TensorFlow是一个采用数据流图(dataflowgraphs),用于数值计算的开源软件库。节点(Nodes)在图中表示数学操作,图... 查看详情

pytorch图像分类教程专栏目录

PyTorch是当前最流行、最热门、市场占有率最高的深度学习框架,广泛应用于人工智能领域的科学研究和工程实践等。图像分类问题是当前人工智能最重要的组成部分,基于PyTorch实现图像分类是迈入人工智能领域的关键前提。本... 查看详情

pytorch图像分类教程专栏目录

PyTorch是当前最流行、最热门、市场占有率最高的深度学习框架,广泛应用于人工智能领域的科学研究和工程实践等。图像分类问题是当前人工智能最重要的组成部分,基于PyTorch实现图像分类是迈入人工智能领域的关键前提。本... 查看详情

python基于mask信息抽取roi子图并构建基于迁移学习(densenet)的图像分类器实战(原始影像和mask文件都是二维的情况)

Python基于MASK信息抽取ROI子图并构建基于迁移学习(densenet)的图像分类器实战(原始影像和mask文件都是二维的情况)目录 查看详情

pytorch实战用pytorch实现基于神经网络的图像风格迁移(代码片段)

用PyTorch实现基于神经网络的图像风格迁移1.风格迁移原理介绍2.FastNeuralStyle网络结构3.用PyTorch实现风格迁移3.1首先看看如何使用预训练的VGG。3.2接下来要实现风格迁移网络参考资料风格迁移,又称为风格转换。只需要给定原... 查看详情

图像分类convit从入门到实战——使用convit实现植物幼苗的分类(pytorch)(代码片段)

摘要来自Facebook的研究者提出了一种名为ConViT的新计算机视觉模型,它结合了两种广泛使用的AI架构——卷积神经网络(CNN)和Transformer,该模型取长补短,克服了CNN和Transformer本身的一些局限性。同时,借助这两种架... 查看详情

pytorch开源图像分类算法框架(代码片段)

PyTorch的开源图像分类算法框架pytorch-image-models,功能完善,集成大量数据增强方法和主流的网络框架,同时易用。pytorch-image-models:https://github.com/rwightman/pytorch-image-models训练使用方法:训练脚本:train.py 查看详情

基于pytorch框架实现手写图片的分类(代码片段)

...模型4,训练模型5,结果评价​编辑总结前言基于pytorch框架实现手写图片的分类🍨本文为🔗365天深度学习训练营中的学习记录博客🍦参考文章:Pytorch实战|第P4周:猴痘病识别🍖原作者:K同学... 查看详情

如何使用 Pytorch 将二进制迁移学习模型扩展到多个图像类别?

】如何使用Pytorch将二进制迁移学习模型扩展到多个图像类别?【英文标题】:HowtoextendabinarytransferlearningmodelwithPytorchtomultipleimagecategories?【发布时间】:2021-07-0813:46:43【问题描述】:我正在处理一些代码,这些代码使用ResNet-18模... 查看详情

图像分类实战:mobilenetv2从训练到tensorrt部署(pytorch)(代码片段)

...据做数据集,数据集共有12种类别,演示如何使用pytorch版本的m 查看详情

pytorch深度学习项目实战100例——基于lenet5实现交通标志分类任务|第50例

前言大家好,我是阿光。本专栏整理了《PyTorch深度学习项目实战100例》,内包含了各种不同的深度学习项目,包含项目原理以及源码,每一个项目实例都附带有完整的代码+数据集。正在更新中~✨ 查看详情

keras深度学习实战——基于vgg19模型实现性别分类(代码片段)

Keras深度学习实战——基于VGG19模型实现性别分类0.前言1.VGG19架构简介2.使用预训练VGG19模型进行性别分类2.1构建输入与输出数据2.2模型构建与训练2.3模型错误分类示例相关链接0.前言在《迁移学习》中,我们了解了利用迁移学... 查看详情

pytorch深度学习项目实战100例——基于alexnet实现宠物小精灵(宝可梦)分类任务|第49例

前言大家好,我是阿光。本专栏整理了《PyTorch深度学习项目实战100例》,内包含了各种不同的深度学习项目,包含项目原理以及源码,每一个项目实例都附带有完整的代码+数据集。正在更新中~✨ 查看详情

小白学习pytorch教程十四迁移学习:微调resnet实现男人和女人图像分类(代码片段)

@Author:Runsen上次微调了Alexnet,这次微调ResNet实现男人和女人图像分类。ResNet是ResidualNetworks的缩写,是一种经典的神经网络,用作许多计算机视觉任务。ResNet论文参见此处:https://arxiv.org/abs/1512.03385该模型... 查看详情

小白学习pytorch教程十二迁移学习:微调vgg19实现图像分类(代码片段)

@Author:Runsen前言:迁移学习就是利用数据、任务或模型之间的相似性,将在旧的领域学习过或训练好的模型,应用于新的领域这样的一个过程。从这段定义里面,我们可以窥见迁移学习的关键点所在,... 查看详情

「深度学习一遍过」必修17:基于pytorch细粒度分类实战(代码片段)

本专栏用于记录关于深度学习的笔记,不光方便自己复习与查阅,同时也希望能给您解决一些关于深度学习的相关问题,并提供一些微不足道的人工神经网络模型设计思路。专栏地址:「深度学习一遍过」必修篇... 查看详情