【问题标题】:Keras loss consistently low but accuracy starts high then dropsKeras 损失一直很低,但准确度开始很高然后下降
【发布时间】:2018-11-27 14:49:54
【问题描述】:

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

  1. 损失是每个训练示例与正确答案的距离(然后除以示例数量 - 一种平均损失)。
  2. 准确率是有多少个训练样本是正确的(如果将最高输出作为正确答案,那么它是否为 0.7 会损失 0.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 个 epochs 上,第二次尝试让它工作。这是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'

【问题讨论】:

  • 能否请您也发布您的代码?显然,在训练过程中(假设设置正确),验证和训练损失值都会降低,准确度会增加,直到达到一个平台(如果你继续训练,可能过了一段时间验证损失值开始增加,验证准确度下降,这被称为-配件)。但是在您的情况下,一开始的准确性很高,这很奇怪,并且可能表明您的代码中存在错误或错误。
  • @today 我已经发布了我的整个代码,如果有什么不清楚的地方请告诉我(我对 python 还是很陌生,所以它可能看起来一团糟)。谢谢

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


【解决方案1】:

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

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

如果你想让我解释更多,请告诉我,我会更新我的答案。

【讨论】:

  • 谢谢,有道理。一旦我检查了这是问题所在,我将运行代码并标记为已回答!
【解决方案2】:

为了补充@today 的答案,如果最后一层的激活是sigmoid,那么损失应该是binary_crossentropy。这是多标签分类问题的秘诀。否则,对于单标签分类,使用softmax 加上categorical_crossentropy。不要混淆sigmoidcategorical_crossentropy

【讨论】:

    猜你喜欢
    • 2020-02-09
    • 1970-01-01
    • 1970-01-01
    • 2020-07-05
    • 2016-12-08
    • 2020-10-16
    • 1970-01-01
    • 2019-03-25
    • 1970-01-01
    相关资源
    最近更新 更多