基于深度学习的猫狗分类实战

项目背景:

随着人工智能和深度学习技术的迅速发展,图像分类任务在计算机视觉领域取得了显著的成就。在日常生活中,猫和狗是人们常见且喜爱的宠物,对它们进行准确的分类具有一定的实际需求和应用价值。

同时,大规模的图像数据集的可用性以及强大的计算资源的普及,为开展基于深度学习的图像分类研究提供了良好的条件。此外,深度学习在图像识别领域的卓越表现,使得其能够处理复杂的图像特征,从而为实现高精度的猫狗分类提供了技术支持。

项目目的:

  1. 探索和应用深度学习技术在图像分类任务中的有效性和潜力,特别是在处理具有相似特征的猫和狗图像时。
  2. 提高对猫狗图像的分类准确率,为相关的图像识别应用提供可靠的模型和算法。
  3. 深入理解深度学习模型在学习和提取图像特征方面的机制,通过对猫狗分类的研究,优化模型结构和训练参数,以提升模型的性能和泛化能力。
  4. 为动物保护、宠物管理等领域提供技术支持,例如自动识别流浪猫狗、辅助宠物医疗诊断等。
  5. 培养和提升团队在深度学习、计算机视觉和数据处理方面的技术能力和创新思维

摘要:本文介绍了使用深度学习技术实现猫狗分类的项目,包括数据预处理、模型选择、训练过程以及结果评估。通过这个项目,我们能够深入了解深度学习在图像分类任务中的应用。

一、引言

在计算机视觉领域,图像分类是一个基础且重要的任务。猫狗分类作为一个经典的二分类问题,具有较高的研究价值和实际应用场景。通过对大量的猫狗图片进行学习,我们可以训练出一个能够准确区分猫狗的模型。

二、数据预处理

  1. 数据收集
    我们从网络上收集了大量的猫狗图片数据集,包括不同品种、姿态和背景的图片,以增加数据的多样性和泛化能力。
  2. 在当前目录创建一个dataset文件夹,用来存放数据集。在dataset文件夹下创建train、val、test文件夹。在train文件夹下创建cat(🐱)、dog(🐕)文件夹,这是当前猫狗实验分类创建的,对应的文件夹下放对应的图片,比如说cat文件夹下放的都是猫的图片。val、test文件夹与train文件夹相同。
                                              导入相关包的代码
    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
    
    

  3. 数据清洗
    对收集到的数据进行清洗,去除模糊、重复和质量较差的图片,确保数据的准确性和有效性。
  4. 数据标注
    为每张图片标注其类别(猫或狗),以便模型能够进行有监督的学习。
  5. 数据增强
    通过随机旋转、裁剪、翻转、亮度调整等操作对数据进行增强,以增加数据量和减少过拟合的风险。这里我的代码是进行随机 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
    

三、加载数据

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)

四、迁移学习

由于我们的数据量相对有限,采用迁移学习的方法,利用在大规模数据集上预训练好的模型参数,然后在我们的猫狗数据集上进行微调。
代码如下:
 

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

五、模型调优

为了适应自己的数据集,将ResNet-50的最后一层替换为,将原来最后一个全连接层的输入喂给一个有256个输出单元的线性层,接着再连接ReLU层和Dropout层,然后是256 x 2的线性层,输出为 2通道的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),#猫狗是二分类,故是2
    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

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

# 定义训练过程


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


四、训练过程

  1. 优化算法
    选择合适的优化算法,如随机梯度下降(SGD)、Adagrad、Adadelta 等,并调整学习率、动量等参数。
  2. 损失函数
    使用交叉熵损失函数来衡量模型的预测与真实标签之间的差异。
  3. 训练策略
    采用批量训练的方式,设置合适的批量大小,并进行多次迭代训练,直到模型收敛。
    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')
    

七、结果评估

  1. 准确率
    使用准确率作为主要的评估指标,计算模型在测试集上正确分类的比例。
  2. 混淆矩阵
    绘制混淆矩阵,直观地展示模型对猫和狗的分类情况,分析错误分类的样本特征。
  3. 可视化
    通过对模型的中间特征图进行可视化,了解模型对图像的学习和理解过程。
    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')
    
    
    

八、模型推理预测

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

六、总结与展望

通过本次猫狗分类项目的实践,我们深入掌握了深度学习在图像分类中的应用技术。未来,可以进一步探索更先进的模型架构和训练方法,提高分类的准确率和泛化能力,并将其应用到更广泛的图像分类任务中。

  • 19
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
TensorFlow是一个开源的机器学习框架,它可以用于构建和训练深度学习模型。对于分类这个问题,我们可以使用TensorFlow来构建一个卷积神经网络(CNN)模型。首先,我们需要一组带有标签的图像数据集作为训练数据,这些数据将被用来训练CNN模型。我们可以使用TensorFlow的数据预处理工具来对图像数据进行预处理,包括图像缩放、归一化等操作。 接下来,我们可以使用TensorFlow的高级API(比如Keras)来构建一个CNN模型。CNN模型通常包括多个卷积层、池化层和全连接层,这些层的组合可以提取图像特征并实现分类任务。我们可以使用TensorFlow提供的各种优化器和损失函数来定义模型的训练目标,并通过反向传播算法来进行模型的训练。 在训练过程中,我们可以使用TensorFlow提供的工具来监控模型的训练过程,比如训练损失的变化、模型的准确率等。一旦模型训练完成,我们可以使用测试数据来评估模型的性能,检查模型在分类任务上的准确率和召回率等指标。 最终,我们可以将训练好的模型部署到生产环境中,用来对新的图像进行分类。TensorFlow还提供了一些部署工具和库,可以帮助我们将训练好的模型集成到实际的应用中去。通过使用TensorFlow构建基于深度学习分类模型,我们可以实现高效、准确的图像分类任务。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值