Skip to main content
 首页 » 编程设计

python之Keras 损失一直很低,但准确性开始很高然后下降

2025年05月04日15rubylouvre

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

  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 个时期,第二次尝试让它工作。这是 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' 

请您参考如下方法:

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

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

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