【精选】基于深度学习的卷积神经网络的水果分类系统

2024-01-03 11:56:21

1.研究背景与意义

项目参考AAAI Association for the Advancement of Artificial Intelligence

研究背景与意义

随着人工智能技术的不断发展,深度学习成为了计算机视觉领域的热门研究方向之一。卷积神经网络(Convolutional Neural Network,CNN)作为深度学习的重要组成部分,已经在图像分类、目标检测和语义分割等任务中取得了显著的成果。而水果分类作为计算机视觉领域中的一个重要应用场景,对于农业生产、食品安全和市场销售等方面具有重要意义。

水果分类系统的研究背景可以从以下几个方面来阐述。首先,随着人们生活水平的提高和对健康饮食的重视,水果的需求量不断增加。然而,传统的水果分类方法主要依赖于人工判断,存在主观性强、效率低下和易出错等问题。因此,开发一种基于深度学习的卷积神经网络的水果分类系统,可以提高水果分类的准确性和效率,满足市场需求。

其次,水果分类在农业生产中具有重要意义。农业生产中,对水果的分类可以帮助农民了解不同品种的水果的生长情况和产量,为农业生产提供科学依据。此外,水果分类还可以帮助农民对水果进行分级和定价,提高农产品的附加值和市场竞争力。

此外,水果分类系统还对食品安全具有重要意义。近年来,食品安全问题引起了广泛关注。水果作为人们日常饮食中不可或缺的一部分,其质量和安全性对人们的健康至关重要。然而,市场上存在一些不法商贩,他们可能会在水果中添加有害物质或者销售过期、变质的水果。通过建立一个基于深度学习的卷积神经网络的水果分类系统,可以帮助消费者识别出水果的品种和质量,提高食品安全意识。

最后,水果分类系统还对市场销售具有重要意义。在市场销售中,水果的品种和质量是消费者购买的重要因素之一。通过建立一个准确、高效的水果分类系统,可以帮助商家对水果进行分类和定价,提高市场竞争力。同时,消费者也可以通过该系统了解水果的品种和质量,做出更加明智的购买决策。

综上所述,基于深度学习的卷积神经网络的水果分类系统具有重要的研究背景和意义。它不仅可以提高水果分类的准确性和效率,满足市场需求,还可以在农业生产、食品安全和市场销售等方面发挥重要作用。因此,对于开展相关研究和应用具有重要的理论和实践价值。

2.图片演示

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.视频演示

基于深度学习的卷积神经网络的水果分类系统_哔哩哔哩_bilibili

4.深度学习基础

深度学习框架不是向传统的图像分类方法将特征提取和分类识别分步骤来实现,而是将二者器结合到一个框架中。在训练过程中不需要进行人工特征设计,操作过程简单并节省大量的时间。深度学习首先利用无监督学习进行自下而上的训练,每层的卷积核自动对输入数据或上层的特征图像进行特征提取,将每层得到的结果传到下一层,然后最高层用监督学习进行自上而下的微调,修改每层的参数,至训练结果达到最佳。深度学习与浅层学习相比具有许多优点[3.4];
⑴深度学习是通过对隐含层中非线性结构进行学习,从而调整网络参数来实现函数预测值与真实值的逼近,并且深度神经网络还可以在小样本数据中进行学习数据集的特征。深层网络结构的优势是,可以用较少的参数来表示比较复杂的函数[5]。
⑵深度学习的学习能力强可以很好地表示数据的特征,因为模型中包含多个隐含层,隐含层包含大量神经元,且网络层数深宽度广,理论上可以映射到任意函数,从而解决更复杂的问题。浅层神经网络在图像、语音等方面表现不佳,但深层神经网络可以通过对大量数据集进行训练和学习从而得到最佳结果。目前,深度学习在图像识别、人脸识别、自然语言处理、语音识别等应用领域取得优异成绩。
⑶经典的机器学习算法,在增加数据集的情况下并没有取得很好地效果,并且经典的机器学习算法往往需要更复杂的方法来提高网络的准确率。而深度学习神经网络在大批量数据集训练时,可以提高网络性能并得到良好的实验结果。并且迁移学习使的深度神经网络的适应性强,易于转换。
在这里插入图片描述

卷积神经网络

卷积神经网络是一类包含卷积计算且具有深度结构的前馈神经网络,是深度学习的代表算法之—[46]。卷积神经网络框架由特征映射和特征提取两部分组成,特征映射的目的是降维,就是将高维空间的特征向量映射到低维或者一维数据特征的过程,而且卷积神经网络的每个卷积层含有多个特征映射,也就是有多个平面,由于每个映射面上的神经元进行权值共享,因此大大减少了卷积神经网络的参数。特征提取是将卷积层中每个神经元的输入与前一卷积层中的多个神经元进行相互连接,在最高层将卷积层得到的局部信息进行综合起来得到全局信息的过程,即卷积神经网络通过卷积核和池化层去实现图片的特征提取。

卷积神经网络结构

卷积神经网络结构一般都包含多个网络层,由输入层、卷积层、激活函数层、下采样层以及全连接层组成。卷积神经网络的输入层的功能是将训练的数据进行输入到卷积神经网络中,一般输入的是图像,图像数据可以用矩阵进行表示,是卷积神经网络进行卷积操作的直接数据。卷积层的功能是对输入层的输入数据进行特征提取,其主要是通过卷积核进行加权平均提取图像特征,再进行卷积操作生成特征图像。激活函数层的功能是利用非线性因素,通过卷积神经网络逼近任何的非线性函数进行解决线形模型表达力不足的问题,常见的激活函数有ReLU(Rectified Linear Unit)、Tanh、Sigmoid等。下采样层的功能是对前面生成的特征图像进行信息筛选和特征选择,从而减少网络的训练参数。全连接层功能是将下采样层提取到的特征图像通过相邻层间的节点相连进行综合起来,再选择不同的损失函数作为卷积神经网络的目标函数进行分类、回归或者排序。
卷积神经网络模型与BP神经网络模型结构类似,都选用了前向传播计算输出值,反向传播调整权重和偏置的方法[7]。卷积神经网络与传统的神经网络进行比较可以发现,卷积神经网络可以进行权值共享稀疏连接。传统的神经网络是每个输出单元都与每个输入单元交互,而卷积神经网络是将每个神经元仅与输入神经元的一块区域连接,这种连接方式保证了学习后的过滤器能够对于局部的输入特征有最强的响应,目的是存储更少的参数,减少内存的使用。同时权值共享的方式将一组连接的卷积共享同一个权重,而不是每个连接分配一个不同的权重,通过权值共享这样可以达到减少参数的目的。

卷积神经网络的优化

卷积神经网络之所以能够取得突破性发展,除了图形处理器(GraphicsProcessing Unit, GPU)和现场可编程逻辑门阵列(Field-Programmable Gate Array,FPGA)等计算设备贡献之外,主要得益于一些新发展的网络训练,比如ReLUI48]、Dropout[491、Adamlsl和批量规范化(Batch Normalization, BN)[511,这些方法的应用加快了卷积网络训练的收敛速度。以下是对这些卷积神经网络特性的详细介绍。
激活函数的作用是加入非线性因素,从而提高线性模型的表达力,把激活的神经元的特征通过函数保留并映射到下一层。Sigmoid、Tanh或Softsign 等饱和非线性(Saturating Nonlinearities)函数是卷积神经网络的中常见的函数,其对解决神经网络的梯度消失问题有一定的效果,但与ReLU激活函数相比较其表现性能还是不佳。并且ReLU激活函数在指数运算量和求误差梯度时,会占用很少的内存空间且运算量也很少,而传统的激活函数的运算量会很大。ReLU激活函数是不饱和非线性激活函数(Non-Saturating Nonlinearity),其能很好的解决深层神经网络的梯度消失问题,并且收敛速度很快。
为了减少数据的过拟合现象,Hinton教授和 Yann LeCun 等人[49]提出了“Dropout”和“DropConnect”的方法。Dropout是通过在训练时将隐藏层中部分神经元输出值设置为0,形成稀疏网络,减少了某些神经元之间特定的共适应关系,不仅提高了网络的运算速度而且加强了网络泛化能力,从而很好的解决过拟合问题。dropout作用和Ll,L2正则化相似,都是减少网络的权重,提高了网络的鲁棒性。
Adam优化算法被称为适应性矩估计(Adaptive Moment Estimation),是在2015年由OpenAI 的Diederik Kingma和多伦多大学的Jimmy Ba提出的,是一种替代传统随机梯度下降算法的一种优化算法。

5.核心代码讲解

5.1 canshu.py

根据代码中的注释,我将核心部分封装为一个名为"Canshu"的类:

class Canshu:
    def __init__(self):
        """路径参数"""
        self.train_img_dir = "./sample/train" #训练集路径
        self.test_img_dir = "./sample/test" #测试集路径
        self.model_save_dir = "./model" #模型保存路径

        """种类参数"""
        self.labels = ['buddhahand','durian','mangosteen','rambutan','sugar apple'] #种类标签
        self.num = len(self.labels) #种类数

        """图片参数"""
        self.image_width = 64 #图片统一宽度
        self.image_height = 64 #图片统一高度

        """训练参数"""
        self.train_ratio = 0.9 #训练集比例
        self.train_batch_size = 100 #训练集批次大小
        self.val_batch_size = 100 #验证集批次大小
        self.epochs = 60 #训练次数
        self.lr = 0.0001 #学习率  0.000005

这个类包含了代码中的核心参数信息,并且将这些参数封装在一个类中,方便调用和管理。

该程序文件名为canshu.py,主要用于存储参数信息。

首先,该文件定义了一些路径参数,包括训练集路径(train_img_dir)、测试集路径(test_img_dir)和模型保存路径(model_save_dir)。

接下来,定义了种类参数,其中labels为一个包含了五个种类标签的列表,num为种类数。

然后,定义了图片参数,包括图片统一宽度(image_width)和图片统一高度(image_height)。

最后,定义了训练参数,包括训练集比例(train_ratio)、训练集批次大小(train_batch_size)、验证集批次大小(val_batch_size)、训练次数(epochs)和学习率(lr)。

整体而言,该程序文件主要用于存储各种参数信息,方便其他程序文件进行调用和使用。

5.2 ImprovedVGG16.py

封装为类后的代码如下:



class ImprovedVGG16(nn.Module):
    def __init__(self):
        super(ImprovedVGG16, self).__init__()
        original_vgg16 = models.vgg16(pretrained=True)
        self.features = original_vgg16.features
        self.avgpool = original_vgg16.avgpool
        self.classifier = nn.Sequential(
            nn.Linear(512 * 7 * 7, 4096),
            nn.ReLU(True),
            nn.Dropout(),
            nn.Linear(4096, 4096),
            nn.ReLU(True),
            nn.Dropout(),
            nn.Linear(4096, 4)  # 假设是四类
        )

    def forward(self, x):
        x = self.features(x)
        x = self.avgpool(x)
        x = torch.flatten(x, 1)
        x = self.classifier(x)
        return x

这个程序文件是一个改进的VGG16模型的实现。它使用了PyTorch的torchvision库中的models模块来导入VGG16模型。该模型包含了原始VGG16模型的特征提取部分和分类器部分。

在初始化方法中,首先通过models.vgg16(pretrained=True)加载了预训练的VGG16模型。然后将原始模型的特征提取部分赋值给self.features,平均池化层赋值给self.avgpool,分类器部分赋值给self.classifier。分类器部分由三个全连接层组成,分别是输入维度为512 * 7 * 7,输出维度为4096的线性层,ReLU激活函数,Dropout层,输入维度为4096,输出维度为4096的线性层,ReLU激活函数,Dropout层,输入维度为4096,输出维度为4的线性层(假设有四个类别)。

在前向传播方法中,输入数据经过特征提取部分和平均池化层后,通过torch.flatten将特征张量展平为一维。然后将展平后的特征张量输入到分类器部分,得到最终的输出。

5.3 LeNet-5.py
import torch
import torch.nn as nn
import torch.nn.functional as F

class ImprovedLeNet5(nn.Module):
    def __init__(self):
        super(ImprovedLeNet5, self).__init__()
        self.conv1 = nn.Conv2d(3, 6, 5)  # 假设输入是3通道的彩色图像
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 4)  # 分为四类

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = x.view(-1, 16 * 5 * 5)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x

这个程序文件是一个改进版的LeNet-5模型,用于图像分类任务。它包含了卷积层、池化层和全连接层。

  • ImprovedLeNet5 类继承自 nn.Module,是模型的主体部分。
  • __init__ 方法定义了模型的结构,包括两个卷积层、两个池化层和三个全连接层。其中,第一个卷积层输入通道数为3,输出通道数为6;第二个卷积层输入通道数为6,输出通道数为16。全连接层的输出维度分别为120、84和4,用于分类任务中的四个类别。
  • forward 方法定义了数据在模型中的前向传播过程。首先通过卷积层和激活函数ReLU进行特征提取,然后通过池化层进行下采样,接着将特征展平为一维向量,最后通过全连接层得到分类结果。

该模型适用于输入为3通道的彩色图像,输出为四个类别的分类任务。

5.4 model.py


class VGG:
    def __init__(self, num):
        self.num = num

    def model_CNN(self):
        model = keras.Sequential([
            layers.Conv2D(64, 3, strides=(1, 1), padding="same", activation="relu"),
            layers.Conv2D(64, 3, strides=(1, 1), padding="same", activation="relu"),
            layers.MaxPool2D(2, 2),
            layers.Conv2D(128, 3, strides=(1, 1), padding="same", activation="relu"),
            layers.Conv2D(128, 3, strides=(1, 1), padding="same", activation="relu"),
            layers.MaxPool2D(2, 2),
            layers.Conv2D(256, 3, strides=(1, 1), padding="same", activation="relu"),
            layers.Conv2D(256, 3, strides=(1, 1), padding="same", activation="relu"),
            layers.Conv2D(256, 3, strides=(1, 1), padding="same", activation="relu"),
            layers.Conv2D(256, 3, strides=(1, 1), padding="same", activation="relu"),
            layers.MaxPool2D(2, 2),
            layers.Conv2D(512, 3, strides=(1, 1), padding="same", activation="relu"),
            layers.Conv2D(512, 3, strides=(1, 1), padding="same", activation="relu"),
            layers.Conv2D(512, 3, strides=(1, 1), padding="same", activation="relu"),
            layers.Conv2D(512, 3, strides=(1, 1), padding="same", activation="relu"),
            layers.MaxPool2D(2, 2),
            layers.Conv2D(512, 3, strides=(1, 1), padding="same", activation="relu"),
            layers.Conv2D(512, 3, strides=(1, 1), padding="same", activation="relu"),
            layers.Conv2D(512, 3, strides=(1, 1), padding="same", activation="relu"),
            layers.Conv2D(512, 3, strides=(1, 1), padding="same", activation="relu"),
            layers.MaxPool2D(2, 2),
            layers.Flatten(),
            layers.Dense(256, activation="relu"),  # 256
            layers.Dense(128, activation="relu"),
            layers.Dense(self.num, activation="softmax")
        ])
        return model

这个程序文件名为model.py,是一个用于构建模型的文件。文件中定义了一个名为model_CNN的函数,用于构建一个卷积神经网络模型。模型使用了VGG19的结构,包括多个卷积层、池化层和全连接层。模型的输入是一个数字num,输出是一个softmax分类器。模型的具体结构可以在代码中找到。

5.5 predict.py
# -*- coding: utf-8 -*-




class ImageClassifier:
    def __init__(self, model_path):
        self.model = tf.keras.models.load_model(model_path)

    def preprocess_image(self, image_path):
        test_data = TestDataSet()
        image = test_data.preprocess_img_all([image_path])[0]  # 预处理图片
        image = tf.expand_dims(image, axis=0)  # 增加 batch 维度
        return image

    def predict(self, image):
        prediction = self.model.predict(image)[0]  # 预测图片类别
        predicted_label = np.argmax(prediction)  # 获取最大概率类别的索引
        confidence = prediction[predicted_label]  # 获取置信度
        label = canshu.labels[predicted_label]  # 将索引转换为标签
        return label, confidence

这个程序文件名为predict.py,它的功能是使用已加载的模型对单张图片进行分类预测。程序首先导入了必要的库和模块,包括os、numpy、pathlib、canshu、tensorflow和test。然后定义了一个函数predict_image,用于预测单张图片的类别和置信度。在主函数中,程序指定了待预测的图片路径和模型路径,并加载了模型。接着调用predict_image函数对图片进行预测,并打印出分类结果和置信度。

5.6 preproccess.py

class ImageDataSet:
    def __init__(self):
        self.num = canshu.num #种类数
        self.train_batch_size = canshu.train_batch_size #训练批次大小
        self.val_batch_size = canshu.val_batch_size #验证批次大小

        data_root = pathlib.Path(canshu.train_img_dir) #创建训练图片路径对象
        image_paths = list(data_root.glob("*")) #遍历匹配所有(*)目录并存放到列表中
        image_paths = self.read_path(image_paths) #获取所有图片文件路径(含文件名)
        random.shuffle(image_paths) #随机打乱

        #划分训练集验证集
        self.train_image_paths = image_paths[:int(canshu.train_ratio * len(image_paths))] #训练集
        self.val_image_paths = image_paths[int(canshu.train_ratio * len(image_paths)):] #验证集


    #数据训练前处理并打包
    def build(self):
        """
        :return: 预处理后的训练集和验证集
        """
        #训练集
        img_train_list = self.preprocess_img_all(self.train_image_paths) #加载图片并预处理
        train_image_ds = tf.data.Dataset.from_tensor_slices(img_train_list) #训练集数据打包
        train_all_images_labels = [self.text2vec(pathlib.Path(path).name.split("_")[0]) for path in self.train_image_paths] #获取独热编码
        train_label_ds = tf.data.Dataset.from_tensor_slices(tf.cast(train_all_images_labels, tf.int32)) #训练集标签打包
        train_set = tf.data.Dataset.zip((train_image_ds, train_label_ds)) #合并数据和标签
        train_set = train_set.batch(self.train_batch_size, drop_remainder=True).prefetch(tf.data.experimental.AUTOTUNE) #训练前处理操作

        #验证集
        img_val_list = self.preprocess_img_all(self.val_image_paths)
        val_image_ds = tf.data.Dataset.from_tensor_slices(img_val_list)
        val_all_images_labels = [self.text2vec(pathlib.Path(path).name.split("_")[0]) for path in self.val_image_paths]
        val_label_ds = tf.data.Dataset.from_tensor_slices(tf.cast(val_all_images_labels, tf.int32))
        val_set = tf.data.Dataset.zip((val_image_ds, val_label_ds))
        val_set = val_set.batch(self.val_batch_size, drop_remainder=True).prefetch(tf.data.experimental.AUTOTUNE)
        return train_set, val_set


    #所有图片预处理
    def preprocess_img_all(self, paths):
        """
        :param paths: 照片路径(含文件名)
        :return: 灰度后的图片矩阵
        """
        img_list = [] #存储图片矩阵
        for path in paths: #逐个图片获取
            image = tf.io.read_file(path)  #读取图片文件
            image = tf.image.decode_png(image, channels=3)  #解码图像所需的彩色通道数目,输出RGB图像
            image = tf.image.resize(image, [canshu.image_height,canshu.image_width])  #调整图片大小
            image = 2 * tf.cast(image, dtype=tf.float32) / 255. - 1  #归一化
            r, g, b = image[:, :, 0], image[:, :, 1], image[:, :, 2] #获取各个通道像素值
            image = 0.2989 * r + 0.5870 * g + 0.1140 * b #灰度处理
            image = tf.expand_dims(image, axis=2)  #增加维度,灰度后维度降低
            img_list.append(image)
        return img_list


    #标签转为独热编码
    def text2vec(self,text):
        """
        :param text: 标签值
        :return: 独热编码
        """
        text_num = canshu.labels.index(text) #获取标签列表的下标索引作为标签的唯一数字标识
        vector = np.zeros(self.num)  #初始化独热编码矩阵
        vector[text_num] = 1  #对应位置置一
        return vector


    #获取所有图片文件路径(含文件名)
    def read_path(self,paths):
        """
        :param paths: 父文件夹路径
        :return: 所有子孙图片文件
        """
        file_all = [] #存储图片文件路径
        for i in range(len(paths)): #逐个路径获取
            for file_name in os.listdir(paths[i]):  #逐个获取指定目录下的所有子目录和文件名
                full_path = os.path.abspath(os.path.join(paths[i],file_name))#合并路径
                if os.path.isdir(full_path):  #判断路径对象是否为文件夹
                    file_all.extend(full_path) #追加子文件夹中的图片文件列表
                else: #路径对象为文件
                    if file_name.endswith('.jpg') or file_name.endswith('.bmp') or file_name.endswith('.png'): #文件后缀是否为'.jpg'、'.bmp'、'.png'(是否为图片文件)
                        file_all.append(full_path)
        return file_all

该程序文件名为preprocess.py,是一个用于数据加载和预处理的程序。

程序首先通过read_path方法读取文件夹中的所有子文件夹的图片文件路径,并对路径进行打乱。然后,程序根据设定的训练集和验证集比例划分训练集和验证集。

接下来,程序通过preprocess_img_all方法对图片进行加载和预处理。预处理过程包括调整图片大小、归一化、灰度处理,并增加维度。

然后,程序通过text2vec方法将图片标签进行独热编码转换。

最后,程序将图片矩阵数据和独热编码标签打包并分批处理,返回预处理后的训练集和验证集。

6.系统整体结构

整体功能和构架概述:

该项目是一个基于深度学习的卷积神经网络的水果分类系统。它包含了多个程序文件,每个文件负责不同的功能。以下是每个文件的功能概述:

文件名功能概述
canshu.py存储参数信息,包括路径参数、种类参数、图片参数和训练参数
ImprovedVGG16.py实现改进的VGG16模型,包括特征提取部分和分类器部分
LeNet-5.py实现改进版的LeNet-5模型,用于图像分类任务
model.py构建一个卷积神经网络模型,使用VGG19的结构
predict.py使用已加载的模型对单张图片进行分类预测
preprocess.py数据加载和预处理,包括读取文件路径、划分训练集和验证集、加载和预处理图片
rename.py对图片文件进行重命名,用于数据集的整理
test.py对模型进行测试,计算准确率和损失
train.py训练模型,包括模型的初始化、前向传播、反向传播和参数更新
turn.py图片旋转处理,用于数据增强
ui.py用户界面,用于交互式操作和展示结果
init.py初始化文件,用于标识该目录为一个Python包

7.数据集的构建

图像分类是根据图像中信息特征,对不同目标进行识别分类,而数据集在整个实验过程中起到至关重要的作用。图像数据集在图像分类、图像识别、图像处理和行为分析等视觉对象识别研究方面起着关键的作用。神经网络训练的基础都是建立在通用和特定用途的数据集上,数据集是研究人员的必备工具,只有用高质量、清晰度高的数据集进行训练和测试,这样得到的结果才能更加准确。因为没有公开的和现存的数据集,所以需要构建用于品质分类的数据集。数据集的构建主要包含数据采集、数据标注和数据集分割三个步骤。
在这里插入图片描述

数据集采集

数据集是深度学习研究的基础,而优质的、高度清晰的数据集才能使神经网络模型训练的更加有意义。数据集是通过现场采集和网络采集得到。
现场采集是指在脐橙果园或水果超市对果实进行拍照。这些地方数量多并包含了大部分的特征,所以现场采集方法不仅能保证拍摄数据图片的质量,还可以保证拍摄样本的多样性。但需要注意的是,这些是在不同的光照条件、场景背景和角度下拍摄的,所以要将拍摄的照片进行进一步的处理。
网络采集是利用网络爬虫技术从网页上批量获取果实图像。网络爬虫是一段自动提取网页的程序或者脚本,其是按照一定的规则,从网络上获得所需的信息,它是搜索引擎的重要组成部分[7]。基于Python语言图片爬虫技术可以快捷、高效的从网络上批量下载所需的数据,这是大家目前最常用的方法之一。
网络爬虫工作流程如图所示,具体步骤为:⑴通过脚本请求Web服务器的资源,批量构建索引页地址;(⑵获取响应内容,如果能正常响应,会得到一个Response,其内容就是各个图片的地址内容;⑶3解析相应获取的内容,将图片的地址存于列表中;(4存储数据,使用Requests下载图片,并将下载的文件保存至数据库,或特定文件夹。
在这里插入图片描述

最后,对所有采集的脐橙图像数据进行筛选,将不清晰、不合格的图片删除,将留下的图片进行格式统一化处理,图像尺寸统一固定为长为64像素、宽为64像素、水平分辨率为96像素、垂直分辨率为96像素。

8.卷积神经网络模型

由于数据集样本量不是很大,同时考虑网络训练时间的长短等因素,在LeNet-5模型的基础上进行参数改进,采用一个由2个卷积层、2个池化层、一个全连接层和一个 Softmax分类函数组成的网络模型。卷积神经网络模型如图所示。
在这里插入图片描述

⑴输入层,将脐橙图片作为输入.x,其大小是64×64像素矩阵,是RGB三通道。CNN结构的大小一般是依据输入图像进行设置。
⑵卷积层C,卷积层是滤波器对输入的脐橙图像的像素矩阵进行卷积操作,从而得到特征图像。卷积操作的优势是对输入数据可以最大程度的提取并保留最原始的信号特征,并且可以对信号特征进行增强和降低噪声对信号的干扰。我们将卷积核的大小设置为5×5,因为卷积核的大小会影响特征图像的提取,如果选取的卷积核尺寸太小可能会使提取的部分特征图像无效,如果设置卷积核尺寸太大则会使从输入图像或特征图中提取到的特征的复杂度超出卷积核的表示能力R)。我们将输入层输入的64×64像素图片进行卷积操作,用12个5×5大小的卷积核去卷积64×64大小的图片。用输入的图片去遍历每个卷积核,从而得到60×60的特征图,最终获得12个60×60大小特征图。然后通过ReLU激活函数进行计算。C,层卷积操作的公式表达如式所示:
在这里插入图片描述

其中,w,表示卷积核,b。表示偏置,f(x)是ReLU激活函数。
3下采样层S,下采样层是对前一层Cr输出的特征图像生成对应的缩略图,它是通过放大或缩小Ci输入的特征图来降低图像分辨率,减少了训练参数的数量,并降低输出的特征向量的维度。当图片像素在邻域发生微小位移时,池化层的结果不会改变,这样就保留了图片中比较重要的信息特征,从而增强了网络的鲁棒性l55]。本文将MAX_Pool滤波器设置为2×2大小,如果缩放因子的值过大会使提取的图像特征更加粗糙,导致很多细节特征被忽略,如果缩放因子过小又会对下采样的结果产生一定的影响,所以在选择缩放因子的大小时要谨慎考虑[7]。C1中输出的特征图大小为60×60,将MAX_Pool滤波器和C1中的特征图进行最大池化,得到12个30×30的特征图像。下采样计算公式为:
在这里插入图片描述

然而Si层与Cz层之间并不存在一一对应的关系,Cz层得到的特征图则是按照一定的规则对Si中的特征图进行选取并进行卷积操作,这种连接被称为稀疏连接(Sparse Connection)[47]。与前馈神经网络中的全连接相比,稀疏连接是卷积层中的神经元只和其相邻层的神经元进行部分连接,并不是全部相连。具体的讲,卷积神经网络第L层特征图中的每个神经元都仅是与L-1层中的感受野内的像素进行线性组合。稀疏连接效果是将网络正则化,不仅对网络结构的稳定性和泛化能力有所提高,同时还避免了网络过度拟合现象。同时,稀疏连接可以大大减少权重数量,不但提高了神经网络学习速度,而且减少了网络内存开销[9]。具体的卷积计算为:
在这里插入图片描述

全连接层将获得的图像特征,在Softmax函数进行分类。Softmax函数一般用于解决多分类问题,能够一次完成多个分类任务。Softmax函数就是将全连接层输出值就转化为[0,1]的范围,并且这些值满足累加起来结果为1的特性,然后选取概率值最大的节点作为输出节点。Softmax函数收敛效果很好,可以达到全局最小值,从而解决了因局部收敛而出现的过拟合问题。Softmax函数是一种有监督的单层神经网络的分类器,它一般与深度学习的方法相结合从而用于分类识别问题[59]。Softmax 的代价函数可以表示为:
在这里插入图片描述

其中,k表示神经元的个数,x,为多个输入。通过此式每个输出都映射到了0到1区间,可以看成是概率。

9.训练结果分析

经过训练得到的损失率如图所示。根据图可知,随着训练次数的增加Loss率越来越低,基本训练的损失率都在0.2以下。由于个别样本比较难以确认分类使损失率在某时刻较高,但整体的损失率都较低,在训练迭代了8000次时Loss率趋势比较平缓,达到一定的稳定水平,由此来看卷积神经网络模型的训练是比较成功的。
在这里插入图片描述

通过多次的实验,我们取实验结果的平均值,从而进一步说叨我们的实验结果的准确性。我们用测试准确率和测试损失率来验证我们实验的效果。经过多次训练和测试,得到较好的训练模型,测试的准确率和损失率分别如图所示。由图可知,我们的测试准确率整体呈上升趋势,并且准确率一直在90%以上。在迭代8500次时,准确率达到最高点。从图3.5很明显的看出,测试的损失率呈直线下降趋势,在迭代2000次以后,Loss率全部在0.2以下,这说明我们的模型的性能很好。在迭代6000次以后,损失率基本呈平缓趋势。根据图可以得出,我们的实验准确率很高,网络性能比较好。
在这里插入图片描述
在这里插入图片描述

为了验证本章实验方法的有效性,我们将自己的卷积神经网络与现有的四种水果分类的方法进行了比较。这些方法分别为PCA+KSVM、FRFE+BPNN[1]、PCA+FSCABC、和 FRFE+IHGA[6]。这些方法全部都是传统的水果分类方法。都是先经过特征提取,然后用分类器进行分类。因为特征提取需要人工设计图像特征是靠以往经验,所以具有很大的盲目性且过程比较复杂、繁琐。并且分类器结构简单,可能无法将复杂特征映射到最终识别结果,从而使分类准确率不是很高,性能表现不好。我们将本章的方法和其他四种分类方法进行了对比,实验结果如表所示。我们的卷积神经网络方法的总体准确率达到94.80%,比方法FRFE+IHGA高出5.21%。经实验验证本文所设计的卷积神经网络要比传统水果分类方法具有更优越的性能。
在这里插入图片描述

10.系统整合

下图[完整源码&数据集&环境部署视频教程&自定义UI界面]

在这里插入图片描述

参考博客《基于深度学习的卷积神经网络的水果分类系统》

文章来源:https://blog.csdn.net/cheng2333333/article/details/135335431
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。