Keras损失一直很低但准确度开始高然后下降

时间:2018-06-18 17:43:06

标签: python machine-learning keras loss cross-entropy

首先,我的假设可能是错误的:

  1. 损失是每个训练样例的正确答案距离(然后除以示例数量 - 平均损失的种类)。
  2. 准确度是指多少训练样例是正确的(如果将最高输出作为正确答案,那么如果它的0.7会导致0.3的损失并不重要,它仍然输出正确的回答)。这是以百分比形式给出的。
  3. 在我看来,这意味着准确度通常会接近100%而不是损失为0.这不是我所看到的:

    10000/10000 [==============================] - 1067s - loss: 0.0408 - acc: 0.9577 - val_loss: 0.0029 - val_acc: 0.9995
    Epoch 2/5
    10000/10000 [==============================] - 991s - loss: 0.0021 - acc: 0.9997 - val_loss: 1.9070e-07 - val_acc: 1.0000
    Epoch 3/5
    10000/10000 [==============================] - 990s - loss: 0.0011 - acc: 0.4531 - val_loss: 1.1921e-07 - val_acc: 0.2440
    

    这是在3个时代,第二次尝试使这个工作。这是train_dategen shuffle=True。我有shuffle=False的结果(我最初认为这可能是问题),在这里:

    10000/10000 [==============================] - 1168s - loss: 0.0079 - acc: 0.9975 - val_loss: 0.0031 - val_acc: 0.9995
    Epoch 2/5
    10000/10000 [==============================] - 1053s - loss: 0.0032 - acc: 0.9614 - val_loss: 1.1921e-07 - val_acc: 0.2439
    Epoch 3/5
    10000/10000 [==============================] - 1029s - loss: 1.1921e-07 - acc: 0.2443 - val_loss: 1.1921e-07 - val_acc: 0.2438
    Epoch 4/5
    10000/10000 [==============================] - 1017s - loss: 1.1921e-07 - acc: 0.2439 - val_loss: 1.1921e-07 - val_acc: 0.2438
    Epoch 5/5
    10000/10000 [==============================] - 1041s - loss: 1.1921e-07 - acc: 0.2445 - val_loss: 1.1921e-07 - val_acc: 0.2435
    

    我使用categorical_crossentropy表示丢失,因为我有3个班级。我有超过需要的数据(约178,000张图片,全部归类为3类中的1张)。

    我误解了什么,或者出了什么问题?

    这是我的完整代码:

    # Importing the Keras libraries and packages
    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
    
    # Initialising the CNN
    classifier = Sequential()
    # Step 1 - Convolution
    classifier.add(Conv2D(32, (3, 3), input_shape = (200, 200, 3), activation = 'relu'))
    # Step 2 - Pooling
    classifier.add(MaxPooling2D(pool_size = (2, 2)))
    # Adding a second convolutional layer
    classifier.add(Conv2D(32, (3, 3), activation = 'relu'))
    classifier.add(MaxPooling2D(pool_size = (2, 2)))
    # Step 3 - Flattening
    classifier.add(Flatten())
    # Step 4 - Full connection
    classifier.add(Dense(units = 128, activation = 'relu'))
    classifier.add(Dense(units = 3, activation = 'sigmoid'))
    # Compiling the CNN
    classifier.compile(optimizer = 'adam', loss = 'categorical_crossentropy', metrics = ['accuracy'])
    # Part 2 - Fitting the CNN to the images
    from keras.preprocessing.image import ImageDataGenerator
    train_datagen = ImageDataGenerator(rescale = 1./255)
    test_datagen = ImageDataGenerator(rescale = 1./255)
    training_set = train_datagen.flow_from_directory('dataset/training_set',
                    target_size = (200, 200),
                    batch_size = 64,
                    class_mode = 'categorical',
                    shuffle=True)
    
    test_set = test_datagen.flow_from_directory('dataset/test_set',
                    target_size = (200, 200),
                    batch_size = 62,
                    class_mode = 'categorical',
                    shuffle=True)
    
    classifier.fit_generator(training_set,
                    steps_per_epoch = 10000,
                    epochs = 5,
                    validation_data = test_set,
                    validation_steps=1000)
    
    classifier.save("CSGOHeads.h5")
    # Part 3 - Making new predictions
    import numpy as np
    from keras.preprocessing import image
    test_image = image.load_img('dataset/single_prediction/1.bmp', target_size = (200, 200))
    test_image = image.img_to_array(test_image)
    test_image = np.expand_dims(test_image, axis = 0)
    result = classifier.predict(test_image)
    training_set.class_indices
    if result[0][0] == 1:
        prediction = 'head'
    else:
        prediction = 'not'
    

2 个答案:

答案 0 :(得分:3)

由于您将图像分类为3个类之一(即称为单标签多类分类:有多个类,但每个图像只有一个标签),您应该使用softmax作为激​​活函数最后一层而不是使用sigmoid

classifier.add(Dense(units = 3, activation = 'softmax')) # don't use sigmoid here

如果您想让我解释一下,请告诉我,我会更新我的答案。

答案 1 :(得分:3)

为了补充@今天的答案,如果最后一层的激活是sigmoid,则损失应为binary_crossentropy。它是多标签分类问题的一个秘诀。否则,对于单标签分类,请使用softmaxcategorical_crossentropy。不要将sigmoidcategorical_crossentropy混淆。