自定义RMSE和使用内置Keras MSE计算相同预测结果的平方根不一致

9

我已经定义了一个自定义的RMSE函数:

def rmse(y_pred, y_true):
    return K.sqrt(K.mean(K.square(y_pred - y_true)))

我正在将其与Keras提供的均方误差进行比较:
keras.losses.mean_squared_error(y_true, y_pred)
对于某些(相同的)预测,我得到的MSE和RMSE指标值分别为:
mse:115.7218 - rmse: 8.0966
现在,当我将MSE开方时,得到了10.7574,显然比自定义的RMSE函数输出的要高。我还没有找出其中的原因,也没有找到任何相关的帖子。RMSE函数中可能有错误吗?还是与Keras如何定义mse函数中的axis=-1有关(我还没有完全理解它的作用)?
这是我调用RMSE和MSE的地方:
model.compile(loss="mae", optimizer="adam", metrics=["mse", rmse])
所以我期望MSE的平方根与RMSE相同。
我最初在Cross Validated上问了这个问题,但被认为是不相关的。

你的结果 mse: 115.7218 - rmse: 8.0966 是从哪里来的?是从 model.evaluate 还是 model.fit 还是其他地方?请提供尽可能多的信息。 - meowongac
这些是模型.fit在一个epoch完成后的验证结果。以下是一些预测的模型.evaluate结果:mse 60.0054 - rmse 6.8625。MSE的平方根为7.7463 - mka
问题,为什么应该是相同的? - PV8
你是怎么做这个比较的?也许发一下代码会有助于找出问题。 - Manoj Mohan
@mka,你能解决这个问题吗? - alan.elkin
2个回答

6
在RMSE损失函数中,我可能看不到错误吗?或者这与Keras如何定义MSE损失函数中的axis =-1有关(其目的我尚未完全理解)?
当Keras执行损失计算时,批次维度被保留,这是axis =-1的原因。返回值是张量。这是因为每个样本的损失在取平均之前可能需要加权,这取决于是否传递了fit()方法中的某些参数,例如sample_weight
我使用两种方法得到相同的结果。
from tensorflow import keras
import numpy as np
from keras import backend as K

def rmse(y_pred, y_true):
    return K.sqrt(K.mean(K.square(y_pred - y_true)))

l1 = keras.layers.Input(shape=(32))
l2 = keras.layers.Dense(10)(l1)
model = keras.Model(inputs=l1, outputs=l2)

train_examples = np.random.randn(5,32)
train_labels=np.random.randn(5,10)

MSE方法

model.compile(loss='mse', optimizer='adam')
model.evaluate(train_examples, train_labels)

RMSE方法

model.compile(loss=rmse, optimizer='adam')
model.evaluate(train_examples, train_labels)

输出

5/5 [==============================] - 0s 8ms/sample - loss: 1.9011
5/5 [==============================] - 0s 2ms/sample - loss: 1.3788

sqrt(1.9011) = 1.3788


0

虽然像Manoj的回答所示,对于简单的模型配置,sqrt(mse)等于rmse,但我在复杂的模型配置中遇到了这个问题,并且无法弄清楚为什么会发生。不过,如果有人非常需要将rmse作为指标来监控,但在问题中遇到了相同的问题,我已经找到了一个解决方法。我在callbacks中使用了LambdaCallback来打印每个epoch后的训练和验证rmse,并且它起作用了:

def rmse(y_true, y_pred):
    return K.sqrt(K.mean(K.square(y_true - y_pred)))

rmse_print_callback = keras.callbacks.LambdaCallback(on_epoch_end=lambda epoch,logs: 
                 print(f"rmse: {rmse(training_labels, model.predict(training_data)):.4f} - val_rmse: {rmse(validation_labels, model.predict(validation_data)):.4f}"))

model.fit(training_data, training_labels, epochs= 100, callbacks=[rmse_print_callback])

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接