1 回答

TA貢獻1712條經驗 獲得超3個贊
這里有兩個問題,在文檔中都有提到cross_val_predict
:
結果可能與和 不同
cross_validate
,cross_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 分數)。
簡單來說,whilecross_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方法并沒有完全做到這一點;它所做的是為每個kCV 折疊計算 RMSE,然后對這些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如果方便的話我們也可以使用。
添加回答
舉報