【问题标题】:Model accuracy and loss not improving in CNNCNN 中的模型准确性和损失没有改善
【发布时间】:2020-05-11 20:07:31
【问题描述】:

我正在使用下面的 LeNet 架构来训练我的图像分类模型,我注意到每次迭代的训练、验证精度都没有提高。该领域的任何一位专业人士都可以解释可能出了什么问题吗?

训练样本 - 属于 2 个类别的 110 张图像。 验证 - 属于 2 个类别的 50 张图像。

#LeNet

import keras 
from keras.models import Sequential
from keras.layers import Conv2D
from keras.layers import MaxPooling2D
from keras.layers import Flatten
from keras.layers import Dense

#import dropout class if needed
from keras.layers import Dropout

from keras import regularizers

model = Sequential()
#Layer 1
#Conv Layer 1
model.add(Conv2D(filters = 6, 
                 kernel_size = 5, 
                 strides = 1, 
                 activation = 'relu', 
                 input_shape = (32,32,3)))
#Pooling layer 1
model.add(MaxPooling2D(pool_size = 2, strides = 2))
#Layer 2
#Conv Layer 2
model.add(Conv2D(filters = 16, 
                 kernel_size = 5,
                 strides = 1,
                 activation = 'relu',
                 input_shape = (14,14,6)))
#Pooling Layer 2
model.add(MaxPooling2D(pool_size = 2, strides = 2))
#Flatten
model.add(Flatten())
#Layer 3
#Fully connected layer 1
model.add(Dense(units=128,activation='relu',kernel_initializer='uniform'
                     ,kernel_regularizer=regularizers.l2(0.01)))
model.add(Dropout(rate=0.2))
#Layer 4
#Fully connected layer 2
model.add(Dense(units=64,activation='relu',kernel_initializer='uniform'
                     ,kernel_regularizer=regularizers.l2(0.01)))
model.add(Dropout(rate=0.2))

#layer 5
#Fully connected layer 3
model.add(Dense(units=64,activation='relu',kernel_initializer='uniform'
                     ,kernel_regularizer=regularizers.l2(0.01)))
model.add(Dropout(rate=0.2))

#layer 6
#Fully connected layer 4
model.add(Dense(units=64,activation='relu',kernel_initializer='uniform'
                     ,kernel_regularizer=regularizers.l2(0.01)))
model.add(Dropout(rate=0.2))

#Layer 7
#Output Layer
model.add(Dense(units = 2, activation = 'softmax'))
model.compile(optimizer = 'adam', loss = 'categorical_crossentropy', metrics = ['accuracy'])

from keras.preprocessing.image import ImageDataGenerator

#Image Augmentation
train_datagen = ImageDataGenerator(
        rescale=1./255, #rescaling pixel value bw 0 and 1
        shear_range=0.2,
        zoom_range=0.2,
        horizontal_flip=True)

#Just Feature scaling
test_datagen = ImageDataGenerator(rescale=1./255)

training_set = train_datagen.flow_from_directory(
       '/Dataset/Skin_cancer/training',
        target_size=(32, 32),
        batch_size=32,
        class_mode='categorical')

test_set = test_datagen.flow_from_directory(
        '/Dataset/Skin_cancer/testing',
        target_size=(32, 32),
        batch_size=32,
        class_mode='categorical')

model.fit_generator(
        training_set,
        steps_per_epoch=50,   #number of input (image)
        epochs=25,
        validation_data=test_set,
        validation_steps=10)          # number of training sample

Epoch 1/25
50/50 [==============================] - 52s 1s/step - loss: 0.8568 - accuracy: 0.4963 - val_loss: 0.7004 - val_accuracy: 0.5000
Epoch 2/25
50/50 [==============================] - 50s 1s/step - loss: 0.6940 - accuracy: 0.5000 - val_loss: 0.6932 - val_accuracy: 0.5000
Epoch 3/25
50/50 [==============================] - 48s 967ms/step - loss: 0.6932 - accuracy: 0.5065 - val_loss: 0.6932 - val_accuracy: 0.5000
Epoch 4/25
50/50 [==============================] - 50s 1s/step - loss: 0.6932 - accuracy: 0.4824 - val_loss: 0.6933 - val_accuracy: 0.5000
Epoch 5/25
50/50 [==============================] - 49s 974ms/step - loss: 0.6932 - accuracy: 0.4949 - val_loss: 0.6932 - val_accuracy: 0.5000
Epoch 6/25
50/50 [==============================] - 51s 1s/step - loss: 0.6932 - accuracy: 0.4854 - val_loss: 0.6931 - val_accuracy: 0.5000
Epoch 7/25
50/50 [==============================] - 49s 976ms/step - loss: 0.6931 - accuracy: 0.5015 - val_loss: 0.6918 - val_accuracy: 0.5000
Epoch 8/25
50/50 [==============================] - 51s 1s/step - loss: 0.6932 - accuracy: 0.4986 - val_loss: 0.6932 - val_accuracy: 0.5000
Epoch 9/25
50/50 [==============================] - 49s 973ms/step - loss: 0.6932 - accuracy: 0.5000 - val_loss: 0.6929 - val_accuracy: 0.5000
Epoch 10/25
50/50 [==============================] - 50s 1s/step - loss: 0.6931 - accuracy: 0.5044 - val_loss: 0.6932 - val_accuracy: 0.5000
Epoch 11/25
50/50 [==============================] - 49s 976ms/step - loss: 0.6931 - accuracy: 0.5022 - val_loss: 0.6932 - val_accuracy: 0.5000
Epoch 12/25

【问题讨论】:

    标签: python tensorflow keras deep-learning conv-neural-network


    【解决方案1】:

    从您的图层中删除 all kernel_initializer='uniform' 参数;不要在这里指定任何东西,default 初始化器 glorot_uniform 是强烈推荐的(而 uniform 是特别糟糕的)。

    作为一般规则,请记住,这些相当高级的设置的默认值是为了您的方便而存在的,它们是隐式推荐的,您最好不要乱用它们,除非您有特定的理由这样做并且您知道正是你在做什么。

    尤其是kernel_initializer 论点,我开始相信它给人们带来了很多不必要的痛苦(最近的例子见here)。

    此外,默认情况下不应使用 dropout,尤其是在模型似乎难以学习任何东西的情况下;开始时没有任何 dropout(注释掉相应的层),只有在看到过度拟合的迹象时才将其添加回来。

    【讨论】:

    • 谢谢,现在损失变化率有所提高,但训练准确率仍然没有太大提高,测试准确率在所有迭代中保持在 0.5。可能是什么问题?
    • @Arun_Ramji_Shanmugam 查看关于辍学的更新(最后一段)。
    • 是的,训练集准确率有所提高(没有太大偏差),但验证准确率从头到尾都保持在 0.5。是因为我的验证集只有 50 个样本吗???
    【解决方案2】:

    最重要的是您使用的是loss = 'categorical_crossentropy',将其更改为loss = 'binary_crossentropy',因为您只有2 个类。并将flow_from_directory 中的class_mode='categorical' 更改为class_mode='binary'

    正如@desertnaut 正确提到的,categorical_crossentropy 与最后一层的softmax 激活密切相关,如果您将损失更改为binary_crossentropy,最后的激活也应更改为sigmoid

    其他改进:

    1. 您的数据非常有限(160 张图像),并且您使用了将近 50% 的数据作为验证数据。
    2. 在构建图像分类模型时,您只有两个 Conv2D 层和 4 个密集层。密集层正在增加大量需要学习的权重。添加更多的 conv2d 层并减少 Dense 层。
    3. 设置 batch_size = 1 并删除 steps_per_epoch。由于您的输入非常少,因此每个 epoch 的步数都与输入记录相同。
    4. 使用默认的 glorot_uniform 内核初始化程序。
    5. 要进一步调整您的模型,请使用多个 Conv2D 层构建模型,然后是 GlobalAveragePooling2D 层和 FC 层以及最终的 softmax 层。
    6. 使用 ImageDataGenerator 的 horizontal_flipvertical_flipshear_range、zoom_range 等数据增强技术来增加训练和验证图像的数量。

    按照@desertnaut 的建议将 cmets 移动到答案部分 -

    问题 - 谢谢!是的,更少的数据是我认为的问题。一个额外的 问题 - 为什么添加比 conv 层更密集的层 对模型产生负面影响,当我们 决定我们要使用多少个卷积层和密集层? – Arun_Ramji_Shanmugam 2 天前

    Answer - 为了回答您问题的第一部分,Conv2D 层维护 图像的空间信息和要学习的权重取决于 层中提到的内核大小和步幅,其中为 Dense 层需要 Conv2D 的输出被展平并进一步使用 从而丢失空间信息。致密层也增加了更多 权重的数量,例如 2 个 512 的密集层添加 (512*512)=262144 模型的参数或权重(必须由 模型)。这意味着你必须训练更多的时期和 具有良好的炒作参数设置来学习这些权重。 – TensorFlow 勇士 2 天前

    Answer - 要回答问题的第二部分,请使用系统实验 发现最适合您的特定数据集的方法。这也取决于 关于你拥有的处理能力。请记住,更深层次的网络总是 更好,代价是更多的数据和学习的复杂性增加。 一种常规的方法是寻找类似的问题并深入 已经证明有效的学习架构。还有我们 可以灵活地利用预训练模型,如 resnet、vgg 等等,通过冻结部分层和训练来使用这些模型 在剩余的层上。 – TensorFlow 勇士 2 天前

    问题 - 感谢您的详细回答!如果你不再打扰一个问题 - 所以当我们使用已经训练好的模型(可能是一些层)时,是否需要在与我们要训练的输入数据相同的输入数据上进行训练 工作 ? – Arun_Ramji_Shanmugam 昨天

    答案 - 用于图像分类的迁移学习背后的直觉是 如果一个模型是在一个足够大且足够通用的数据集上训练的,这 模型将有效地作为视觉世界的通用模型。 您可以在此处找到带有解释的迁移学习示例 - tensorflow.org/tutorials/images/transfer_learning 。 –张量流 昨天的勇士

    【讨论】:

    • 谢谢!是的,更少的数据是我认为的问题。另一个问题 - 为什么添加比卷积层更多的密集层会对模型产生负面影响,当我们决定要使用多少个卷积层和密集层时,是否有任何规则可遵循?
    • 为了回答你问题的第一部分,Conv2D 层维护图像的空间信息,并且要学习的权重取决于层中提到的内核大小和步幅,其中 Dense 层需要Conv2D 的输出被展平并进一步使用,因此丢失了空间信息。密集层也增加了更多的权重,例如 2 个 512 的密集层向模型添加 (512*512)=262144 参数或权重(必须由模型学习)。这意味着你必须训练更多数量的epochs 和良好的炒作参数设置来学习这些权重。
    • 要回答您问题的第二部分,请使用系统实验来发现最适合您的特定数据集的方法。这也取决于您拥有的处理能力。请记住,更深的网络总是更好,但代价是更多的数据和学习的复杂性增加。一种传统的方法是寻找已经证明有效的类似问题和深度学习架构。我们还可以灵活地利用预训练模型,如 resnet、vgg 等,通过冻结部分层并在剩余层上进行训练来使用这些模型。
    • 感谢您的详细解答!!如果您不打扰另一个问题 - 那么当我们使用已经训练好的模型(可能是一些层)时,是否需要在与我们将要工作的模型相同的输入数据上进行训练?
    • 图像分类迁移学习背后的直觉是,如果模型在足够大且足够通用的数据集上进行训练,该模型将有效地充当视觉世界的通用模型。您可以在此处找到带有解释的迁移学习示例 - tensorflow.org/tutorials/images/transfer_learning
    猜你喜欢
    • 2016-07-18
    • 1970-01-01
    • 2018-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多