当使用cross_val_predict与cross_val_score时,sklearn的cv分数是不同的。

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

我预计这两种方法返回的错误比较相似,谁能给我指出错误的地方?

计算RMSE...

rf = RandomForestRegressor(random_state=555, n_estimators=100, max_depth=8)
rf_preds = cross_val_predict(rf, train_, targets, cv=7, n_jobs=7) 
print("RMSE Score using cv preds: {:0.5f}".format(metrics.mean_squared_error(targets, rf_preds, squared=False)))

scores = cross_val_score(rf, train_, targets, cv=7, scoring='neg_root_mean_squared_error', n_jobs=7)
print("RMSE Score using cv_score: {:0.5f}".format(scores.mean() * -1))

RMSE Score using cv preds: 0.01658
RMSE Score using cv_score: 0.01073
python machine-learning scikit-learn cross-validation
1个回答
1
投票

这里有两个问题,这两个问题在以下文档中都有提到 cross_val_predict:

结果可能不同 cross_validatecross_val_score 除非所有的测试集都有相同的大小,并且度量在样本上分解。

首先是在两种情况下使所有的集(训练集和测试集)都是相同的,而你的例子中并不是这种情况。要做到这一点,我们需要采用 kfold 方法来定义我们的CV折线,然后在两种情况下使用相同的折线。下面是一个使用假数据的例子。

from sklearn.datasets import make_regression
from sklearn.model_selection import KFold, cross_val_score, cross_val_predict
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error

X, y = make_regression(n_samples=2000, n_features=4, n_informative=2,
                      random_state=42, shuffle=False)

rf = RandomForestRegressor(max_depth=2, random_state=0)
kf = KFold(n_splits=5)

rf_preds = cross_val_predict(rf, X, y, cv=kf, n_jobs=5) 
print("RMSE Score using cv preds: {:0.5f}".format(mean_squared_error(y, rf_preds, squared=False)))

scores = cross_val_score(rf, X, y, cv=kf, scoring='neg_root_mean_squared_error', n_jobs=5)
print("RMSE Score using cv_score: {:0.5f}".format(scores.mean() * -1))

上面的代码片段的结果(完全可重现,因为我们已经明确地设置了所有必要的随机种子)是:

RMSE Score using cv preds: 15.16839
RMSE Score using cv_score: 15.16031

所以,我们可以看到,这两个分数确实是相似的,但仍然是: 异曲同工.

为什么会这样呢?答案就在上面引用的句子中相当隐晦的第二部分,即RMSE分数不会对样本进行分解(说实话,我不知道有哪个ML分数会这样)。

简单来说,虽然 cross_val_predict 严格按照其定义计算RMSE,即(伪代码)。

RMSE = square_root([(y[1] - y_pred[1])^2 + (y[2] - y_pred[2])^2 + ... + (y[n] - y_pred[n])^2]/n)

其中 n 是指样本数量,即 cross_val_score 方法并不完全如此;它所做的是计算每个 k CV翻牌,然后平均这些。k 值,即(又是伪代码)。

RMSE = (RMSE[1] + RMSE[2] + ... + RMSE[k])/k

正因为RMSE不能在样本上分解 这两个值虽然很接近,但是 异曲同工.

我们可以通过手动进行CV程序,并模拟RMSE计算来证明事实确实如此。cross_val_score 和上文所述,即。

import numpy as np
RMSE__cv_score = []

for train_index, val_index in kf.split(X):
    rf.fit(X[train_index], y[train_index])
    pred = rf.predict(X[val_index])
    err = mean_squared_error(y[val_index], pred, squared=False)
    RMSE__cv_score.append(err)

print("RMSE Score using manual cv_score: {:0.5f}".format(np.mean(RMSE__cv_score)))

结果是:

RMSE Score using manual cv_score: 15.16031

即: 与上述方法返回的结果相同 cross_val_score 以上。

所以,如果我们想成为 准确,事实上,正确的RMSE(即根据其定义精确计算)是由以下方法返回的。cross_val_predict; cross_val_score 返回它的近似值。但在实际操作中,我们经常会发现差别并不是那么大,所以我们也可以使用 cross_val_score 如果比较方便。

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