【问题标题】:R-squared results of test and validation differ by a huge margin测试和验证的 R 平方结果相差​​很大
【发布时间】:2017-10-05 07:25:58
【问题描述】:

我正在使用神经网络解决 keras 和 tensorflow 的回归问题。数据被拆分,因此 282774 个数据集用于训练,70694 个用于验证,88367 个用于测试。为了评估我的模型,我打印出均方误差 (MSE)、平均绝对误差 (MAE) 和 R 方分数。以下是我得到的结果中的一些示例:

               MSE           MAE             R-squared
Training       1.562072899   0.958128839     0.849787137
Validation     0.687871457   0.62066941      0.935365564
Test           0.683918759   0.618674863   -16.22829222

我不了解测试数据的 R 平方值。我知道 R-squared 可以是负数,但是如果两者都属于看不见的数据类别,那么验证和测试之间怎么会有如此大的差异。谁能给我一个提示?

一些背景信息:

由于 keras 没有内置 R 平方度量,因此我使用在网络上找到的一些代码实现了它,这对我来说似乎是合乎逻辑的:

def r2_keras(y_true, y_pred):
    SS_res =  K.sum(K.square(y_true - y_pred)) 
    SS_tot = K.sum(K.square(y_true - K.mean(y_true))) 
    return ( 1 - SS_res/(SS_tot + K.epsilon()) )

如果有帮助:这是我的模型:

model = Sequential()
model.add(Dense(75, input_shape=(7,)))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(Dropout(0.5))

model.add(Dense(1, activation='linear'))

adam = optimizers.Adam(lr=0.001)
model.compile(loss='mse',
              optimizer=adam,
              metrics=['mse', 'mae', r2_keras])

history = model.fit(x_train, y_train,
                    epochs=50,
                    batch_size=32,
                    validation_split=0.2)


score = model.evaluate(x_test, y_test, batch_size=32)

我注意到的一件奇怪的事情是,似乎并未考虑所有测试数据。控制台打印出以下内容:

86304/88367 [============================>.] - ETA: 0s-----

也许这会导致 R 平方计算错误?

感谢任何帮助/提示我可以理解这个问题。

更新: 我检查了异常值,但找不到任何重要的异常值。考虑到标准偏差,测试和训练的最小值和最大值很接近。直方图看起来也非常相似。

所以在下一步中,我让我的模型再次预测测试数据的值,并使用 pandas + numpy 来计算 r2_score。这次我得到了一个大约等于 r2_score 的值来进行验证。

以下是我的做法。您是否发现我执行计算的方式有任何缺陷? (我只是想确定“测试”的旧 r2_score 确实是一个计算错误)

# "test" is a dataframe with input data and the real outputs
# "inputs" is a list of the input column names
# The real/true outputs are contained in the column "output"
test['output_pred'] = model.predict(x=np.array(test[inputs]))
output_mean = test['output'].mean()    # Is this the correct mean value for r2 here?
test['SSres'] = np.square(test['output']-test['output_pred'])
test['SStot'] = np.square(test['output']-output_mean)
r2 = 1-(test['SSres'].sum()/(test['SStot'].sum()))

【问题讨论】:

  • 可能是数据问题(例如您当前测试数据中的异常值)? (尝试切换您的测试和验证数据,看看是否看到相同的效果)
  • 感谢您的意见,很抱歉回复晚了。我检查了异常值并进一步调查(请参阅原始帖子中的更新)。
  • 我遇到了同样的问题。样本内 r2 为 0.43,但 val_r2 很大(负 5 亿)。

标签: python machine-learning tensorflow neural-network keras


【解决方案1】:

Tensorflow 的内置评估方法会逐批评估您的测试集,从而计算每批的 r2。然后,从 model.evaluate() 产生的指标是每批所有 r2 的简单平均值。在 model.fit() 中,r2(以及验证集上的所有指标)是按时期计算的(而不是按批次计算,然后取平均值。)

您可以将您的输出和 output_pred 分成与您在 model.evaluate() 中使用的批次大小相同的批次,并计算每个批次的 r2。我猜该模型在总平方和 (SS_tot) 较高的批次上产生较高的 r2,而在较低的批次上产生较差的 r2。所以当取平均值时,结果会很差(但是在整个数据集上计算 r2 时,具有较高 ss_tot 的样本通常会占主导地位)。

【讨论】:

    猜你喜欢
    • 2018-07-20
    • 2020-12-16
    • 1970-01-01
    • 2019-07-09
    • 2018-11-08
    • 2017-06-22
    • 1970-01-01
    • 2020-02-13
    • 2021-09-26
    相关资源
    最近更新 更多