【Python】基于卷积神经网络的猫狗识别-PyTorch实现

本文介绍了使用深度学习中的AlexNet模型对KaggleCatsvsDogs数据集进行图像分类的实验,包括模型结构、数据预处理、损失函数选择和实验结果分析。模型在训练集上达到了96.60%的精度,展示了深度学习在图像识别任务中的应用潜力。
摘要由CSDN通过智能技术生成

介绍

        文章内容来自我的《深度学习》课程作业实验报告。

        图像识别是在提取图像特征的基础上,对图像的各种不同模式目标和对象 进行识别的技术。本实验通过对 Kaggle 上的 Cats.vs.Dogs 图像数据集进行学习, 实现识别图片的猫狗类型。深度学习方法在图像识别中应用比较广泛。用于基于 卷积神经网络的图像识别方法有很多,常用的卷积神经网络模型有 LeNet、 AleXNet、GoogLeNet、VGGNet、ResNet 等模型。本实验使用 Kaggle 上的 Cats vs.Dogs 图像数据集的部分数据,采用了结构较为简单的 AleXNet 网络,并引入 了预训练模型,构建了算法构建一个卷积神经网络模型,解决了猫狗二分类图像识别问题。

解决方案

2.1 AlexNet 模型

        模型使用 AlexNet 模型进行猫狗分类。AlexNet 输入为 RGB 三通道的 224 × 224 × 3 大小的图像(也可填充为 227 × 227 × 3 )。AlexNet 共包含 5 个 卷积层(包含 3 个池化)和 3 个全连接层。其中,每个卷积层都包含卷积核、 偏置项、ReLU 激活函数和局部响应归一化(LRN)模块。第 1、2、5 个卷积层 后面都跟着一个最大池化层,后三个层为全连接层。最终输出层为 softmax,将 网络输出转化为概率值,用于预测图像的类别。模型结构如下:

2.2 损失函数

        使用交叉熵损失作为损失函数,计算公式如下:

2.3 评价指标

       使用精确度作为评价指标,计算公式如下:

其中:TP为真正例,TN为真负例,FP为假正例,FN为假负例。

实验结果和分析

3.1 数据集与工具

        Visual Studio Code

        PyTorch 1.13

        kaggle Dogs vs. Cats 数据集

3.2 训练过程及代码

       首先进行数据的预处理,将原始数据集中训练集里的猫狗图像人为重新划分训练集和测试集。其中,训练集2000张,测试集500张,猫狗各占50%。将数据的红绿蓝通道以均值0.485, 0.456, 0.406,标准差0.229, 0.224, 0.225进行归一化处理,并且依据概率对图片水平翻转,进行数据增强。

       构建模型AlexNet模型,这里使用了torchvision.models中的模型结构,参数初始化为AlexNet提供的参数,在此基础上进行微调,大大降低了训练时间。

# 加载模型
def get_model(path_state_dict, vis_model=False):
    """
    创建模型,加载参数
    :param path_state_dict:
    :return:
    """
    model = alexnet()
    pretrained_state_dict = torch.load(path_state_dict)
    model.load_state_dict(pretrained_state_dict)

    if vis_model:
        print(model)

    return model

获取AlexNet模型,并对其结构进行修改。因为是二分类问题,所以将最后输出的类别,从1000改为2。

# ============================ step 2/5 模型 ============================
    alexnet_model = get_model(path_state_dict, True)

    num_ftrs = alexnet_model.classifier._modules["6"].in_features
    alexnet_model.classifier._modules["6"] = nn.Linear(num_ftrs, num_classes)
    
    alexnet_model.to("cuda" if torch.cuda.is_available() else "cpu")

定义损失函数与优化器

# ============================ step 3/5 损失函数 ============================
    criterion = nn.CrossEntropyLoss()
    # ============================ step 4/5 优化器 ============================

    optimizer = torch.optim.SGD(alexnet_model.parameters(), lr=LR, momentum=0.9)  # 选择优化器

    scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=lr_decay_step, gamma=0.1)  # 设置学习率下降策略

训练与测试过程

# ============================ step 5/5 训练 ============================
    train_curve = []
    train_acc=[]
    valid_curve = []
    valid_acc=[]
    for epoch in range(start_epoch + 1, MAX_EPOCH):

        loss_mean = 0.
        correct = 0.
        total = 0.

        alexnet_model.train()
        for i, data in enumerate(train_loader):

            # forward
            inputs, labels = data
            inputs, labels = inputs.to(device), labels.to(device)
            outputs = alexnet_model(inputs)

            # backward
            optimizer.zero_grad()
            loss = criterion(outputs, labels)
            loss.backward()

            # update weights
            optimizer.step()

            # 统计分类情况
            predicted = torch.argmax(outputs.data, 1)
            total += labels.size(0)
            correct += torch.sum(predicted == labels)

            # 打印训练信息
            loss_mean += loss.item()
            train_curve.append(loss.item())
            train_acc.append(correct / total)
            if (i+1) % log_interval == 0:
                loss_mean = loss_mean / log_interval
                print("Training:Epoch[{:0>3}/{:0>3}] Iteration[{:0>3}/{:0>3}] Loss: {:.4f} Acc:{:.2%}".format(
                    epoch, MAX_EPOCH, i+1, len(train_loader), loss_mean, correct / total))
                loss_mean = 0.

        scheduler.step()  # 更新学习率

        # validate the model
        if (epoch+1) % val_interval == 0:

            correct_val = 0.
            total_val = 0.
            loss_val = 0.
            alexnet_model.eval()
            with torch.no_grad():
                for j, data in enumerate(valid_loader):
                    inputs, labels = data
                    inputs, labels = inputs.to(device), labels.to(device)

                    bs, ncrops, c, h, w = inputs.size()     # [4, 10, 3, 224, 224
                    outputs = alexnet_model(inputs.view(-1, c, h, w))
                    outputs_avg = outputs.view(bs, ncrops, -1).mean(1)

                    loss = criterion(outputs_avg, labels)

                    predicted = torch.argmax(outputs_avg.data, 1)
                    total_val += labels.size(0)
                    correct_val += torch.sum(predicted == labels)

                    loss_val += loss.item()

                loss_val_mean = loss_val/len(valid_loader)
                valid_curve.append(loss_val_mean)
                valid_acc.append(correct_val / total_val)
                print("Valid:\t Epoch[{:0>3}/{:0>3}] Iteration[{:0>3}/{:0>3}] Loss: {:.4f} Acc:{:.2%}".format(
                    epoch, MAX_EPOCH, j+1, len(valid_loader), loss_val_mean, correct_val / total_val))
            alexnet_model.train()

3.3 结果与分析

        迭代过程中,交叉熵损失与精确度变化情况如上图所示。训练和测试均设置batch为64。在训练过程中,每一个iteration,交叉熵损失与准确度进行一次计算。测试过程中,每一个epoch,交叉熵损失与准确度进行一次计算。整个过程设置了epoch=3。在图中可以看出,在第一个epoch后,模型逐渐趋于稳定,并且没有出现明显的过拟合或欠拟合现象。在最后一个epoch后,交叉熵损失为0.0765,准确率为96.60%。

  • 27
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的卷积神经网络猫狗识别Python代码,使用Keras框架: ```python import os import numpy as np from keras.preprocessing.image import load_img, img_to_array from keras.models import Sequential from keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout # 设置训练和验证数据集的路径 train_dir = 'train/' validation_dir = 'validation/' # 定义模型的架构 model = Sequential() model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(150, 150, 3))) model.add(MaxPooling2D((2, 2))) model.add(Conv2D(64, (3, 3), activation='relu')) model.add(MaxPooling2D((2, 2))) model.add(Conv2D(128, (3, 3), activation='relu')) model.add(MaxPooling2D((2, 2))) model.add(Conv2D(128, (3, 3), activation='relu')) model.add(MaxPooling2D((2, 2))) model.add(Flatten()) model.add(Dropout(0.5)) model.add(Dense(512, activation='relu')) model.add(Dense(1, activation='sigmoid')) # 编译模型 model.compile(loss='binary_crossentropy', optimizer='rmsprop', metrics=['accuracy']) # 定义生成器 from keras.preprocessing.image import ImageDataGenerator # 对训练和验证图像进行增强处理 train_datagen = ImageDataGenerator(rescale=1./255, rotation_range=40, width_shift_range=0.2, height_shift_range=0.2, shear_range=0.2, zoom_range=0.2, horizontal_flip=True) test_datagen = ImageDataGenerator(rescale=1./255) train_generator = train_datagen.flow_from_directory(train_dir, target_size=(150, 150), batch_size=32, class_mode='binary') validation_generator = test_datagen.flow_from_directory(validation_dir, target_size=(150, 150), batch_size=32, class_mode='binary') # 训练模型 history = model.fit_generator(train_generator, steps_per_epoch=100, epochs=100, validation_data=validation_generator, validation_steps=50) # 保存模型 model.save('cats_dogs_cnn.h5') ``` 注意:这个代码只是一个简单的示例,你需要根据自己的数据集和需求进行适当修改。同时,要提醒你注意数据集的准备和预处理,这对于模型的性能和准确性至关重要。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值