我正在tf.keras中编程一个模型,然后在训练集上运行model.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]
model.predict_classes的输出:
[9 9 0 ... 5 0 5]
print(y_test)的输出:
[9 0 0 7 6 8 5 1 3 2 4 1 4 5 8 4 9 2 4]
答案 0 :(得分:1)
首先,损失函数是错误的:您处于多类分类设置中,并且正在使用适合于回归而非分类(MSE)的损失函数。
将模型编译更改为:
model.compile(loss='categorical_crossentropy',
optimizer='SGD',
metrics=['accuracy'])
有关更多信息,请参见Keras MNIST MLP example,并在What function defines accuracy in Keras when the loss is mean squared error (MSE)?中提供答案以获取更多详细信息(尽管这里实际上存在反问题,即分类设置中的回归损失)。
此外,尚不清楚您使用的MNIST变体是否已标准化;如果没有,您应该自己对它们进行标准化:
x_train = x_train.values/255
x_test = x_test.values/255
也不清楚为什么要使用784个单位的图层,因为这实际上是NN的 second 图层(第一个图层由input_shape
参数隐式设置-请参阅Keras Sequential model input layer),并且您的784种输入功能中的每一项功能肯定不需要包含一个单元。
更新(在评论后):
但是,为什么MSE对于分类没有意义?
这是一个理论问题,并不完全适合SO。粗略地说,由于同样的原因,我们不使用线性回归进行分类-我们使用 logistic 回归,这两种方法之间的实际差异恰恰是损失函数。 Ng的安德鲁·伍(Andrew Ng)在Coursera受欢迎的机器学习课程中对此进行了很好的解释-请参阅他在YouTube上的Lecture 6.1 - Logistic Regression | Classification(解释从〜3:00开始)以及 4.2为什么不线性回归[用于分类(强烈推荐并免费提供)教科书An Introduction to Statistical Learning中的]?。
MSE确实具有很高的准确性,那为什么不重要呢?
如今,您在MNIST上投入的几乎所有 都将“奏效”,这当然既不能使其正确,也不能成为要求更高的数据集的好方法...
更新2 :
每当我使用交叉熵时,精度就会以大约10%的幅度波动
对不起,无法重现该行为...将Keras MNIST MLP example与模型的简化版本结合使用,即:
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
请注意,第一个Dense层的activation='linear'
相当于not specifying anything,就像您的情况一样(正如我所说,实际上,您扔给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'))
为了使用更好的(和default)'glorot_uniform'
初始化程序,并删除kernel_regularizer
args(它们可能是引起任何问题的原因-总是 >从简单开始!)...