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

时间:2019-06-02 17:35:48

标签: python machine-learning keras neural-network artificial-intelligence

我正在学习神经网络,目前正在使用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个时元时,我的准确性为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 个答案:

答案 0 :(得分:2)

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

当您显示准确性指标时,它实际上会误导您,因为它显示了 binary 分类性能。解决方案是通过选择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. 添加卷积层。我不确定您在学习中的位置,但是卷积层有助于学习和提取图像中的正确特征,以便将最佳特征呈现给密集层,以便对这些特征进行分类以提高准确性。现在,您正在对原始像素进行分类,考虑到它们的噪声水平或由于不受限制的事物(旋转,平移,偏斜,缩放等)的获取,建议不要对原始像素进行分类。