sklearn分层的k折CV,具有ElasticNetCV等线性模型

时间:2019-03-01 12:59:54

标签: python scikit-learn regression cross-validation

将交叉验证(CV)与sklearn一起使用非常简单直接。但是,在线性CV模型(如cv=5ElasticNetCV中设置LassoCV时,默认实现是KFold CV。由于各种原因,我想使用StratifiedKFold。在documentation中,似乎可以使用cv=给出任何 CV方法。

传递cv=KFold(5)可以正常工作,但是cv=StratifiedKFold(5)会引发错误:

  

ValueError:支持的目标类型为:(“二进制”,“多类”)。改为“连续”。

我知道拟合后可以使用cross_val_score,但是我想将StratifiedKFold作为CV直接传递给线性模型。

我的最低工作示例是:

from sklearn.linear_model import ElasticNetCV
from sklearn.model_selection import KFold, StratifiedKFold
import numpy as np

x = np.arange(100, dtype=np.float64).reshape(-1, 1)
y = np.arange(100) + np.random.rand(100)

# KFold default implementation:
model_default = ElasticNetCV(cv=5)
model_default.fit(x, y)  # works fine
# KFold given as cv explicitly:
model_kfexp = ElasticNetCV(cv=KFold(5))
model_kfexp.fit(x, y)  # also works fine

# StratifiedKFold given as cv explicitly:
model_skf = ElasticNetCV(cv=StratifiedKFold(5))
model_skf.fit(x, y)  # THIS RAISES THE ERROR

您知道如何直接将StratifiedKFold设置为简历吗?

1 个答案:

答案 0 :(得分:1)

问题的根源是这一行:

y = np.arange(100) + np.random.rand(100)

StratifiedKFold无法从连续分布中进行采样,因此会出错。尝试更改此行,您的代码将愉快地执行:

from sklearn.linear_model import ElasticNetCV
from sklearn.model_selection import KFold, StratifiedKFold
import numpy as np

x = np.arange(100, dtype=np.float64).reshape(-1, 1)
y = np.random.choice([0,1], size=100)

# KFold default implementation:
model_default = ElasticNetCV(cv=5)
model_default.fit(x, y)  # works fine
# KFold given as cv explicitly:
model_kfexp = ElasticNetCV(cv=KFold(5))
model_kfexp.fit(x, y)  # also works fine

# StratifiedKFold given as cv explicitly:
model_skf = ElasticNetCV(cv=StratifiedKFold(5))
model_skf.fit(x, y)  # no ERROR

注意

如果您对连续数据进行采样,请使用KFold。如果您的目标是绝对目标,则可以同时使用KFoldStratifiedKFold中的任意一个。

注意2

如果您坚持对连续数据进行 模拟 分层抽样,则可能希望对数据应用pandas.cut,然后对该数据进行分层抽样,最后将生成的(train_id, test_id)生成器传递给cv param:

x = np.arange(100, dtype=np.float64).reshape(-1, 1)
y = np.arange(100) + np.random.rand(100)

y_cat = pd.cut(y, 10, labels=range(10))
skf_gen = StratifiedKFold(5).split(x, y_cat)

model_skf = ElasticNetCV(cv=skf_gen)
model_skf.fit(x, y)  # no ERROR