使用 model.evaluate 和 model.predict 评估测试数据上的模型性能时的不同结果

问题描述 投票:0回答:1

我对 Keras 中的 model.evaluate() 和 model.predict() 函数有疑问。我在 Keras 中构建了一个简单的 LSTM 模型,并想在测试数据集上测试模型性能。我考虑了以下两种方法来计算测试数据集的指标:

  • 使用 model.evaluate() 方法
  • 使用 model.predict() 方法获取拟合值并手动计算指标

然而,我最终得到了不同的结果。此外,model.evaluate() 方法的结果还取决于batch_size 参数的值。根据我的理解和这篇post,他们应该有相同的结果。这是可以复制结果的代码:

import tensorflow as tf
from keras.models import Model
from keras.layers import Dense, LSTM, Activation, Input
import numpy as np
from tqdm.notebook import tqdm
import keras.backend as K
from keras.callbacks import ModelCheckpoint, EarlyStopping

class VLSTM:
    def __init__(self, input_shape=(6, 1), nb_output_units=1, nb_hidden_units=128, dropout=0.0, 
                 recurrent_dropout=0.0, nb_layers=1):
        self.input_shape = input_shape
        self.nb_output_units = nb_output_units
        self.nb_hidden_units = nb_hidden_units
        self.nb_layers = nb_layers
        self.dropout = dropout
        self.recurrent_dropout = recurrent_dropout

    def build(self):
        inputs = Input(shape=self.input_shape)
        outputs = LSTM(self.nb_hidden_units)(inputs)
        outputs = Dense(1, activation=None)(outputs)
        return Model(inputs=[inputs], outputs=[outputs])
    
def RMSE(output, target):
    return K.sqrt(K.mean((output - target) ** 2))

n_train = 500
n_val = 100
n_test = 250 

X_train = np.random.rand(n_train, 6, 1)
Y_train = np.random.rand(n_train, 1)
X_val = np.random.rand(n_val, 6, 1)
Y_val = np.random.rand(n_val, 1)
X_test = np.random.rand(n_test, 6, 1)
Y_test = np.random.rand(n_test, 1)

input_shape = (X_train.shape[1], X_train.shape[2])
model = VLSTM(input_shape=input_shape)
m = model.build()
m.compile(loss=RMSE,
              optimizer='adam',
              metrics=[RMSE])

callbacks = []
callbacks.append(EarlyStopping(patience=30))


# train model
hist = m.fit(X_train, Y_train, \
             batch_size=32, epochs=10, shuffle=True, \
             validation_data=(X_val, Y_val), callbacks=callbacks)

# Use evaluate method with default batch size
test_mse = m.evaluate(X_test, Y_test)[1]
print("Mse is {} using evaluate method with default batch size".format(test_mse))

# Use evaluate method with batch size 1
test_mse = m.evaluate(X_test, Y_test, batch_size=1)[1]
print("Mse is {} using evaluate method with batch size = 1".format(test_mse))

# Use evaluate method with batch size = n_test
test_mse = m.evaluate(X_test, Y_test, batch_size=n_test)[1]
print("Mse is {} using evaluate method with batch size = n_test".format(test_mse))

# Use pred method and compute RMSE manually
Y_test_pred = m.predict(X_test)
test_mse = np.sqrt( ((Y_test_pred - Y_test) ** 2).mean())
print("Mse is {} using evaluate method with batch size = 1".format(test_mse))

运行代码后,结果如下:

使用默认批量大小的评估方法,Mse 为 0.3068242073059082

使用批量大小 = 1 的评估方法,Mse 为 0.26647186279296875

使用批量大小 = n_test 的评估方法,Mse 为 0.30763307213783264

使用预测方法,Mse 为 0.3076330596820157

看起来使用 mode.predict() 和 model.evaluate() 且批量大小 = n_test 会给出相同的结果。谁能解释一下吗?预先感谢!

keras neural-network lstm evaluate
1个回答
0
投票

是的,你的猜测是正确的,使用预测计算出的 mse 确实等于使用 batch_size=len(dataset) 进行评估。
这很容易理解,因为当您使用预测计算 mse 时,您没有将数据集分成批次来计算它,您只是一次计算所有。

显然你可以用预测来计算你的mse,也可以像这样分成批次:

Y_test_pred_batches = np.split(Y_test_pred, 5 ,axis=0) #batch_size = 250/5=50 
Y_test_batches = np.split(Y_test, 5 ,axis=0)
batch_rmss = []
for y_pred, y_true in zip(Y_test_pred_batches, Y_test_batches):
    batch_rmss.append(rms(y_pred, y_true))
np.mean(batch_rmss)

其输出为:0.28436336682976376 现在评估:

test_mse = m.evaluate(X_test, Y_test, batch_size=50)[1]
test_mse

其输出为:0.28436335921287537 所以基本上它们是相同的。

如果您尝试使用 np.split(Y_test_pred, 250 ,axis=0) 使批量大小为 1,则我的情况下的输出为 0.24441334738835332。当评估batch_size = 1时,输出为0.244413360953331。所以你可以看到它是一样的。

© www.soinside.com 2019 - 2024. All rights reserved.