【深度学习】使用Tensorflow和Keras对本地数据集进行图像分类以及性能调优

1. 背景

学习深度学习框架Tensorflow的Keras框架进行图像分类,按照网上的教程一步步来,记录要点和总结

2. 要点

1. 准备本地数据集
2. 使用Keras加载本地数据集,分为训练集和测试集,并进行磁盘读取优化
3. 手动创建网络,添加自定义层
4. 针对过拟合的处理
5. 性能调优

总结

本程序的目的是利用tensorflow框架进行图像分类

要点:

    1. 本地准备数据集

    2. 利用tensorflow tf.keras.utils.image_dataset_from_directory将本地文件生成Dataset对象

    3. 利用Dataset.to_numpy()将验证数据集的images和labels转换成numpy数组,以便验证预测的正确性

    4. 使用自定义优化器在训练过程中随训练次数降低学习率,防止过拟合

    5. 使用数据集中的充分打乱和重复数据,防止过拟合

    6. 使用在神经网络中添加数据增强层(随机旋转,随机缩放,随机翻转)防止过拟合

    7. 使用在神经网络中添加Dropout层,(目的是在网络的输出中随机丢弃一定比率的数据,防止过拟合

    8. 在训练完成后,使用plt生成准确率和损失值的趋势图,方便分析和调整

3.1 准备本地数据集

准备图片目录结构如下

-DataSet

        -Daisy

                -XXX.jpg

                -YYY.jpg

                -...

        -Sunflowers

                -XXX.jpg

                -YYY.jpg

                ...

        -...

要点就是文件夹里面放同一类型的图片,文件夹名称就是这些图片的标签

3.2 加载数据集

train_ds = tf.keras.utils.image_dataset_from_directory(
        train_data_dir,
        seed=123, #将样本打乱的随机数种子
        image_size=(image_height, image_width),
        batch_size=batch_size #批次大小,受制于系统性能
    ).shuffle(32) #使用shuffle将图片打乱

    # single_data = list(train_ds.as_numpy_iterator())
    # label = single_data[0]
    
    val_ds = tf.keras.utils.image_dataset_from_directory(
        test_data_dir,
        seed=123,
        image_size=(image_height, image_width),
        batch_size=1
    )

3.3 手动创建网络,添加自定义层

# 定义一个序贯模型
model = tf.keras.Sequential(
    [
        # 归一化层,通常用于加速模型的训练并提高其性能 【0~255】 -> 【0~1】
        normalization_layer,

        # 接下来是三个卷积层,每个卷积层后都接一个ReLU激活函数
        tf.keras.layers.Conv2D(
            16, 3, activation='relu'),
        # 接下来是一个最大池化层,用于降低特征图的尺寸,从而减少计算复杂度
        tf.keras.layers.MaxPool2D(),

        # 第二个卷积层和最大池化层
        tf.keras.layers.Conv2D(
            32, 3, activation='relu'),
        tf.keras.layers.MaxPool2D(),

        # 第三个卷积层和最大池化层
        tf.keras.layers.Conv2D(
            64, 3, activation='relu'),
        tf.keras.layers.MaxPool2D(),

        # Flatten层将卷积层的输出拉平,为全连接层做准备
        tf.keras.layers.Flatten(),
        # 第一个全连接层,128个神经元,激活函数为ReLU
        tf.keras.layers.Dense(128, activation='relu'),
        # 最后一个全连接层,numclasss个神经元,用于分类任务,不使用激活函数
        tf.keras.layers.Dense(numclasss)
    )
)

4 针对过拟合的处理

上面的网络训练小样本数据集会出现明显的过拟合,验证集的准确率只有大约50%,大约当epoch 大于3的时候就开始出现过拟合,我现在没有结果截图了,有兴趣的可以尝试

4.1 过拟合发生的原因

1. 训练数据集太小或缺乏代表性。如果训练集数据量太小,模型可能会在训练过程中过于拟合训练数据,导致在新的、未见过的数据上表现不佳。同时,如果训练数据缺乏代表性,模型可能无法泛化到所有可能的情况,从而产生过拟合。
2. 训练集样本存在的噪音干扰过大。如果训练样本中存在大量噪声,模型可能会过度关注这些噪声,从而忽略真实的输入输出关系,导致过拟合。
3. 模型复杂度过高。如果所使用的模型复杂度超过训练数据的复杂性,模型可能会过度拟合训练数据,产生过拟合现象。
4. 训练过程中的优化方法不当。例如,如果使用了过于复杂的优化算法(如过多的迭代次数),可能会使模型在训练过程中过于追求最小化损失函数,从而产生过拟合。
5. 验证集和测试集与训练集分布不一致。如果验证集和测试集的数据分布与训练集的数据分布相差太大,那么模型在这些数据集上的表现可能不佳,导致过拟合。
6. 数据集中的类别不平衡。如果数据集中某些类别的样本数量远大于其他类别,模型可能会过度关注数量较多的类别,从而忽略数量较少的类别,导致过拟合。
7. 特征选择不当。如果所选特征与预测目标无关或相关性不大,那么模型在这些特征上的学习就可能是无效的,甚至可能导致过拟合。
8. 超参数调整不当。模型的超参数如学习率、批次大小、正则化参数等调整不当,也可能导致过拟合。

4.2 减少过拟合的方法

为了防止过拟合,可以采取以下措施:

1. 增加训练数据集的数量和多样性,使其更具代表性。
对训练数据进行预处理,如去噪、归一化等,以减少噪声对模型的影响。
2. 选择合适的模型复杂度,避免过于复杂的模型。
3. 选择合适的优化算法和参数,避免过度优化。
4. 验证集和测试集应该与训练集保持一致的数据分布。
5. 对于类别不平衡的数据集,可以采用重采样、生成合成样本等方法来平衡类别分布。
6. 选择与预测目标高度相关的特征,并删除无关或相关性不大的特征。
7. 调整超参数以优化模型的性能,例如通过交叉验证等方法来寻找最佳的超参数组合。

4.3 代码调整

1. 逐渐降低的学习率 
    lr_schedule = tf.keras.optimizers.schedules.InverseTimeDecay(
        0.001,
        decay_steps=500,
        decay_rate=1,
        staircase=False)

'''
lr_schedule = tf.keras.optimizers.schedules.InverseTimeDecay(: 这一行代码是创建了一个名为InverseTimeDecay的学习率调度器实例,这个实例被赋值给了变量lr_schedule。这个调度器在Tensorflow的优化器库中定义。
0.001: 这是初始学习率,即在开始训练时使用的学习率。
decay_steps=500: 这是指在训练过程中,学习率会在每500步进行一次衰减。
decay_rate=1: 这是指学习率的衰减比例。一个衰减率值为1的学习率调度器意味着学习率会在每个decay_steps步长后减半。
staircase=False: 这表示当进行学习率衰减时,不是按照阶梯式(staircase)方式进行,而是连续平滑地衰减。
'''

这段代码是用来创建一个学习率调度器(Learning Rate Scheduler)的,该调度器使用了一种叫做"Inverse Time Decay"的策略。这种策略基本上是说,随着时间的推移,学习率会以一种倒数的方式进行衰减。在实践中,这种学习率调度器通常用于深度学习模型训练中,因为随着训练的进行,模型可能会逐渐适应训练数据,因此需要逐渐降低学习率以避免过拟合。通过这种方式,可以在训练初期使用较高的学习率进行模型训练,然后在训练过程中逐渐降低学习率,从而使得模型能够在保持良好泛化性能的同时,更好地优化模型参数。

2. 降低卷积核过高的权重

将上面的网络定义修改如下

# 定义一个序贯模型
model = tf.keras.Sequential(
    [
        # 归一化层,通常用于加速模型的训练并提高其性能
        normalization_layer,
        # 接下来是三个卷积层,每个卷积层后都接一个ReLU激活函数和L2正则化,用于防止过拟合
        tf.keras.layers.Conv2D(
            16, 3, activation='relu', kernel_regularizer=tf.keras.regularizers.l2(0.001)),
        # 接下来是一个最大池化层,用于降低特征图的尺寸,从而减少计算复杂度
        tf.keras.layers.MaxPool2D(),
        # 第二个卷积层和最大池化层
        tf.keras.layers.Conv2D(
            32, 3, activation='relu', kernel_regularizer=tf.keras.regularizers.l2(0.001)),
        tf.keras.layers.MaxPool2D(),
        # 第三个卷积层和最大池化层
        tf.keras.layers.Conv2D(
            64, 3, activation='relu', kernel_regularizer=tf.keras.regularizers.l2(0.001)),
        tf.keras.layers.MaxPool2D(),
        # 接下来是一个Dropout层,用于防止过拟合,随机丢弃一部分神经元
        tf.keras.layers.Dropout(0.2),
        # Flatten层将卷积层的输出拉平,为全连接层做准备
        tf.keras.layers.Flatten(),
        # 第一个全连接层,128个神经元,激活函数为ReLU
        tf.keras.layers.Dense(128, activation='relu'),
        # 最后一个全连接层,numclasss个神经元,用于分类任务,不使用激活函数
        tf.keras.layers.Dense(numclasss)
    )
)

注意,和上面网络的不同点:

kernel_regularizer=tf.keras.regularizers.l2(0.001):这是正则化项,用于控制模型的复杂性以防止过拟合。L2正则化是最常见的正则化方法之一,它通过对卷积核的权重进行惩罚来减少模型的复杂度。这里的参数0.001是 L2 正则化的系数。

3. 数据增强
data_augmentation = tf.keras.Sequential(
        [
            tf.keras.layers.RandomFlip(
                'horizontal', input_shape=(image_height, image_width, 3)),
            tf.keras.layers.RandomRotation(0.1),
            tf.keras.layers.RandomZoom(0.1)
        ]
    )

'''
tf.keras.Sequential( [...] ):这是创建一个顺序模型(Sequential model)的语句,该模型将按照定义的顺序执行一系列层。
tf.keras.layers.RandomFlip( 'horizontal', input_shape=(image_height, image_width, 3) ):这是一个随机水平翻转层。它将输入图像(预期为彩色图像,具有高度image_height、宽度image_width和3个颜色通道)沿水平方向翻转。这种翻转是随机的,也就是说,翻转操作在每次前向传播时都有可能发生。
tf.keras.layers.RandomRotation(0.1):这是一个随机旋转层。它将输入图像(保持与前面相同的形状)旋转一个随机的角度,角度范围为-0.1到+0.1弧度(约合10度)。这意味着每次前向传播时,图像都可能以不同的角度旋转。
tf.keras.layers.RandomZoom(0.1):这是一个随机缩放层。它将输入图像(保持与前面相同的形状)随机缩放,缩放因子在0.9到1.1之间变化。这意味着每次前向传播时,图像都可能以不同的缩放比例进行缩放。
'''

这段代码是使用 TensorFlow 和 Keras 创建的一个数据增强(Data Augmentation)模块。数据增强是一种技术,通过在训练数据周围添加一些小的变化(或扰动)来扩展数据集,从而增加模型的泛化能力。这种方法可以帮助模型更好地理解输入数据的各种变化,并提高其预测的准确性。

然后将数据增强层插入到网络的最前面

# 定义一个序贯模型
model = tf.keras.Sequential(
    # 列表中的第一个元素是数据增强层,通常用于提高模型的泛化能力
    [
        data_augmentation,
        # 列表中的第二个元素是归一化层,通常用于加速模型的训练并提高其性能
        normalization_layer,
        # 接下来是三个卷积层,每个卷积层后都接一个ReLU激活函数和L2正则化,用于防止过拟合
        tf.keras.layers.Conv2D(
            16, 3, activation='relu', kernel_regularizer=tf.keras.regularizers.l2(0.001)),
...

最后,看看结果吧

可以看到,当训练轮次达到15轮时,训练还没有发生过拟合(通常表现为”Traning Accuracy“继续提高,但是"Validation Accuracy"停滞不前或开始下降,同时Validation的loss开始上升),而且准确率达到了70%以上

  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: 利用卷积神经网络对MINST数据集进行分类实验是一种常见和有效的图像识别方法。MINST数据集是一个手写数字图片集合,包括了60000个训练样本和10000个测试样本。 卷积神经网络(Convolutional Neural Network,CNN)是一种模拟人类视觉系统的深度学习模型,其在图像处理和模式识别任务中表现出色。使用CNN对MINST数据集进行分类实验的步骤如下: 1. 数据准备:首先,将MINST数据集加载到程序中,并进行标准化处理,将图像的像素值归一化到0到1之间。 2. 构建CNN模型:这里可以使用Python的深度学习框架,如TensorFlowKeras或PyTorch来构建CNN模型。定义卷积层、池化层和全连接层,并设置合适的卷积核大小、池化窗口大小和激活函数。 3. 模型训练:将训练集输入到CNN模型中,进行反向传播优化算法,如随机梯度下降(SGD)、Adam或RMSprop来优化模型参数。根据训练集不断调整卷积核权重、偏置和全连接层权重、偏置,直到模型收敛。 4. 模型评估:使用测试集评估已经训练好的模型。将测试集输入到CNN模型中,计算分类准确率、精确度、召回率等指标来评估模型的性能。 5. 结果分析:分析模型在测试集上的性能表现,可以观察混淆矩阵、绘制准确率和损失函数变化曲线等。 通过这样的实验,我们可以了解CNN模型在MINST数据集上的分类效果。MINST数据集是一个较为简单的图像分类任务,对于CNN来说可以很好地处理。这个实验也可以作为学习和理解CNN模型的基础,为后续更复杂的图像分类任务打下基础。 ### 回答2: 卷积神经网络(Convolutional Neural Networks, CNN)是一种深度学习模型,特别适合处理图像数据。下面我将介绍如何使用CNN对MINST手写数字数据集进行分类实验。 MINST数据集是一个包含60000个训练样本和10000个测试样本的手写数字数据集。我们的目标是将这些手写数字图像正确地分类为0至9中的一个。 首先,我们需要导入所需的库和数据集。我们可以使用Python的TensorFlow库来实现卷积神经网络,并使用MINST数据集进行训练和测试。 接下来,我们定义一个CNN模型。一个典型的CNN模型由卷积层、池化层和全连接层组成。我们可以通过多次迭代来选择合适的参数和层数。 然后,我们将数据集分为训练集和测试集。训练集用于训练CNN的权重和参数,而测试集用于评估模型的性能。 接下来,我们进行训练和优化。我们使用训练集来训练CNN模型,并通过优化算法来调整权重和参数,以最小化损失函数。 在训练完成后,我们使用测试集来评估模型的性能。我们将模型应用于测试集中的图像,然后计算模型的准确率和损失。 最后,我们可以进行预测。我们可以将新的手写数字图像输入到CNN模型中,然后通过模型的输出确定该图像属于哪个数字类别。 通过上述步骤,我们可以使用CNN对MINST手写数字数据集进行分类实验。这种方法在图像分类问题中已经证明了其有效性,并且在许多实际应用中得到了广泛应用。 ### 回答3: 卷积神经网络(Convolutional Neural Network, CNN)是一种深度学习模型,特别适用于图像处理任务。MINST数据集是一个常用的手写数字识别数据集,由60000个训练样本和10000个测试样本组成。 利用卷积神经网络对MINST数据集进行分类实验的步骤如下: 1. 数据准备:首先需要下载MINST数据集,并将其分为训练集和测试集。MINST数据集提供了每个样本的数字标签和对应的图像数据。 2. 构建模型:使用深度学习框架如TensorFlow或PyTorch,搭建一个卷积神经网络模型。模型可以包含卷积层、池化层、全连接层等组件。可以选择不同的网络架构和超参数进行实验。 3. 数据预处理:在输入数据之前,进行一些预处理步骤,如将图像数据进行归一化、缩放和平衡处理等。这样可以提高模型的收敛速度和准确性。 4. 训练模型:将准备好的训练集输入模型,使用训练数据进行模型的训练。通过反向传播算法,不断调整模型的权重和偏差,使模型能够更好地拟合训练数据。 5. 测试模型:使用测试集对训练好的模型进行评估。将测试集的图像输入模型,得到输出的预测结果。计算预测结果与真实标签之间的差距,评估模型的准确性。 6. 调优和改进:根据测试结果分析模型的性能,可以进行一些调优和改进,如调整网络架构、增加层数、调整超参数等,以进一步提高模型的准确率。 通过以上步骤,可以利用卷积神经网络对MINST数据集进行分类实验。可以通过测量准确度、损失函数等指标来评估模型的性能。不断优化模型,提高准确率,是卷积神经网络在MINST数据集进行分类实验的关键。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值