首先,我的假设可能有误:
- 损失是每个训练样本与正确答案之间的差距(然后除以样本数量 – 某种平均损失)。
- 准确率是正确训练样本的数量(如果最高输出被视为正确答案,那么即使是0.7也会导致0.3的损失,但它仍然输出正确答案)。这以百分比给出。
在我看来,这意味着准确率通常会比损失更接近100%。但我看到的情况并非如此:
10000/10000 [==============================] - 1067s - loss: 0.0408 - acc: 0.9577 - val_loss: 0.0029 - val_acc: 0.9995Epoch 2/510000/10000 [==============================] - 991s - loss: 0.0021 - acc: 0.9997 - val_loss: 1.9070e-07 - val_acc: 1.0000Epoch 3/510000/10000 [==============================] - 990s - loss: 0.0011 - acc: 0.4531 - val_loss: 1.1921e-07 - val_acc: 0.2440
这是3个epoch的结果,这是第二次尝试使其工作。这是在train_dategen
设置为shuffle=True
的情况下。我也有shuffle=False
的结果(我最初认为这可能是问题所在),如下所示:
10000/10000 [==============================] - 1168s - loss: 0.0079 - acc: 0.9975 - val_loss: 0.0031 - val_acc: 0.9995Epoch 2/510000/10000 [==============================] - 1053s - loss: 0.0032 - acc: 0.9614 - val_loss: 1.1921e-07 - val_acc: 0.2439Epoch 3/510000/10000 [==============================] - 1029s - loss: 1.1921e-07 - acc: 0.2443 - val_loss: 1.1921e-07 - val_acc: 0.2438Epoch 4/510000/10000 [==============================] - 1017s - loss: 1.1921e-07 - acc: 0.2439 - val_loss: 1.1921e-07 - val_acc: 0.2438Epoch 5/510000/10000 [==============================] - 1041s - loss: 1.1921e-07 - acc: 0.2445 - val_loss: 1.1921e-07 - val_acc: 0.2435
我使用categorical_crossentropy
作为损失函数,因为我有3个类别。我的数据量超过所需(约178,000张图片,全部分类为3个类别中的一个)。
我是否误解了什么,或者是哪里出了问题?
这是我的完整代码:
# 导入Keras库和包from keras.models import Sequentialfrom keras.layers import Conv2Dfrom keras.layers import MaxPooling2Dfrom keras.layers import Flattenfrom keras.layers import Dense# 初始化CNNclassifier = Sequential()# 步骤1 - 卷积classifier.add(Conv2D(32, (3, 3), input_shape = (200, 200, 3), activation = 'relu'))# 步骤2 - 池化classifier.add(MaxPooling2D(pool_size = (2, 2)))# 添加第二个卷积层classifier.add(Conv2D(32, (3, 3), activation = 'relu'))classifier.add(MaxPooling2D(pool_size = (2, 2)))# 步骤3 - 平坦化classifier.add(Flatten())# 步骤4 - 全连接classifier.add(Dense(units = 128, activation = 'relu'))classifier.add(Dense(units = 3, activation = 'sigmoid'))# 编译CNNclassifier.compile(optimizer = 'adam', loss = 'categorical_crossentropy', metrics = ['accuracy'])# 第二部分 - 将CNN拟合到图像from keras.preprocessing.image import ImageDataGeneratortrain_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")# 第三部分 - 进行新预测import numpy as npfrom keras.preprocessing import imagetest_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_indicesif result[0][0] == 1: prediction = 'head'else: prediction = 'not'
回答:
由于您是在将图像分类到3个类别之一(即所谓的单标签多类分类:有多个类别,但每张图像只有一个标签),您应该在最后一层使用softmax
作为激活函数,而不是使用sigmoid
:
classifier.add(Dense(units = 3, activation = 'softmax')) # 不要在这里使用sigmoid
如果您需要更多解释,请告诉我,我会更新我的回答。