基于TensorFlow和Keras的猫狗图像分类(构建CNN卷积神经网络模型)

在计算机视觉领域,卷积神经网络(CNN)凭借其强大的特征提取能力,成为图像分类任务的首选模型架构。本文将以猫狗图像二分类任务为例,深入讲解如何使用TensorFlow和Keras构建一个完整的CNN模型,涵盖数据预处理、模型构建、训练评估、模型保存与加载,以及单张图片预测等全流程。

本项目的训练模型和训练代码以及检测代码仓库:
https://github.com/zhouxy2003/cat_dog_detect.git
创作不易,如果能帮到你,希望给一个star⭐

cat_dog_detect/
├── main.py                     # 训练脚本,使用 dataset 中的数据训练 CNN 模型,并保存权重文件
├── detect.py                   # 检测脚本,加载模型权重并对新图像进行猫狗分类
├── cat_dog_detect.weights.h5   # 已训练好的模型权重文件(由 main.py 生成)
├── createCNN/                  # 模型构建模块目录
├── dataset/                    # 过大未提供可按照以下示例创建

一、数据预处理:为模型训练奠定基础

数据预处理是模型训练前的关键步骤,其核心目标是将原始图像数据转化为适合模型输入的格式,并通过数据增强技术提升数据的多样性,增强模型的泛化能力。数据集结构如下所示。

dataset
├── training_set
│   ├── cats
│   │   ├── cat_image_1.jpg
│   │   ├── cat_image_2.jpg
│   │   └──...
│   └── dogs
│       ├── dog_image_1.jpg
│       ├── dog_image_2.jpg
│       └──...
└── test_set
    ├── cats
    │   ├── cat_image_3.jpg
    │   ├── cat_image_4.jpg
    │   └──...
    └── dogs
        ├── dog_image_3.jpg
        ├── dog_image_4.jpg
        └──...

1.1 图像增强:扩充数据集

在猫狗图像分类任务中,数据集的规模和多样性直接影响模型的性能。通过图像增强技术,可以在不增加额外数据采集成本的情况下,生成更多样化的训练样本。

train_datagen = ImageDataGenerator(
                    rescale=1./255,          #像素归一化
                    shear_range=0.2,         #改变图像形状
                    zoom_range=0.2,          #进行缩放
                    horizontal_flip=True,    #水平翻转
                )

使用ImageDataGenerator类进行图像增强,主要操作包括:

  • 像素值归一化(rescale:将图像像素值从默认的[0, 255]区间缩放到[0, 1],这有助于加快模型的收敛速度,提高训练效率。
  • 随机剪切变换(shear_range:对图像进行随机角度的剪切,模拟不同视角下的图像变化。
  • 随机缩放(zoom_range:对图像进行随机比例的缩放,模拟目标在图像中远近不同的视觉效果。
  • 随机水平翻转(horizontal_flip:以一定概率对图像进行水平翻转,增加样本的多样性,尤其适用于图像左右对称的场景。

1.2 创建数据生成器:批量加载数据

数据生成器负责从磁盘读取图像数据,并按照指定的参数进行预处理和批量加载。在训练过程中,数据生成器会自动从指定目录中读取图像,应用数据增强操作,并将图像和对应的标签以批次的形式输送给模型。

train_set = train_datagen.flow_from_directory(
                    directory='./dataset/training_set',   #数据集路径
                    target_size=(64,64),                  #尺寸大小
                    batch_size=32,                        #每个批次大小
                    class_mode='binary'                   #分类模式:二分类
                )

通过flow_from_directory方法,我们可以方便地将图像数据组织成适合模型训练的格式,同时指定图像尺寸、批次大小和标签模式。

二、构建卷积神经网络:搭建模型架构

CNN的设计需要结合任务特点和数据特性,合理选择网络层数、卷积核大小、激活函数等参数。在猫狗图像分类任务中,我们采用经典的CNN架构,由卷积层、池化层、展平层和全连接层组成。结构图如下所示。
在这里插入图片描述
本项目的任务是进行猫🐱与狗🐕的识别,属于典型的二分类问题。在网络结构中,卷积层使用了ReLU激活函数(ReLU(x)=max(0, x)),以引入非线性特性并加速收敛;在输出层,采用Sigmoid激活函数,将输出映射至[0,1]区间,以便进行二分类判别。

通过tf.keras构建顺序模型添加每一层

CNN模型
├── 输入层 (图像输入)
├── 第一组卷积层
│   └── 卷积操作 (filters=32, kernel_size=(3,3), activation='relu')
├── 第一组池化层
│   └── 最大池化操作 (pool_size=(2,2), strides=(2,2))
├── 第二组卷积层
│   └── 卷积操作 (filters=32, kernel_size=(3,3), activation='relu')
├── 第二组池化层
│   └── 最大池化操作 (pool_size=(2,2), strides=(2,2))
├── 展平层
│   └── 将多维特征图展平为一维向量
├── 全连接层
│   └── 神经元 (units=128, activation='relu')
└── 输出层
    └── 神经元 (units=1, activation='sigmoid')

2.1 卷积层与池化层:特征提取与降维

卷积层是CNN的核心组成部分,通过卷积核在图像上滑动,提取图像的局部特征。每个卷积层后通常会连接一个池化层,用于降低数据维度,减少计算量,同时保留重要特征。

我们构建了两组卷积层和池化层,通过调整卷积核数量和大小,逐步提取图像的高级语义特征。

2.2 展平层与全连接层:特征整合与分类决策

展平层将卷积层和池化层输出的三维特征图转化为一维向量,以便输入到全连接层。全连接层通过学习特征之间的复杂关系,输出最终的分类结果。

在输出层,我们使用sigmoid激活函数,将输出值映射到[0, 1]区间,用于二分类任务的概率预测。

三、训练与评估模型:优化模型性能

模型训练是调整模型参数以最小化损失函数的过程,而模型评估则用于验证模型在新数据上的泛化能力。

3.1 编译模型:选择优化器和损失函数

在编译模型时,我们需要选择合适的优化器、损失函数和评估指标。对于二分类任务,通常使用binary_crossentropy作为损失函数,adam作为优化器,并选择accuracy作为评估指标。

cnn.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

3.2 训练模型:迭代优化模型参数

通过fit方法进行模型训练,指定训练数据集、验证数据集和训练轮数。在训练过程中,模型会根据损失函数的反馈不断调整参数,逐步提高分类准确率。使用的数据集约4000张图片。30轮后准确率可达90%左右。

cnn.fit(x=train_set, validation_data=test_set,epochs=30)

四、保存与加载模型权重:持久化模型

为了避免重复训练,我们可以将训练好的模型权重保存到文件中,并在需要时加载使用。这对于部署模型和后续优化非常重要。

cnn.save_weights('cat_dog_detect.weights.h5')

五、单张图片预测:应用模型进行推理

训练好的模型可以用于对单张图片进行预测。首先需要对图片进行预处理,使其格式与训练数据一致,然后输入模型进行预测,最后根据预测结果判断图片中的动物是猫还是狗。

cnn.load_weights('./cat_dog_detect.weights.h5')

test_image = image.load_img('./cod4.jpg', target_size=(64,64,3))
test_image = np.expand_dims(test_image, axis = 0)
result = cnn.predict(test_image)

这里解释一下参数含义:
target_size=(64,64,3):因为训练时对输入图像大小调整为64x64,颜色通道为3,即为彩色rgb.
axis = 0: 我们在构建网络时,需多添加一个维度

Model: "sequential"
┌─────────────────────────────────┬────────────────────────┬───────────────┐
│ Layer (type)                    │ Output Shape           │       Param # │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ conv2d (Conv2D)                 │ (None, 62, 62, 32)     │           896 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ max_pooling2d (MaxPooling2D)    │ (None, 31, 31, 32)     │             0 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ conv2d_1 (Conv2D)               │ (None, 29, 29, 32)     │         9,248 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ max_pooling2d_1 (MaxPooling2D)  │ (None, 14, 14, 32)     │             0 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ flatten (Flatten)               │ (None, 6272)           │             0 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ dense (Dense)                   │ (None, 128)            │       802,944 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ dense_1 (Dense)                 │ (None, 1)              │           129 │
└─────────────────────────────────┴────────────────────────┴───────────────┘

shape如上所示。

我们该如何知道1代表🐱还是🐕呢,我们可以通过print(train_set.class_indices)进行获取映射关系,其会将数据集的类别进行自动分类映射。
识别效果如下(图片取自网络,侵权联系删除谢谢):
在这里插入图片描述

总结与展望

通过本文的实践,我们完成了一个完整的猫狗图像分类项目,掌握了从数据预处理到模型部署的全流程。然而,这只是CNN应用的起点。希望可以帮您对cnn结果有所了解。
Enjoy Deep learning!🚀

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值