当前位置: 首页 > 知识库问答 >
问题:

tf.keras预测是坏的而评估是好的

燕禄
2023-03-14

我正在tf中编程一个模型。keras和运行模型。训练集上的evaluate()通常会产生约96%的准确率。我对测试集的评估通常很接近,大约93%。然而,当我手动预测时,模型通常不准确。这是我的代码:

import tensorflow as tf
from tensorflow.keras import layers
import numpy as np
import pandas as pd

!git clone https://github.com/DanorRon/data
%cd data
!ls

batch_size = 100
epochs = 15
alpha = 0.001
lambda_ = 0.001
h1 = 50

train = pd.read_csv('/content/data/mnist_train.csv.zip')
test = pd.read_csv('/content/data/mnist_test.csv.zip')

train = train.loc['1':'5000', :]
test = test.loc['1':'2000', :]

train = train.sample(frac=1).reset_index(drop=True)
test = test.sample(frac=1).reset_index(drop=True)

x_train = train.loc[:, '1x1':'28x28']
y_train = train.loc[:, 'label']

x_test = test.loc[:, '1x1':'28x28']
y_test = test.loc[:, 'label']

x_train = x_train.values
y_train = y_train.values

x_test = x_test.values
y_test = y_test.values

nb_classes = 10
targets = y_train.reshape(-1)
y_train_onehot = np.eye(nb_classes)[targets]

nb_classes = 10
targets = y_test.reshape(-1)
y_test_onehot = np.eye(nb_classes)[targets]

model = tf.keras.Sequential()
model.add(layers.Dense(784, input_shape=(784,), kernel_initializer='random_uniform', bias_initializer='zeros'))
model.add(layers.Dense(h1, activation='relu', kernel_regularizer=tf.keras.regularizers.l2(lambda_), kernel_initializer='random_uniform', bias_initializer='zeros'))
model.add(layers.Dense(10, activation='softmax', kernel_regularizer=tf.keras.regularizers.l2(lambda_), kernel_initializer='random_uniform', bias_initializer='zeros'))

model.compile(optimizer='SGD',
             loss = 'mse',
             metrics = ['categorical_accuracy'])

model.fit(x_train, y_train_onehot, epochs=epochs, batch_size=batch_size)

model.evaluate(x_test, y_test_onehot, batch_size=batch_size)

prediction = model.predict_classes(x_test)
print(prediction)

print(y_test[1:])

我听说很多时候人们都有这个问题,那只是数据输入的问题。但我看不出这有什么问题,因为它几乎总是错误地预测(如果它是随机的,大约和你预期的一样多)。如何解决此问题?

编辑:以下是具体结果:

最后一个训练步骤:

Epoch 15/15
49999/49999 [==============================] - 3s 70us/sample - loss: 0.0309 - categorical_accuracy: 0.9615

评估输出:

2000/2000 [==============================] - 0s 54us/sample - loss: 0.0352 - categorical_accuracy: 0.9310
[0.03524150168523192, 0.931]

模型的输出。predict\u类:

[9 9 0 ... 5 0 5]

打印输出(y\U测试):

[9 0 0 7 6 8 5 1 3 2 4 1 4 5 8 4 9 2 4]

共有1个答案

拓拔安邦
2023-03-14

首先,您的损失函数是错误的:您处于多类分类设置中,并且您使用的是适合回归而不是分类(MSE)的损失函数。

将模型编译更改为:

model.compile(loss='categorical_crossentropy',
              optimizer='SGD',
              metrics=['accuracy'])

请参见Keras MNIST MLP示例以获取佐证,并在损失为均方误差(MSE)时,在定义Keras准确性的函数中给出自己的答案?有关更多详细信息(尽管这里实际上存在反问题,即分类设置中的回归损失)。

此外,不清楚您使用的MNIST变体是否已经规范化;如果没有,您应该自己规范化它们:

x_train = x_train.values/255
x_test = x_test.values/255

也不清楚为什么你要求一个784单元的层,因为这实际上是NN的第二层(第一层由input_shape参数隐式设置-请参阅Keras Sequential模型输入层),它当然不需要为您的784输入特性中的每一个包含一个单元。

更新(评论后):

但为什么MSE对于分类毫无意义?

这是一个理论问题,不完全适合SO;粗略地说,这与我们不使用线性回归进行分类的原因相同——我们使用逻辑回归,两种方法之间的实际区别正是函数损失。Andrew Ng在Coursera广受欢迎的机器学习课程中很好地解释了这一点——参见他的第6.1讲——逻辑回归|YouTube分类(解释从大约3:00开始),以及第4.2节为什么不使用线性回归[进行分类]?(强烈推荐并免费提供)教科书Hastie、Tibshirani和同事的《统计学习导论》。

MSE确实提供了很高的精度,为什么这不重要呢?

如今,几乎任何你扔给MNIST的东西都会“起作用”,这当然既不能使它正确,也不能成为要求更高的数据集的好方法。。。

更新2:

每当我使用交叉熵运行时,准确率只是在10%左右摆动

抱歉,无法复制该行为。。。以Keras MNIST MLP为例,使用您模型的简化版本,即:

model = Sequential()
model.add(Dense(784, activation='linear', input_shape=(784,)))
model.add(Dense(50, activation='relu'))
model.add(Dense(num_classes, activation='softmax'))

model.compile(loss='categorical_crossentropy',
              optimizer=SGD(),
              metrics=['accuracy'])

仅经过5个阶段,我们就很容易获得约92%的验证准确率:

history = model.fit(x_train, y_train,
                    batch_size=128,
                    epochs=5,
                    verbose=1,
                    validation_data=(x_test, y_test))

Train on 60000 samples, validate on 10000 samples
Epoch 1/10
60000/60000 [==============================] - 4s - loss: 0.8974 - acc: 0.7801 - val_loss: 0.4650 - val_acc: 0.8823
Epoch 2/10
60000/60000 [==============================] - 4s - loss: 0.4236 - acc: 0.8868 - val_loss: 0.3582 - val_acc: 0.9034
Epoch 3/10
60000/60000 [==============================] - 4s - loss: 0.3572 - acc: 0.9009 - val_loss: 0.3228 - val_acc: 0.9099
Epoch 4/10
60000/60000 [==============================] - 4s - loss: 0.3263 - acc: 0.9082 - val_loss: 0.3024 - val_acc: 0.9156
Epoch 5/10
60000/60000 [==============================] - 4s - loss: 0.3061 - acc: 0.9132 - val_loss: 0.2845 - val_acc: 0.9196

请注意第一个密集层的激活='linear',这相当于不指定任何内容,就像在您的情况下一样(正如我所说,实际上您向MNIST抛出的所有内容都将“起作用”)。。。

最后建议:尝试将模型修改为:

model = tf.keras.Sequential()
model.add(layers.Dense(784, activation = 'relu',input_shape=(784,)))
model.add(layers.Dense(h1, activation='relu'))
model.add(layers.Dense(10, activation='softmax'))

为了使用更好的(也是默认的)“glorot\u uniform”初始值设定项,并删除kernel\u正则化器参数(它们可能是任何问题的原因-始终从简单开始!)。。。

 类似资料:
  • 我理解经典例子的问题 但我无法说服自己以下是有效的还是无效的 我知道'foo(i)'和'i'的求值顺序是不确定的,但是'评估'到底是什么意思?也就是说bar的第二个参数总是42,或者'i'的当前值可以在foo改变它之前被传入吗?

  • 校验者: @飓风 @小瑶 @FAME @v 翻译者: @小瑶 @片刻 @那伊抹微笑 有 3 种不同的 API 用于评估模型预测的质量: Estimator score method(估计器得分的方法): Estimators(估计器)有一个 score(得分) 方法,为其解决的问题提供了默认的 evaluation criterion (评估标准)。 在这个页面上没有相关讨论,但是在每个 esti

  • 问题内容: 我知道Java在这种情况下具有智能/惰性评估: 但是关于: 即使返回true 也被调用? 问题答案: 在Java(和其他类似C的语言)中,这称为 短路评估 。* 是的,在第二个示例中总是被调用。也就是说,除非编译器/ JVM可以确定它没有可观察到的副作用,否则在这种情况下它可以选择进行优化,但是无论如何您都不会注意到它们之间的差异。 两者截然不同; 前者本质上是一种优化技术,而第二种则

  • 本文向大家介绍接口测试质量评估标准是什么?相关面试题,主要包含被问及接口测试质量评估标准是什么?时的应答技巧和注意事项,需要的朋友参考一下 接口表现与接口文档的一致性 请求参数:必选和非必选、长度、字符类型、为空、缺失、组合、重复 返回数据:正常和异常

  • 问题内容: 我想知道JavaScript是否具有C#中的&&运算符之类的“短路”评估。如果没有,我想知道是否有一种合理的解决方法可以采用。 问题答案: 是的,JavaScript具有“短路”评估。

  • 问题内容: 给出以下代码: 如果返回,php解释器是否还会检查以后的条件,例如? 如果是这样,那么为什么它在不需要时会做额外的工作呢? 问题答案: 是的,PHP解释器是“惰性”的,这意味着它将尽可能少地进行比较以评估条件。 如果要验证,请尝试以下操作: