Keras 图像分类 – 验证数据集上的预测准确率与val_acc不匹配

我正在尝试将一组图像分类到两个类别中

我使用Keras构建了一个CNN,我的分类器似乎工作得很好:

  • 我有1,939张用于训练的图像(50%是,50%是
  • 我有648张用于验证的图像(50%是,50%是
  • 所有图像都是115×45的灰度图像
  • acc增加到99.53%
  • val_acc增加到98.38%
  • lossval_loss都趋近于0

Keras的详细输出看起来对我来说是正常的:

60/60 [==============================] - 6s 98ms/step - loss: 0.6295 - acc: 0.6393 - val_loss: 0.4877 - val_acc: 0.7641Epoch 2/3260/60 [==============================] - 5s 78ms/step - loss: 0.4825 - acc: 0.7734 - val_loss: 0.3403 - val_acc: 0.8799Epoch 3/3260/60 [==============================] - 5s 77ms/step - loss: 0.3258 - acc: 0.8663 - val_loss: 0.2314 - val_acc: 0.9042Epoch 4/3260/60 [==============================] - 5s 83ms/step - loss: 0.2498 - acc: 0.8942 - val_loss: 0.2329 - val_acc: 0.9042Epoch 5/3260/60 [==============================] - 5s 76ms/step - loss: 0.2408 - acc: 0.9002 - val_loss: 0.1426 - val_acc: 0.9432Epoch 6/3260/60 [==============================] - 5s 80ms/step - loss: 0.1968 - acc: 0.9260 - val_loss: 0.1484 - val_acc: 0.9367Epoch 7/3260/60 [==============================] - 5s 77ms/step - loss: 0.1621 - acc: 0.9319 - val_loss: 0.1141 - val_acc: 0.9578Epoch 8/3260/60 [==============================] - 5s 81ms/step - loss: 0.1600 - acc: 0.9361 - val_loss: 0.1229 - val_acc: 0.9513Epoch 9/3260/60 [==============================] - 4s 70ms/step - loss: 0.1358 - acc: 0.9462 - val_loss: 0.0884 - val_acc: 0.9692Epoch 10/3260/60 [==============================] - 4s 74ms/step - loss: 0.1193 - acc: 0.9542 - val_loss: 0.1232 - val_acc: 0.9529Epoch 11/3260/60 [==============================] - 5s 79ms/step - loss: 0.1075 - acc: 0.9595 - val_loss: 0.0865 - val_acc: 0.9724Epoch 12/3260/60 [==============================] - 4s 73ms/step - loss: 0.1209 - acc: 0.9531 - val_loss: 0.1067 - val_acc: 0.9497Epoch 13/3260/60 [==============================] - 4s 73ms/step - loss: 0.1135 - acc: 0.9609 - val_loss: 0.0860 - val_acc: 0.9838Epoch 14/3260/60 [==============================] - 4s 70ms/step - loss: 0.0869 - acc: 0.9682 - val_loss: 0.0907 - val_acc: 0.9675Epoch 15/3260/60 [==============================] - 4s 71ms/step - loss: 0.0960 - acc: 0.9637 - val_loss: 0.0996 - val_acc: 0.9643Epoch 16/3260/60 [==============================] - 4s 73ms/step - loss: 0.0951 - acc: 0.9625 - val_loss: 0.1223 - val_acc: 0.9481Epoch 17/3260/60 [==============================] - 4s 70ms/step - loss: 0.0685 - acc: 0.9729 - val_loss: 0.1220 - val_acc: 0.9513Epoch 18/3260/60 [==============================] - 4s 73ms/step - loss: 0.0791 - acc: 0.9715 - val_loss: 0.0959 - val_acc: 0.9692Epoch 19/3260/60 [==============================] - 4s 71ms/step - loss: 0.0595 - acc: 0.9802 - val_loss: 0.0648 - val_acc: 0.9773Epoch 20/3260/60 [==============================] - 4s 71ms/step - loss: 0.0486 - acc: 0.9844 - val_loss: 0.0691 - val_acc: 0.9838Epoch 21/3260/60 [==============================] - 4s 70ms/step - loss: 0.0499 - acc: 0.9812 - val_loss: 0.1166 - val_acc: 0.9627Epoch 22/3260/60 [==============================] - 4s 71ms/step - loss: 0.0481 - acc: 0.9844 - val_loss: 0.0875 - val_acc: 0.9734Epoch 23/3260/60 [==============================] - 4s 70ms/step - loss: 0.0533 - acc: 0.9814 - val_loss: 0.1094 - val_acc: 0.9724Epoch 24/3260/60 [==============================] - 4s 70ms/step - loss: 0.0487 - acc: 0.9812 - val_loss: 0.0722 - val_acc: 0.9740Epoch 25/3260/60 [==============================] - 4s 72ms/step - loss: 0.0441 - acc: 0.9828 - val_loss: 0.0992 - val_acc: 0.9773Epoch 26/3260/60 [==============================] - 4s 71ms/step - loss: 0.0667 - acc: 0.9726 - val_loss: 0.0964 - val_acc: 0.9643Epoch 27/3260/60 [==============================] - 4s 73ms/step - loss: 0.0436 - acc: 0.9835 - val_loss: 0.0771 - val_acc: 0.9708Epoch 28/3260/60 [==============================] - 4s 71ms/step - loss: 0.0322 - acc: 0.9896 - val_loss: 0.0872 - val_acc: 0.9756Epoch 29/3260/60 [==============================] - 5s 80ms/step - loss: 0.0294 - acc: 0.9943 - val_loss: 0.1414 - val_acc: 0.9578Epoch 30/3260/60 [==============================] - 5s 76ms/step - loss: 0.0348 - acc: 0.9870 - val_loss: 0.1102 - val_acc: 0.9659Epoch 31/3260/60 [==============================] - 5s 76ms/step - loss: 0.0306 - acc: 0.9922 - val_loss: 0.0794 - val_acc: 0.9659Epoch 32/3260/60 [==============================] - 5s 76ms/step - loss: 0.0152 - acc: 0.9953 - val_loss: 0.1051 - val_acc: 0.9724

所以一切看起来都很棒,但是当我尝试预测2000个样本的类别时,我得到了非常奇怪的结果,准确率低于70%

起初我认为这些样本可能有偏差,所以我尝试预测验证数据集中的图像。

我应该有98.38%的准确率,以及完美的50-50分割,但实际上,再次得到了:

  • 170张图像被预测为正确,而不是324张,准确率为98.8%
  • 478张图像被预测为左,而不是324张,准确率为67.3%
  • 平均准确率:75.69% 而不是98.38%

我猜测我的CNN或预测脚本中可能有些问题。

CNN分类器代码:

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
from PIL import ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True

# 初始化CNN
classifier = Sequential()

# 第一步 - 卷积
classifier.add(Conv2D(32, (3, 3), input_shape = (115, 45, 3), activation = 'relu'))

# 第二步 - 池化
classifier.add(MaxPooling2D(pool_size = (2, 2)))

# 添加第二个卷积层
classifier.add(Conv2D(32, (3, 3), activation = 'relu'))
classifier.add(MaxPooling2D(pool_size = (2, 2)))

# 第三步 - 扁平化
classifier.add(Flatten())

# 第四步 - 全连接
classifier.add(Dense(units = 128, activation = 'relu'))
classifier.add(Dense(units = 1, activation = 'sigmoid'))

# 编译CNN
classifier.compile(optimizer = 'adam', loss = 'binary_crossentropy', metrics = ['accuracy'])

# 第二部分 - 将CNN拟合到图像上
from keras.preprocessing.image import ImageDataGenerator
import numpy

train_datagen = ImageDataGenerator(rescale = 1./255, shear_range = 0.2, zoom_range = 0.2, horizontal_flip = False)
test_datagen = ImageDataGenerator(rescale = 1./255)

training_set = train_datagen.flow_from_directory('./dataset/training_set',
                                                 target_size = (115, 45),
                                                 batch_size = 32,
                                                 class_mode = 'binary')

test_set = test_datagen.flow_from_directory('./dataset/test_set',
                                            target_size = (115, 45),
                                            batch_size = 32,
                                            class_mode = 'binary')

classifier.fit_generator(training_set,
                         steps_per_epoch = 1939/32, # 总样本数 / 批次大小
                         epochs = 32,
                         validation_data = test_set,
                         validation_steps = 648/32)

# 保存分类器
classifier.evaluate_generator(generator=test_set)
classifier.summary()
classifier.save('./classifier.h5')

预测代码:

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
from keras.models import load_model
from keras.preprocessing.image import ImageDataGenerator
import os
import numpy as np
from keras.preprocessing import image
from shutil import copyfile

classifier = load_model('./classifier.h5')

folder = './small/'
files = os.listdir(folder)
pleft = 0
pright = 0

for f in files:
    test_image = image.load_img(folder+f, target_size = (115, 45))
    test_image = image.img_to_array(test_image)
    test_image = np.expand_dims(test_image, axis = 0)
    result = classifier.predict(test_image)

    #print training_set.class_indices
    if result[0][0] == 1:
        pright=pright+1
        prediction = 'right'
        copyfile(folder+'../'+f, '/found_right/'+f)
    else:
        prediction = 'left'
        copyfile(folder+'../'+f, '/found_left/'+f)
        pleft=pleft+1

ptot = pleft + pright
print 'Left = '+str(pleft)+' ('+str(pleft / (ptot / 100))+'%)'
print 'Right = '+str(pright)
print 'Total = '+str(ptot)

输出:

Left = 478 (79%)
Right = 170
Total = 648

您的帮助将不胜感激。


回答:

我通过做两件事解决了这个问题:

  1. 正如@***建议的那样,我必须在预测之前重新调整图像值,我在调用predict()之前添加了test_image /= 255.

  2. 由于我的val_loss仍然有点高,我还添加了一个早期停止回调以及在我的Dense层之前添加了两个Dropout()

现在我的预测结果与训练/验证过程中获得的结果一致了。

Related Posts

如何从数据集中移除EXIF数据?

我在尝试从数据集中的图像中移除EXIF数据(这些数据将…

用于Python中的“智能点”游戏的遗传算法不工作

过去几天我一直在尝试实现所谓的“智能点”游戏。我第一次…

哪个R平方得分更有帮助?

data.drop(‘Movie Title’, ax…

使用线性回归预测GRE分数对录取率的影响

我正在学习线性回归,并尝试在Jupyter笔记本中用P…

使用mlrMBO贝叶斯优化进行SVM超参数调优时出现错误

我试图针对一个分类任务优化SVM,这个方法在许多其他模…

Keras模型的二元交叉熵准确率未发生变化

我在网上看到了很多关于这个问题的提问,但没有找到明确的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注