【问题标题】:Training and Loss not changing in Keras CNN modelKeras CNN 模型中的训练和损失没有改变
【发布时间】:2017-04-28 07:25:25
【问题描述】:

我正在运行一个用于左右鞋印分类的 CNN。我有 190,000 张训练图像,其中 10% 用于验证。我的模型设置如下所示。我得到所有图像的路径,读入它们并调整它们的大小。我对图像进行标准化,然后将其拟合到模型中。我的问题是我的训练准确率一直保持在 62.5%,损失在 0.6615-0.6619 左右。我做错了什么吗?我怎样才能阻止这种情况发生?

只需要注意一些有趣的点:

  1. 我首先在 10 张图像上进行了测试,我遇到了同样的问题,但将优化器更改为 adam 并将批量大小更改为 4 有效。

  2. 然后我对越来越多的图像进行了测试,但每次我都需要更改批量大小以提高准确性和损失。对于 10,000 张图像,我必须使用 500 的批量大小和优化器 rmsprop。然而,准确率和损失只是在 epoch 10 之后才真正开始发生变化。

  3. 我现在正在训练 190,000 张图像,我无法增加批量大小,因为我的 GPU 已达到最大值。

    imageWidth = 50
    imageHeight = 150
    
    def get_filepaths(directory):
        file_paths = []
        for filename in files:
            filepath = os.path.join(root, filename)
            file_paths.append(filepath) # Add it to the list.
        return file_paths
    
    def cleanUpPaths(fullFilePaths):
        cleanPaths = []
        for f in fullFilePaths:
            if f.endswith(".png"):
                cleanPaths.append(f)
        return cleanPaths
    
    def getTrainData(paths):
        trainData = []
        for i in xrange(1,190000,2):
            im = image.imread(paths[i])
            im = image.imresize(im, (150,50))
            im = (im-255)/float(255)
            trainData.append(im)
        trainData = np.asarray(trainData)
        right = np.zeros(47500)
        left = np.ones(47500)
        trainLabels = np.concatenate((left, right))
        trainLabels = np_utils.to_categorical(trainLabels)
        return (trainData, trainLabels)

    #create the convnet
    model = Sequential()
    
    model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(imageWidth,imageHeight,1),strides=1))#32
    model.add(Conv2D(32, (3, 3), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.25))
    
    model.add(Conv2D(64, (3, 3), activation='relu',strides=1))
    model.add(Conv2D(64, (3, 3), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.25))
    
    model.add(Conv2D(64, (3, 3), activation='relu'))
    model.add(MaxPooling2D(pool_size=(1, 3)))
    model.add(Dropout(0.25))
    
    model.add(Conv2D(64, (1, 2), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 1)))
    model.add(Dropout(0.25))
    
    model.add(Flatten())
    model.add(Dense(256, activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(2, activation='softmax'))
    
    sgd = SGD(lr=0.01)
    model.compile(loss='categorical_crossentropy', optimizer='rmsprop',metrics=['accuracy'])
    
    #prepare the training data*/
    
    trainPaths = get_filepaths("better1/train")
    trainPaths = cleanUpPaths(trainPaths)
    (trainData, trainLabels) = getTrainData(trainPaths)
    trainData = np.reshape(trainData,(95000,imageWidth,imageHeight,1)).astype('float32')
    trainData = (trainData-255)/float(255)
    
    #train the convnet***
    model.fit(trainData, trainLabels, batch_size=500, epochs=50, validation_split=0.2)
    
    #/save the model and weights*/
    model.save('myConvnet_model5.h5');
    model.save_weights('myConvnet_weights5.h5');

【问题讨论】:

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


    【解决方案1】:

    我现在已经多次遇到此问题,因此想对它和可能的解决方案等进行一些回顾,以帮助将来的人们。

    问题:模型预测它看到的所有数据的 2 个(或更多)可能的类别之一*

    确认问题正在发生方法 1: 训练时模型的准确率保持在 0.5 左右(或 1/n,其中 n 是类数)。 方法 2: 获取预测中每个类的计数,并确认它是预测所有一个类。

    修复/检查(按某种顺序):

    • 双重检查模型架构:使用model.summary(),检查模型。
    • 检查数据标签:确保您的火车数据的标签在预处理等过程中没有混淆(确实发生了!)
    • 检查训练数据馈送是随机的:确保您没有一次将训练数据馈送到模型一个类。例如,如果使用ImageDataGenerator().flow_from_directory(PATH),请检查参数shuffle=Truebatch_size 是否大于1。
    • 检查预训练层不可训练:**如果使用预训练模型,请确保使用预训练权重的任何层最初不可训练。对于第一个时期,只有新添加的(随机初始化的)层应该是可训练的; for layer in pretrained_model.layers: layer.trainable = False 应该在您的代码中。
    • 降低学习率:继续将学习率降低 10 倍并重试。请注意,每次尝试新的学习率时,您都必须完全重新初始化您尝试训练的层。 (例如,我遇到了这个问题,只有在我访问 lr=1e-6 后才解决,所以继续!)

    如果你们中的任何人知道更多可能使模型训练正确的修复/检查,那么请做出贡献,我会尝试更新列表。

    **请注意,一旦新层的初始训练“足够”,通常会使更多预训练模型可训练

    *问题的其他名称,以帮助搜索到这里... keras tensorflow theano CNN 卷积神经网络 错误训练 卡住了 不是静态 坏虫 卡住了 训练优化 优化只有 0.5 准确度不会改变 只预测一个单一的类不会训练模型卡在类模型上 在 epochs 之间重置自身 keras CNN 相同的输出

    【讨论】:

    • 您好 DBCerigo。欢迎来到 SO。请不要在不同的帖子上一遍又一遍地发布相同的答案。他们很可能会被删除。尝试根据具体问题调整您的建议。谢谢。
    【解决方案2】:

    您可以尝试在MaxPooling2D() 之后添加BatchNornmalization() 层。它对我有用。

    【讨论】:

      【解决方案3】:

      我还有两件事要添加到 DBCerigo 的伟大列表中。

      • 检查激活函数:有些层默认有linear激活函数,如果你不在你的模型中插入一些非线性,它将无法泛化,所以网络会尝试学习如何分离linearly 一个非线性的特征空间。确保你有你的非线性设置是一个很好的检查点。
      • 检查模型复杂度:如果您有一个相对简单的模型,并且它只学习到第 1 或第 2 个 epoch 然后停止,可能是它试图学习一些过于复杂的东西。尝试使模型更深。这通常发生在使用只有 1 或 2 层未冻结的冻结模型时。

      虽然第二个问题可能很明显,但我遇到过一次他的问题,在弄清楚之前我浪费了大量时间检查所有内容(数据、批次、LR...)。

      希望对你有帮助

      【讨论】:

      • 谢谢,我做了与您在第二点中描述的几乎相同的事情。你有没有找到任何备忘单或其他东西来快速查找什么在什么时间最有效。
      • 很遗憾,没有,但我们可以做一些事情,从这篇文章的答案中收集所有知识
      【解决方案4】:

      我会尝试几件事。较低的学习率应该有助于处理更多数据。通常,调整优化器应该会有所帮助。此外,您的网络似乎非常小,您可能希望通过添加层或增加层中的过滤器数量来增加模型的容量。

      here 提供了有关如何在实践中应用深度学习的更好描述。

      【讨论】:

      • 所以我通过在每个卷积层之后添加一个批量归一化层来学习模型。我现在得到低训练损失和验证损失,以及高训练和验证准确度。然而,当我通过模型运行测试数据时,我得到了 50% 的准确率。这是一个二元分类任务,所以这并不比机会好。除了增加模型的容量,我还能做些什么吗?
      【解决方案5】:

      在我的情况下,激活功能很重要。我从'sgd'变成'a'

      【讨论】:

        猜你喜欢
        • 2016-07-18
        • 2019-09-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-18
        • 2019-04-02
        • 1970-01-01
        • 2019-09-27
        相关资源
        最近更新 更多