如何在Keras中使用model.predict()再现model.evaluate()输出

时间:2019-12-10 08:29:54

标签: python keras

我有一个Keras模型,最后一行是:

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

在训练过程之后,我想在另一个代码中加载评估模型。我正在使用以下方法生成预测和基本事实:

y_predict = model.predict_generator(generator = testing_generator, steps=steps,verbose=0)
y_true = np.asarray(feature_extractor.classes, dtype='float32')
print('predicted {} samples with {} classes'.format(y_predict.shape[0],y_predict.shape[1]))            
        #Calculate score and error
acc = keras.metrics.binary_accuracy(y_true, y_predict)
err = keras.losses.categorical_crossentropy(tf.convert_to_tensor(y_true, np.float32), tf.convert_to_tensor(y_predict, np.float32))
sess = tf.InteractiveSession() 
acc_now = np.mean(acc.eval())
err_now = np.mean(err.eval())
sess.close()
print('Acc and Err from model.predict: {},{}'.format(acc_now,err_now))
print('Model.evaluate output: {}'.format(model.evaluate_generator(generator = testing_generator, steps=steps,verbose=0)))

然后,我希望评估准确性,错误率和混淆矩阵。我使用predict而不是evaluate的原因是,我将能够产生混淆矩阵。否则,我将不得不同时使用这两者,这在计算上是昂贵的。

问题是,我得到了不同的值:

  

模型中的Acc和Err预测:0.8237550854682922,12.75771713256836

     

Model.evaluate输出:[13.05123828162994,0.10646823157343649]

精度从我的方法中的0.82下降到模型评估输出中的0.1。我是否根据需要转换model.predict()输出?如何使用model.predict()的结果进行模型评估?

我还遵循了this github issue,并尝试了设置m=Model(x,x)的解决方案。 y_predicty_true的形状和类型相同。而且这种方法仍然产生:

  

来自m.e的分数评估:[12.757719990861846,0.11333714980412431]

使用示例代码:

        x = Input(y_predict.shape[1:])
        m = Model(x, x)
        m.compile(loss='categorical_crossentropy', metrics=['accuracy'], optimizer='adam')
        scores = m.evaluate(y_predict, y_true, batch_size=256, verbose=0) 
        print('Scores from m.evaluate: {}'.format(scores))

这里,尽管与evaluate()输出和它与predict()部分相同的误差仍然有所不同,但准确性仍然很低。


添加模型定义:

num_rows = data_in[-2]
num_columns = data_in[-1]
num_channels = data_in[-3]
num_labels = data_out[-1]


# Construct model     
model = Sequential()
for i in range(cnn_size):
    model.add(Conv2D(filters=2**(i)*16, kernel_size=kernel_size, input_shape=(num_channels, num_rows, num_columns), activation='relu'))
    model.add(MaxPooling2D(pool_size=pool_size))
    model.add(Dropout(dropout_rate))
model.add(GlobalAveragePooling2D())
model.add(Dense(num_labels, activation='softmax'))
model.compile(loss='categorical_crossentropy', metrics=['accuracy'], optimizer='adam')

data_in = (1, 40, 180)data_out = (1, 10)

B.T.W我知道我可以为这些统计信息实现自己的numpy解决方案,但我想使用与Keras相同的功能来避免实现方面的变化。

2 个答案:

答案 0 :(得分:1)

如果您使用的是'softmax''categorical_crossentropy'的经典分类问题,则可能需要计算分类精度,而不是二进制精度。

对于这种情况,y_true是一键编码的(这似乎是您的情况,因为您使用的是'categorical_crossentropy'):

keras.metrics.categorical_accuracy(y_true, y_pred)

对于y_true是数字标签(整数)的情况:

keras.metrics.sparse_categorical_accuracy(y_true, y_pred)    

您还可以使用以下方法自行计算准确性:

trueLabels = np.argmax(y_true_numpy, axis=-1) #this line only if y_true is one-hot
predLabels = np.argmax(y_pred_numpy, axis=-1)    
acc = np.mean(trueLabels == predLabels)

关于损失,我认为您正在倒退结果。评估损失应为13.05...。您计算得出的损失接近它:12.75...

现在,如果看似正确的两种不同方法产生的结果相同,我怀疑evaluate给出的更大结果可能来自模型中的额外损失。 Keras评估总结了模型中的所有损失,包括权重调整,损失权重,手动添加的损失等。

我们需要查看您的整个模型,以检测为什么这里有差异。


关于损失,给出模型定义:

似乎没有任何会影响损失的东西,其结果确实是正确的。

在这种情况下,可能还有其他两件事导致差异:

  • testing_generatorfeature_extractor可能无法完全相同
    • 除了可能的错误外,您可能还会迭代同一生成器两次,并且如果生成器是yield类型,则Keras队列可能会使它第二次不在同一点启动您使用生成器
  • 您的Keras版本存在错误(或某些不在代码中的配置已更改)并且Dropouts在评估期间生效的可能性很小。
    • 一项快速检查是多次执行evaluate以查看结果是否完全相同

答案 1 :(得分:0)

我建议您看一下这篇文章。它是用德语编写的,但是代码中的所有注释及其随附的说明都是英语,因此应该没有问题。他也有类似的方法,但指令清晰。只需向下滚动到“ Fehleranalyse”部分。

https://www.mt-ag.com/so-entwirft-man-ein-top-cnn/