Keras 精度和实际精度正好相反

Posted

技术标签:

【中文标题】Keras 精度和实际精度正好相反【英文标题】:Keras accuracy and actual accuracy are exactly reverse of each other 【发布时间】:2019-10-18 10:07:20 【问题描述】:

我正在学习神经网络,目前使用 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.9 或 90% 的准确率。此外,当我使用测试数据集对其进行评估时,我得到了大约的准确度。 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))

【问题讨论】:

这是一个黄金问题,谢谢! 【参考方案1】:

发生这种情况的原因是您使用的损失函数。您正在使用 binary 交叉熵,而您应该使用 categorical 交叉熵作为损失。二进制仅适用于双标签问题,但由于 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% 左右,并且在您的 cmets 中没有提高。检查 Colab 笔记本并更改为分类交叉熵时,您似乎没有对数据进行规范化。因为像素值最初是无符号的 8 位整数,所以当您创建训练集时,它会将值提升为浮点数,但由于数据的动态范围,您的神经网络很难学习正确的权重。当您尝试更新权重时,梯度非常小,基本上没有更新,因此您的网络就像随机机会一样运行。解决方案是在继续之前简单地将训练和测试数据集除以 255:

X_train /= 255.0
X_test /= 255.0

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

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

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

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

【讨论】:

我认为你是对的,我刚刚意识到这一点并在categorical_crossentropy 上对其进行了训练,现在我得到了 10% 的准确率,这与我的计算相符。但是知道为什么精度太低吗? @Kaushal28 请在您的帖子中更新更多信息 - 特别是您如何加载数据集以及如何重塑它以使其适合前馈密集网络。 谢谢!更新了问题。如果代码写得不好,请原谅我,因为这是我第一次尝试训练神经网络和处理数据集。 让我分享我的整个笔记本。 感谢大家的帮助!!

以上是关于Keras 精度和实际精度正好相反的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Keras/tensorflow 的 sigmoid 和交叉熵精度低?

Keras - 验证精度与 LSTM 中的自测精度不匹配?

如何在 Keras 中计算精度和召回率

Keras 精度不变

Keras:微调 Inception 时精度下降

加载相同的保存模型后,Keras 模型精度有所不同