首页 > 解决方案 > Keras 精度和实际精度正好相反

问题描述

我正在学习神经网络,目前使用 Keras 库在 CFAR-10 数据集上实现了对象分类。这是我对 Keras 定义的神经网络的定义:

# Define the model and train it
model = Sequential()

model.add(Dense(units = 60, input_dim = 1024, activation = 'relu'))
model.add(Dense(units = 50, activation = 'relu'))
model.add(Dense(units = 60, activation = 'relu'))
model.add(Dense(units = 70, activation = 'relu'))
model.add(Dense(units = 30, activation = 'relu'))
model.add(Dense(units = 10, activation = 'sigmoid'))

model.compile(loss='binary_crossentropy',
              optimizer='adam',
              metrics=['accuracy'])

model.fit(X_train, y_train, epochs=50, batch_size=10000)

所以我有 1 个输入层,其输入尺寸为 1024 或 (1024, )(每个 32 * 32 *3 的图像首先转换为灰度,导致尺寸为 32 * 32)、5 个隐藏层和 1 个定义的输出层在上面的代码中。

当我训练我的模型超过 50 个 epoch 时,我得到了0.990% 的准确率。此外,当我使用测试数据集对其进行评估时,我得到了大约的准确度。90%。这是评估模型的代码行:

print (model.evaluate(X_test, y_test))

这将打印以下损失和准确性:

[1.611809492111206, 0.8999999761581421]

但是当我通过对每个测试数据图像进行预测来手动计算准确率时,我得到了大约 11% 的准确率(这几乎与随机做出预测的概率相同)。这是我手动计算的代码:

wrong = 0

for x, y in zip(X_test, y_test):
  if not (np.argmax(model.predict(x.reshape(1, -1))) == np.argmax(y)):
    wrong += 1

print (wrong)

这会打印出 10000 个错误预测中的 9002 个。那么我在这里错过了什么?为什么两种准确度正好相反(100 - 89 = 11%)?任何直观的解释都会有所帮助!谢谢。

编辑:

这是我处理数据集的代码:

# Process the training and testing data and make in Neural Network comfortable

# convert given colored image to grayscale
def rgb2gray(rgb):
  return np.dot(rgb, [0.2989, 0.5870, 0.1140])

X_train, y_train, X_test, y_test = [], [], [], []

def process_batch(batch_path, is_test = False):
  batch = unpickle(batch_path)
  imgs = batch[b'data']
  labels = batch[b'labels']


  for img in imgs:
    img = img.reshape(3,32,32).transpose([1, 2, 0])
    img = rgb2gray(img)
    img = img.reshape(1, -1)
    if not is_test:
      X_train.append(img)
    else:
      X_test.append(img)

  for label in labels:
    if not is_test:
      y_train.append(label)
    else:
      y_test.append(label)

process_batch('cifar-10-batches-py/data_batch_1')
process_batch('cifar-10-batches-py/data_batch_2')
process_batch('cifar-10-batches-py/data_batch_3')
process_batch('cifar-10-batches-py/data_batch_4')
process_batch('cifar-10-batches-py/data_batch_5')

process_batch('cifar-10-batches-py/test_batch', True)

number_of_classes = 10
number_of_batches = 5
number_of_test_batch = 1

X_train = np.array(X_train).reshape(meta_data[b'num_cases_per_batch'] * number_of_batches, -1)
print ('Shape of training data: {0}'.format(X_train.shape))

# create labels to one hot format
y_train = np.array(y_train)

y_train = np.eye(number_of_classes)[y_train]
print ('Shape of training labels: {0}'.format(y_train.shape))


# Process testing data

X_test = np.array(X_test).reshape(meta_data[b'num_cases_per_batch'] * number_of_test_batch, -1)
print ('Shape of testing data: {0}'.format(X_test.shape))

# create labels to one hot format
y_test = np.array(y_test)

y_test = np.eye(number_of_classes)[y_test]
print ('Shape of testing labels: {0}'.format(y_test.shape))

标签: pythonmachine-learningkerasneural-networkartificial-intelligence

解决方案


发生这种情况的原因是由于您使用的损失函数。您正在使用二元交叉熵,您应该使用分类交叉熵作为损失。二进制仅适用于双标签问题,但由于 CIFAR-10,您在此处有 10 个标签。

当您显示准确度指标时,它实际上会误导您,因为它显示的是二进制分类性能。解决方案是通过选择重新训练您的模型categorical_crossentropy

这篇文章有更多细节:Keras binary_crossentropy vs categorical_crossentropy performance?

相关 - 这篇文章回答了一个不同的问题,但答案本质上就是你的问题:Keras: model.evaluate vs model.predict accuracy difference in multi-class NLP task

编辑

您提到您的模型的准确性徘徊在 10% 左右,并且在您的评论中没有提高。在检查 Colab 笔记本并更改为分类交叉熵时,您似乎没有对数据进行规范化。因为像素值最初是无符号的 8 位整数,所以当您创建训练集时,它会将值提升为浮点数,但由于数据的动态范围,您的神经网络很难学习正确的权重。当您尝试更新权重时,梯度非常小,以至于基本上没有更新,因此您的网络就像随机机会一样运行。解决方案是在继续之前将您的训练和测试数据集简单地除以 255:

X_train /= 255.0
X_test /= 255.0

这将转换您的数据,以便动态范围从[0,255][0,1]。由于动态范围较小,您的模型训练时间会更容易,这应该有助于梯度传播,并且不会因为标准化之前的较大规模而消失。由于您的原始模型规范具有大量密集层,因此由于数据的动态范围,梯度更新很可能会消失,这就是最初性能不佳的原因。

当我运行你的笔记本时,我得到了 37% 的准确率。这对于 CIFAR-10 来说并不意外,而且只是一个全连接/密集网络。此外,当您现在运行笔记本时,错误示例的准确性和比例匹配。

如果你想提高准确性,我有几个建议:

  1. 实际上包括颜色信息。CIFAR-10 中的每个对象都有不同的颜色配置文件,应该有助于区分
  2. 添加卷积层。我不确定您的学习进度,但卷积层有助于学习和提取图像中的正确特征,以便将最佳特征呈现给密集层,以便对这些特征进行分类提高准确性。现在您正在对原始像素进行分类,考虑到它们可能有多大的噪声,或者由于事物可以得到多么不受约束(旋转、平移、倾斜、缩放等),这是不可取的。

推荐阅读