为什么手动计算MSE与sklearn中的LassoCV.mse_path不同

时间:2018-02-27 09:05:22

标签: python machine-learning scikit-learn

我正在使用python中的套索,但是有一个让我困惑的问题。 在以下example中,我的代码如下:

kf = KFold(10,random_state=0,shuffle=False)  
model_lassocv = LassoCV(cv=kf).fit(X, y) 

model_lassocv.mse_path_给出数组([[5747.95194531,4590.75732123,...]])。

我手动计算了mse:

from sklearn import linear_model
from sklearn.model_selection import cross_val_predict, cross_val_score
lasso = linear_model.Lasso(alpha = model_lassocv.alphas_[0])
predict = cross_val_predict(lasso, X, y, cv=kf)
metrics.mean_squared_error(y_pred=predict[0:44],y_true=y[0:44]) 
# 0:44 is the first test set according to KFold function
# and result here gives 5625 instead of 5747.95

然而,

cross_val_score(lasso,X,y, cv=kf, scoring="neg_mean_squared_error")

给出与model_lassocv.mse_path_相同的否定结果。

对不起我的误导性问题。我想知道为什么metrics.mean_squared_error会从mse_path_返回不同的结果。如果我没有误解KFold的分区,那么10倍CV中的第一个测试集是0:44。并且,由metrics.mean_squared_error计算的第一个alpha(在我的情况下为2.14804358)的第一个测试集中的交叉验证预测和真值的MSE返回5625,而LassoCV的mse_path_返回5747。

1 个答案:

答案 0 :(得分:0)

原因在于您手动实施拟合模型。 mse_path_属性中的MSE是KFold对象生成的每个折叠的MSE。但是,在您的手动实现中,当您使用cross_val_predict时,您要求sklearn训练具有所有可用折叠的模型,而不是LassoCv实现中使用的特定折叠。我将使用sklearn提供的boston数据集提供正确的解决方案。

from sklearn.model_selection import cross_val_predict, cross_val_score, KFold
from sklearn.linear_model import LassoCV, Lasso
from sklearn.metrics import mean_squared_error
from sklearn.datasets import load_boston

X, y = load_boston(return_X_y=True)
kf = KFold(10, random_state=0, shuffle=False)

现在让我们看看折叠是什么样的:

for train_i, test_i in kf.split(X):
    print(train_i, test_i)

(array([ 51,  52,  53, ... , 505], dtype=int64), array([ 0,  1,  2, ... , 50], dtype=int64)) ... (array([ ... ]))

为简洁起见,我只显示第一个折叠,其中训练集由51到505的索引组成,对于此折叠中的测试集,索引从0到50。

现在让我们使用您的LassoCV方法:

model_lassocv = LassoCV(cv=kf).fit(X, y)
model_lassocv.mse_path_

MSE路径的结果:

  array([[  41.74173819,   29.78409579,   32.00672122,  191.68560655,
           103.46618603,  172.62108062,   16.92365434,  181.06822315,
           116.83656233,   35.92813347], [ ... ], ... ])

同样,为简洁起见,我只显示第一个alpha的所有10个折叠的MSE。根据您的示例,您希望匹配LassoCV中使用的第一个alpha的第一个折叠的MSE,因此在我的情况下,我想手动获得结果= 41.74173819。

现在,我将采用手动实现方式:

  lasso = Lasso(alpha = model_lassocv.alphas_[0])
  lasso.fit(X[51:506], y[51:506])
  predict = lasso.predict(X[0:51])
  mean_squared_error(y_pred=predict, y_true=y[0:51])

主要差异:

  1. 我使用KFold对象确定的第一个折叠的训练集来拟合我的模型(还记得我说第一次折叠训练的指数是从51-505?)。
  2. 然后我根据第一次折叠的测试集生成我的预测。 (此处,测试集的索引是0-50)
  3. 我手动计算的结果?

    41.741738189299873

    因此,我们有一场比赛。